2009-10-01 1 views
8

Ho pensato che sarebbe stato utile essere in grado di fare una cosa del genere, ad esempio, per verificare i parametri per riferimenti null e alla fine lanciare un'eccezione.
Ciò farebbe risparmiare un po 'di digitazione e inoltre renderebbe impossibile dimenticare di aggiungere un controllo se viene aggiunto un nuovo parametro.È possibile iterare attraverso i parametri del metodo in C#?

risposta

15

Beh, a meno che non si contano:

public void Foo(string x, object y, Stream z, int a) 
{ 
    CheckNotNull(x, y, z); 
    ... 
} 

public static void CheckNotNull(params object[] values) 
{ 
    foreach (object x in values) 
    { 
     if (x == null) 
     { 
      throw new ArgumentNullException(); 
     } 
    } 
} 

Per evitare il colpo creazione dell'array, si potrebbe avere un certo numero di sovraccarichi per un diverso numero di argomenti:

public static void CheckNotNull(object x, object y) 
{ 
    if (x == null || y == null) 
    { 
     throw new ArgumentNullException(); 
    } 
} 

// etc 

Un'alternativa sarebbe quella di utilizzare gli attributi per dichiarare che i parametri non devono essere nulli e ottenere PostSharp per generare i controlli appropriati:

public void Foo([NotNull] string x, [NotNull] object y, 
       [NotNull] Stream z, int a) 
{ 
    // PostSharp would inject the code here. 
} 

Certo, probabilmente vorrei che PostSharp lo converta in chiamate Code Contracts, ma non so quanto bene i due suonino insieme. Forse un giorno saremo in grado di scrivere la SpeC# -come:

public void Foo(string! x, object! y, Stream! z, int a) 
{ 
    // Compiler would generate Code Contracts calls here 
} 

... ma non nel prossimo futuro :)

+0

Nel tuo caso per quanto riguarda CheckNotNull ((oggetto []) null)? :-) –

+1

Pensa che l'autore abbia significato qualcosa come la parola chiave argomenti di javascript. Per esempio. elenca tutti gli argomenti nel metodo "Foo (stringa x, oggetto y, Stream z, int a)" e li test per null senza specificare ognuno di essi, ma chiama ad alcuni metodi generici come "ValidateArgs (Foo.arguments);" . – Kamarey

+0

@Dzmitry: Beh, sì, questo non è ancora pronto per la produzione :) –

0

E 'possibile scorrere i parametri che sono stati dichiarati per un metodo (attraverso la riflessione), ma non vedo alcun modo per recuperare il valore di questi parametri per una specifica chiamata di metodo ...

Forse potrebbe utilizzare Postsharp e creare un aspetto in cui eseguire questo controllo. Quindi, al momento della compilazione, Postsharp può "tessere" l'aspetto (iniettare codice aggiuntivo) ad ogni metodo che hai scritto ...

2

È possibile definire parametri metodo con un params parola chiave. Ciò renderà possibile passare un numero variabile di parametri al metodo. È quindi possibile eseguire iterazioni su di essi e verificare la presenza di riferimenti null o qualsiasi altra cosa si desideri.

public void MyMethod(params object[] parameters) { 
    foreach (var p in parameters) { 
     ... 
    } 
} 

// method call: 
this.MyMethod("foo", "bar", 123, null, new MyClass()); 

A mio parere, tuttavia, non è un buon modo di fare le cose. Dovrai controllare manualmente il tipo di parametri, la loro posizione nell'array di input e non potrai utilizzare intellisense per loro in Visual Studio.

0

Probabilmente è possibile automatizzare il controllo dei parametri con una libreria AOP come PostSharp.

1

Ho avuto la stessa domanda qualche tempo fa, ma volevo farlo per scopi di registrazione. Non ho mai trovato una buona soluzione, ma ho trovato questo collegamento per quanto riguarda l'utilizzo di un approccio basato su AOP per le voci del metodo di registrazione e l'uscita. Il nocciolo di esso è necessario utilizzare un framework in grado di leggere la classe e iniettare il codice in fase di esecuzione per fare ciò che si sta tentando di fare. Non sembra facile.

How do I intercept a method call in C#?

0

Dopo aver fornito un esempio banale di un metodo che utilizza la parola chiave params, RaYell dice:

A mio parere però, non è un buon modo di fare le cose. Sarà necessario controllare manualmente il tipo dei parametri , la loro posizione nell'array di input e non sarà possibile utilizzare intellisense per lo in Visual Studio.

certamente d'accordo che dichiarare un metodo che prende due strings, uno int, un object che può essere nullo, e un altro MyClass oggetto utilizzando params è una cattiva idea. Tuttavia, ci sono (a mio parere) applicazioni perfettamente valide e appropriate della parola chiave params, vale a dire quando i parametri sono tutti dello stesso tipo. Per esempio:

public T Max<T>(T x, T y) where T : IComparable<T> { 
    return x.CompareTo(y) > 0 ? x : y; 
} 

public T Max<T>(params T[] values) where T : IComparable<T> { 
    T maxValue = values[0]; 

    for (int i = 1; i < values.Length; i++) { 
     maxValue = Max<T>(maxValue, values[i]); 
    } 

    return maxValue; 
} 
0
var mandatoryFields = (new object[] { input1, input2 }).Where(v => v == null || v.ToString().Trim() == ""); 

otterrete la lista dei parametri nulli.

Allora si può semplicemente aggiungere

if(mandatoryFields.ToArray().Count > 0){}