En primer lugar, vamos a los términos correctos. Eso no es un colección inicializador. Es un inicializador de matriz . Un inicializador de colección siempre sigue a un constructor para un tipo de colección. Un inicializador de matriz solo es legal en un inicializador de declaración local o de campo, o en una expresión de creación de matriz.
Tiene toda la razón al observar que esta es una regla extraña. Permítanme caracterizar su rareza con precisión:
Supongamos que tiene un método M que toma una matriz de entradas. Todos estos son legales:
int[] x = new[] { 10, 20, 30 };
int[] y = new int[] { 10, 20, 30 };
int[] z = new int[3] { 10, 20, 30 };
M(new[] { 10, 20, 30 });
M(new int[] { 10, 20, 30 });
M(new int[3] { 10, 20, 30 });
Pero
int[] q = {10, 20, 30}; // legal!
M({ 10, 20, 30 }); // illegal!
Parece que sea el "solitario" matriz inicializador debe ser legal en todas partes que el "decorado" uno es, o nada. Es extraño que exista esta pseudoexpresión que solo es válida en un inicializador, no en ningún otro lado donde una expresión sea legal.
Antes de criticar y defender esta elección, quiero decir que ante todo, esta discrepancia es un accidente histórico. No hay una razón convincente para ello. Si pudiéramos deshacernos de él sin romper el código, lo haríamos. Pero no podemos. Si estuviéramos diseñando C# desde cero nuevamente, creo que las probabilidades son buenas de que el inicializador de matriz "solitario" sin "nuevo" no sea una sintaxis válida.
Entonces, permítanme primero dar algunas razones por las que los inicializadores de matriz NO deben permitirse como expresiones y deben permitirse en los inicializadores de variables locales. Entonces daré algunas razones para lo opuesto.
Razones por inicializadores de matriz no se debe permitir que las expresiones:
inicializadores de matriz violan la propiedad agradable que {
siempre significa la introducción de un nuevo bloque de código. El analizador de recuperación de errores en el IDE que analiza a medida que escribe me gusta para usar llaves como una forma conveniente de saber cuándo una declaración está incompleta; si usted ve:
if (x == M(
{
Q(
Entonces es bastante fácil para el editor de código para adivinar que se echa en falta ))
antes de la {
. el editor asumirá que Q(
es el comienzo de una declaración y le falta su final.
Pero si inicializadores de matriz son expresiones legales, entonces podría ser que lo que falta es )})){}
siguiente la Q
.
En segundo lugar, los inicializadores de matriz como expresiones violan el agradable principio de que todas las asignaciones de pila tienen "nuevo" en alguna parte.
Razones por inicializadores de matriz deben ser permitidos en el terreno y locales inicializadores:
recordar que inicializadores de matriz se añadieron a la lengua en v1.0, los locales antes implícitamente mecanografiados, los tipos anónimos, o la inferencia de tipos de matrices. De vuelta en el día que no tuvimos la agradable "nueva [] {10, 20, 30}" sintaxis, así que sin inicializadores de matriz que lo tienes que decir:
int[] x = new int[] { 10, 20, 30 };
que parece muy redundante! Puedo ver por qué querían sacar ese "nuevo int []" de allí.
Cuando dice
int[] x = { 10, 20, 30 };
no es sintácticamente ambigua; el analizador sabe que este es un inicializador de matriz y no el comienzo de un bloque de código (a diferencia del caso que mencioné anteriormente). Tampoco es ambiguo en cuanto a tipo; está claro que el inicializador es una matriz de entradas del contexto.
De modo que ese argumento justifica por qué en C# 1.0 se permitieron los inicializadores de matriz en los inicializadores locales y de campo pero no en los contextos de expresión.
Pero ese no es el mundo en el que estamos hoy. Si estuviéramos diseñando esto desde cero hoy, probablemente no tendremos inicializadores de matriz que no tengan "nuevo". Hoy en día, por supuesto, nos damos cuenta de que la mejor solución es:
var x = new[] { 10, 20, 30 };
y esa expresión es válida en cualquier contexto. Puede escribirlo explícitamente en el lado de "declaración" o en el "inicializador" del =
si lo cree conveniente, o puede dejar que el compilador deduzca los tipos de ambos lados o ambos.
Así que, resumiendo, sí, tiene razón en que es inconsistente que los inicializadores de matriz solo puedan estar en declaraciones locales y de campo pero no en contextos de expresión. Hubo una buena razón para eso hace diez años, pero en el mundo moderno con la inferencia de tipo, ya no existe una buena razón para ello. Es solo un accidente histórico en este punto.
Puede encontrar esto útil: http://stackoverflow.com/questions/7351453/why-cant-i-use-the-array-initializer-with-an-implicitly -typed-variable (no estrictamente un duplicado) –