c# - valid - ¿Por qué los params se comportan así?
method summary c# (4)
Como se dijo en la respuesta uno:
1: una matriz de cadenas con un elemento en ella: el elemento es nulo
2: un conjunto de cadenas con dos elementos, ambos elementos son nulos
null: null se pasa al método, no a una matriz
2: una matriz de nulos se pasa al método
Salida
1
2
nulo
2
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());
}
}
Esta es una pregunta bastante frecuente. Para más detalles, consulte las secciones 7.4.1 y 7.4.3.1 de la especificación.
Brevemente: un método con una matriz params es aplicable en su "forma normal" o en 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 da 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 ambos eran aplicables. Supongamos que tienes
void M(params object[] x) {}
¿Cómo pasaría realmente una matriz nula a esta cosa si siempre elegimos la forma expandida? ¡Eso sería imposible!
Supongamos que dijiste
M(new object[] { "hello" });
Y siempre elegimos la forma expandida. ¿Qué haría esto? Bueno, una matriz de objetos es un objeto, por lo que este elegiría la forma expandida: haría otra matriz, envolvería esta cosa en la matriz y la pasaría.
La elección de la forma expandida sobre la forma normal conduce a resultados locos. Elegir siempre la forma normal sobre la forma expandida es lo más sensato que se puede hacer.
Funciona como fue diseñado, yo diría:
PrintLength (s);
Está pasando una sola cadena que es nula: dentro de su método, los items
no serán nulos, es una matriz de un elemento, de tipo cadena, de valor null
PrintLength (s, s);
La misma historia aquí: estás pasando dos elementos, por lo que los items
de tu método serán una matriz de dos cadenas: ambas son nulas, pero la matriz no lo es.
PrintLength (null);
Obviamente, esto se interpreta como un único valor NULL y, por lo tanto, los items
son nulos. No está pasando una matriz, ni un elemento de tipo cadena, solo está pasando un valor nulo per se.
PrintLength (null, null);
Eso es otra vez, una matriz de dos elementos, ambos nulos, pero la matriz per se no es nula, ya que se están pasando dos valores.
Quizá sea un poco desconcertante, pero en realidad: lo que necesita verificar en su método PrintLength
no es si sus Items
en su conjunto son nulos, sino si los valores reales items[0]
etc., son nulos.
Lo que es un poco extraño, o contraintuitivo al principio, es el hecho de que el único valor "nulo" explícito se trata como un "nulo", en lugar de una matriz de un solo elemento de valor nulo. ¿Por qué ese es el caso, y si se podría haber implementado de manera diferente? No lo sé, con toda honestidad.
PrintLength(null)
pasa una matriz nula, mientras que PrintLength(null, null)
pasa una string[]
con una longitud de dos que contiene dos objetos de string
nulos. Sería lo mismo que pasar una new string[] { null, null }
Hmm, leyendo lo que escribí, tal vez eso realmente no responde a tu pregunta encogiéndose de hombros .
Editar:
Probablemente este sea el motivo: puede enviar una lista de argumentos separados por comas del tipo especificado en la declaración del parámetro, o una matriz de argumentos del tipo especificado.