ACTUALIZACIÓN: This question was the subject of my blog on June 25th, 2012. Gracias por la gran pregunta!
Con LINQ, la variable de rango se pueden introducir de forma implícita de la colección que está viniendo, sino una instrucción foreach no puede hacer lo mismo sin la palabra clave var.
Eso es correcto.
¿Por qué es esto?
Nunca se sabe cómo responder las preguntas "por qué". Así que voy a pretender que hizo una pregunta diferente:
Hay dos formas distintas en que una variable con nombre puede escribirse implícitamente. Una variable local con nombre, para variable de bucle, variable de bucle foreach, o utilizando variable de declaración se puede tipear implícitamente sustituyendo "var" por su tipo explícito. Un parámetro lambda o variable de rango de consulta puede escribirse implícitamente omitiendo su tipo por completo.
Correcto.
Esa es una incoherencia. Un principio básico de diseño es que se debe evitar la inconsistencia porque es confusa; el usuario asume naturalmente que una inconsistencia transmite significado. ¿Podrían estas características haberse hecho consistentes?
De hecho, hay dos maneras en que podrían haberse hecho consistentes. El primero es requerir "var" en todas partes, para que diga:
Func<double, double> f = (var x)=>Math.Sin(x);
var query = from var customer in customers
join var order in orders on customer.Id equals ...
Todo el diseño es una serie de compromisos. Esto cumple con la prueba de consistencia, pero ahora se siente torpe y detallado.
La segunda es la eliminación de "var" en todas partes, por lo que se podría decir:
x = 12; // Same as "int x = 12;"
using(file = ...) ...
for(i = 0; i < 10; ++i) ...
foreach(c in customers) ...
En los tres primeros casos hemos añadido inadvertidamente la función de "declarada implícitamente locales" en lugar de "implícitamente tecleó lugareños ". Parece extraño y distinto de C# tener una nueva variable local declarada solo porque asignó algo a un nombre que no se había utilizado anteriormente. Este es el tipo de característica que esperaríamos en un lenguaje como JScript o VBScript, no C#.
Sin embargo, en el bloque foreach está claro por el contexto que se está introduciendo una variable local. Podríamos eliminar "var" aquí sin causar demasiada confusión, porque el "en" no se confunde con una tarea.
bien, así que vamos a resumir nuestra posibles características:
- Característica 1: var requiere en todas partes.
- Característica 2: no requiere var en ninguna parte.
- Característica 3: requerir var en los locales, los bucles y usings pero no foreach bucles, lambdas o variables de rango
- Característica 4: require var en los locales, para bucles utilizando y foreach, pero no lambdas o variables de rango
Los dos primeros tienen los beneficios de consistencia, pero la consistencia es solo un factor. El primero es torpe. El segundo es muy dinámico y confuso. El tercero y el cuarto parecen compromisos plausibles, aunque no son consistentes.
La pregunta entonces es: es la variable de bucle foreach más como una variable local o más como un parámetro lambda ? Claramente es más como una variable local; de hecho, el bucle foreach es especificado como una reescritura en la que la variable de bucle se convierte en una variable local.Para coherencia con el bucle "for", y la coherencia con el uso de C# 1.0 y C# 2.0 del bucle foreach, que requirió un tipo de algún tipo, elegimos la opción cuatro como superior a la opción tres.
Espero que responda a su pregunta. De lo contrario, formule una pregunta mucho más específica.
No creo que ex1 sea correcto, no compilará. ¿No te refieres a Employee [] emps = new [] {new Employee (...)}; ... y en tu segundo ejemplo ... foreach no debería tener ningún problema para inferir la T en un T [] o cualquier IEnumerable ... así que no estoy seguro de entender el problema que está describiendo. –
Jeff
Lo siento, primero publico aquí y me acostumbro a cómo funciona el sitio. Si el segundo ejemplo no está relacionado con el primero, mi mal debería haber puesto el conjunto en el foreach en lugar del resultado de linq. – mgmedick
Actualicé su código para reflejar eso y mi respuesta :) –