2009-05-05 11 views

Respuesta

38

Eric Lippert hicieron todo un blog sobre el tema.

En resumen, el problema principal es que se habría requerido un importante re-arquitectura del compilador de C# para hacerlo. Las declaraciones se procesan actualmente de una sola vez. Esto requeriría pases múltiples debido a la capacidad de formar ciclos entre variables inferidas. VB.net tiene más o menos el mismo problema.

+0

divertido, se propone la adición de otra de las características de la lengua sólo para compensar una deficiencia del compilador Hay formas de escribir un compilador que no permita el escape de tipos anónimos, o que pueda manejar un enfoque de primer paso diferido. –

+5

Soy consciente de que hay formas de hacerlo. Estamos eligiendo no hacer ninguno de ellos en este momento; sus costos no valen los beneficios. –

+0

lo siento Eric, supongo que todo lo que estoy tratando de decir es que estoy feliz de esperar al refactor de compiladores en lugar de votar por copiar el nuevo() de java, incluso si podemos tenerlo antes. Simplemente no parece que encaje bien ya que ya tenemos var. –

0

Creo que es porque el alcance de ese tipo implícito es mucho más amplio y, por lo tanto, es más probable que cause problemas que dentro del alcance de un único método.

1

Porque es mucho más fácil de hacer. Si tuvieras que inferir todos los tipos, uno necesitaría algo así como el sistema de inferencia del tipo de Hindley Milner, que hará que tu amada C# se convierta en un lenguaje derivado de Haskel.

1

Básicamente, el problema con el que te estás encontrando es que C# (hasta ahora) es un lenguaje estáticamente tipado. Una variable local definida como var todavía está tipada estáticamente, pero oculta sintácticamente. Un método que devuelve var, por otro lado, tiene muchas implicaciones. Se convierte en una interfaz más para el uso y no se gana nada al usar var.

6

Jared tiene un enlace fantástico en su respuesta, a un tema fantástico.

Creo que no responde la pregunta de forma explícita.

¿Por qué no?

var getFoo() { 
    return new Foo(); 
} 

La razón de esto es:

¿Qué pasa si?

class Foo {} 

var GetFoo() { 
    return GetBar(); 
} 

var GetBar() { 
    return GetBaz(); 
} 

var GetBaz() { 
    return new Foo(); 
} 

Se podría deducir que GetFoo va a volver Foo, pero tendrá que rastrear a través todas las llamadas que método hace que los niños y sus hace sólo para inferir el tipo. Tal como está, el compilador de C# no está diseñado para funcionar de esta manera. Necesita métodos y tipos de campo al principio del proceso antes de que se pueda ejecutar el código que infiere los tipos.

En un nivel puramente estético que encontrar las definiciones var sobre los métodos de confundir las cosas. Su único lugar donde creo que ser explícita siempre ayuda, que le protege de disparar a su auto en el pie accidentalmente devolver un tipo que causa su firma y un montón de otras firmas de método depende de cambiar. Lo peor es que podrías cambiar todas las firmas de una cadena de métodos sin siquiera saber que lo hiciste si devuelves el valor de un método que devuelve un objeto y resulta afortunado.

Creo métodos var es mejor dejar para lenguajes dinámicos como Ruby

+11

No, ese no es el problema. Ya hemos resuelto ese problema en C#, como puede demostrar. Si convierte getFoo en una lambda inferiremos que el tipo de retorno de la lambda es Foo. Sin embargo, hay problemas reales. Un problema es: si "var getFoo() {...}" llama a "var getBar() {...}" que a su vez llama ... terminas teniendo que hacer potencialmente un análisis de todo el programa solo para escribir el métodos. La arquitectura actual del compilador asume que los métodos y los campos se pueden tipear antes de analizar los cuerpos de los métodos. –

+0

Respuesta corregida y expandida para reflejar –

1

puede utilizar en vs 2010 dinámico

Dynamic getFoo() { 
    return new Foo(); 
} 
+0

A menos que literalmente no pueda escribir el tipo allí (por ejemplo, tipos anónimos), esta es una manera horrible de evitar escribir nombres largos. Eliminas todos los beneficios (bastante considerables) del enlace estático. –

+0

Pero es 'dinámico', en minúsculas –

+0

¡Esto es tan útil! Esto resuelve todos los casos obvios en los que necesito un campo para que el inicializador pueda inferir su tipo, que es mucho para mí. Y Eric L. dijo lo mismo al comienzo de su artículo explicando por qué no hay var para los campos. Su artículo continúa explicando cómo los casos recursivos extremos son un problema, pero no pude entender por qué el caso más común no fue abordado. Afortunadamente "dinámico" resuelve esto. –

Cuestiones relacionadas