2012-01-26 17 views
29

Ho un metodo che utilizza la parola chiave params, in questo modo:Perché il passaggio di null a un metodo params genera un array di parametri nullo?

private void ParamsMethod(params string[] args) 
{ 
    // Etc... 
} 

Poi, ho chiamare il metodo utilizzando varie combinazioni di argomenti:

      // Within the method, args is... 
ParamsMethod();    // - a string array with no elements 
ParamsMethod(null);   // - null (Why is this?) 
ParamsMethod((string)null); // - a string array with one element: null 
ParamsMethod(null, null); // - a string array with two elements: null and null 
ParamsMethod("s1");   // - a string array with one element: "s1" 
ParamsMethod("s1", "s2"); // - a string array with two elements: "s1" and "s2" 

capisco tutti i casi, tranne che per il secondo. Qualcuno può spiegare perché ParamsMethod(null) fa sì che args sia null, invece di un array con un elemento nullo?

+0

Ora che conosci la risposta, puoi lavorare su questo puzzle. Hai due metodi, 'void M (object) {}' e 'void M (params object []) {}'. Si chiama 'M (null)'.Quale sovraccarico viene scelto, cosa gli viene passato e perché? –

+2

L'ho già incontrato prima. Penso che sia appena stato ribattezzato uno dei metodi. :) – FishBasketGordo

risposta

29

Un parametro params ha lo scopo di fornire un metodo pratico per specificare i valori: è comunque possibile passare direttamente un riferimento di matrice.

Ora, null è convertibile in string[] o string, quindi entrambe le interpretazioni sono valide: dipende dalle specifiche che è preferibile. Gli stati spec nella sezione 10.6.1.4 che:

  • L'argomento espressa una matrice di parametri può essere una singola espressione che è conversione implicita nel tipo di parametro di matrice. In questo caso, l'array di parametri agisce esattamente come un parametro di valore.

  • alternativa, [...]

In altre parole, i compilatore controlla per vedere se l'argomento è valido come tipo di parametro "normale" prima, e costruisce solamente un array se deve assolutamente.

+4

Inoltre, vale la pena notare che molti metodi che accettano un array di parametri avranno anche overload per (oggetto), (oggetto, oggetto) e (oggetto, oggetto, oggetto) - Questo per evitare il sovraccarico di costruire un array oggetto solo per pochi oggetti, poiché questi sovraccarichi saranno abbinati per primi. –

3

La ragione di ciò è che è possibile passare un array del tipo appropriato a un argomento params. Poiché null può essere convertito in qualsiasi tipo e la sintassi dell'array ha la precedenza, si ottiene null come valore del parametro.

Il casting esplicito a string, ovviamente, lo rende un elemento dell'array piuttosto che l'array stesso.

Si può provare e vedere:

private void DoSomething(params IEnumerable[] arr) { 
    // ... 
} 

... 

DoSomething(new IEnumerable[] {new int[] {}}); // arr[0] isn't IEnumerable[], it's int[]. 

And here's an online demo.

3

Si può passare un array ad un parametro params - in realtà, è preferibile (cioè se si passa un oggetto [] a un metodo che accetta l'oggetto params [], è il parametro intero, non solo il singolo elemento). Null è valido come assegnazione a un array, quindi - vincolo vincolante.

Fondamentalmente, dovrai essere più esplicito.

7

Vedere la specifica C#, sezione 10.6.1.4 matrici parametri:

Matrice parametro permette argomenti da specificare in uno dei due modi in una chiamata di metodo:

  • L'argomento riportati per una matrice di parametri può essere una singola espressione che è implicitamente convertibile (§6.1) al tipo di array di parametri. In questo caso, l'array di parametri agisce esattamente come un parametro di valore.
  • In alternativa, l'invocazione può specificare zero o più argomenti per l'array di parametri, dove ogni argomento è un'espressione che è implicitamente convertibile (§6.1) nel tipo di elemento dell'array di parametri. In questo caso, l'invocazione crea un'istanza del tipo di array di parametri con una lunghezza corrispondente al numero di argomenti, inizializza gli elementi dell'istanza dell'array con i valori di argomento specificati e utilizza l'istanza dell'array appena creata come argomento effettivo.

Da null è convertita in modo implicito string[], sarà utilizzato come matrice.

inoltre:

Quando si esegue la risoluzione di sovraccarico, un metodo con una matrice di parametri può essere applicabile sia nella sua forma normale o nella sua forma espansa (§7.5.3.1). La forma espansa di un metodo è disponibile solo se la forma normale del metodo non è applicabile e solo se un metodo con la stessa firma del modulo espanso non è già dichiarato nello stesso tipo.

che chiarisce che il compilatore effettivamente prima tenta di utilizzare il metodo con un array argomento (forma normale) prima prova utilizzando l'argomento come un array elemento (forma estesa).

2

Dalla descrizione lingua:

Una matrice di parametri permette argomenti da specificare in uno dei due modi in una chiamata di metodo:

  • L'argomento espressa una matrice di parametri può essere un singola espressione che è implicitamente convertibile (§6.1) nel tipo di matrice dei parametri. In questo caso, l'array di parametri agisce esattamente come un parametro di valore.

  • In alternativa, l'invocazione può specificare zero o più argomenti per l'array di parametri, dove ogni argomento è un'espressione che è implicitamente convertibile (§6.1) nel tipo di elemento dell'array di parametri. In questo caso, l'invocazione crea un'istanza del tipo di array di parametri con una lunghezza corrispondente al numero di argomenti, inizializza gli elementi dell'istanza dell'array con i valori di argomento specificati e utilizza l'istanza dell'array appena creata come argomento effettivo.

Dal null in ParamsMethod(null) può essere convertito in modo implicito (string[])null, la prima regola è quella che viene applicata.

Problemi correlati