2010-02-05 16 views
22

salida¿Por qué los parámetros se comportan así?

nula

Código

class Program 
{   
    static void Main(String[] args) 
    { 
     String s = null; 
     PrintLength(s); 
     PrintLength(s, s); 
     PrintLength(null); 
     PrintLength(null, null);  
     Console.ReadKey(); 
    } 

    private static void PrintLength(params String[] items) 
    { 
     Console.WriteLine(items == null ? "null" : items.Length.ToString()); 
    }  
} 

Respuesta

28

Esta es una pregunta bastante frecuente. Para más detalles, consulte la sección 7.4.1 y 7.4.3.1 de la especificación.

En pocas palabras: un método con una matriz params es aplicable ya sea en su "forma normal" o su "forma expandida". Es decir, se puede decir

PrintLength(new string[] {"hello"}); // normal form 
PrintLength("hello"); // expanded form, translated into normal form by compiler. 

Cuando se le dé una llamada que es aplicable en ambas formas , el compilador siempre elige la forma normal sobre la forma expandida.

Supongamos que elegimos la forma expandida cada vez que ambas aplicaban. Supongamos que tiene

void M(params object[] x) {} 

¿Cómo pasaría una matriz nula a esto si siempre elegimos la forma expandida? Eso sería imposible!

Supongamos que usted ha dicho

M(new object[] { "hello" }); 

y siempre eligió la forma expandida. ¿Qué haría esto? Bueno, una matriz de objetos es un objeto, por lo que elegiría la forma expandida: haría otra matriz, envuelva esto en la matriz y pase eso.

La elección de la forma expandida sobre la forma normal conduce a resultados disparatados. Siempre es más sensato elegir la forma normal sobre la forma expandida.

+0

¡Buena información! –

+0

Buen post Eric. Podría agregar que con el primer PrintLength (null), está pasando un valor nulo a la función, mientras que con el segundo ejemplo PrintLength (s) está pasando un puntero de cadena (referencia) que en realidad no hace referencia a nada. Sin embargo, la referencia todavía existe en la memoria con un valor de 0 ya que es un puntero nulo. – regex

+0

Estaba 90% seguro de que este era el caso, pero ese 10% simplemente seguía fastidiándome. – ChaosPandion

4

El PrintLength(null) está pasando una matriz nula donde como PrintLength(null, null) está pasando un string[] con una longitud de dos que contiene dos string objetos nulos. Sería lo mismo que pasa new string[] { null, null }

Hmm leer lo que escribí tal que en realidad no responde a su pregunta encogimiento de hombros.

Editar:

Esta es probablemente la razón: Puede enviar una lista separada por comas de los argumentos del tipo especificado en la declaración de parámetros, o una serie de argumentos del tipo especificado.

http://msdn.microsoft.com/en-us/library/w5zay9db.aspx

+0

Creo que la pregunta es, ¿por qué pasar un solo nulo no pasa el equivalente de una nueva cadena [] {null}? Parece una especie de comportamiento intencionalmente codificado, pero para qué es misterioso. – technophile

+0

Re: editar Por lo tanto, está interpretando el valor nulo como si pasara una cadena [] s = null; Hm. Interesante caso de esquina. – technophile

5

Funciona como fue diseñado, diría:

PrintLength (s);

Usted está pasando en una sola cadena que es nula - dentro de su método, items se no ser nulos - Es una matriz de un elemento - de tipo cadena - de valor null

PrintLength (s, s);

La misma historia aquí - estás pasando en dos elementos, por lo items en su método será una serie de dos cuerdas - ambos de los cuales son nulas a sí mismos, pero la matriz no se

PrintLength (nulo);

Esto, obviamente, obtiene interpretado como un único valor nulo y por lo tanto items es nulo. No está pasando una matriz, ni un elemento de tipo cadena; solo está pasando un valor nulo per se.

PrintLength (null, null);

Eso es nuevo - un conjunto de dos elementos, ambos de los cuales son nulas - pero la matriz per se no es nulo, ya que está pasando en dos valores.

Es un poco desconcertante, tal vez - pero en realidad: lo que hay que comprobar si en su método de PrintLength no es si su Items en su conjunto es nulo - pero si los valores reales items[0] y así sucesivamente son nulos.

Lo que es un poco extraño quizás - o contraintuitivo al principio - es el hecho de que el único valor explícito "nulo" se trata como "nulo" - en lugar de una matriz de un solo elemento de valor nulo. Por qué ese es el caso, y si podría haberse implementado de manera diferente, no lo sé, honestamente.

0

Como se ha dicho en respuesta de una:

  • 1: una matriz de cadenas con un elemento en él - el elemento es nulo

  • 2: una matriz de cadenas con dos elementos en ella, ambos elementos son nulos

  • nulo: null se pasa en el método, no una matriz

  • 2: una matriz de valores nulos es pas incluido en el método

Cuestiones relacionadas