14

Siempre pensé que funcionaba bien en ambos sentidos. Luego hizo esta prueba y se dio cuenta de que no está permitido en reasignaciones:¿Por qué no se permiten los inicializadores de recopilación en reasignaciones?

int[] a = {0, 2, 4, 6, 8}; 

funciona bien, pero no:

int [ ] a; 
a = { 0, 2, 4, 6, 8 }; 

algún motivo técnico para esto? Pensé que podría preguntar al respecto aquí, porque este comportamiento fue lo que esperaba intuitivamente.

+4

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) –

Respuesta

20

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.

+4

Wow. StackOverflow sería 1000 veces más increíble si publicaras una respuesta a cada pregunta de C#. –

+0

@JimSchubert: Aprecio mucho el sentimiento, pero te aseguro que sería peor. ¡No sé la respuesta al 99% de las preguntas de C# en el sitio! Soy un experto en historia, diseño e implementación del lenguaje; Centrándonos en eso durante los últimos seis años, significa que hay grandes áreas de programación práctica de C# de las que no sé casi nada. –

+0

De todos modos, me encanta leer sus respuestas! – Matthias

1

más lo sea:

int [] a;// ={1,2,3,4}; 
    a = new [] {1, 2, 3, 4}; 

En VB funciona de la misma manera que la declaración, más fácil xD

Dim a() As Integer '={1,2,3,4} 
a = {1, 2, 3, 4} 
+1

Él pregunta por qué existe esta restricción. –

+0

Gracias, agregar 'new []' antes, lo hace funcionar. Pero por qué existe esta restricción cuando podría funcionar sin ella (al igual que cuando la asignas por primera vez) –

+0

Bueno, creo que es solo para lenguaje, porque en VB se puede hacer, debemos mirar el código MSIL generado cuál es la diferencia . – Piyey

Cuestiones relacionadas