utilizan tipo que puede para metodos las funciones flecha expresiones expresion delegados delegado convertir anonimos c# delegates lambda anonymous-methods out-parameters

c# - que - no se puede convertir expresion lambda en el tipo delegado



¿Por qué los delegados/lambdas anónimos no infieren tipos en los parámetros out/ref? (2)

Del comentario de Eric Lippert sobre por qué la declaración y asignación de una variable var no se puede dividir:

Estoy de acuerdo en que, en principio, esto podría hacerse, pero es bastante más complicado en la práctica de lo que indicaría su esbozo rápido. var no solo requiere que haya un inicializador, también requiere que el inicializador no haga referencia a la variable. Si tiene int M (out int), entonces puede decir "int x = M (out x);" pero no puedes decir "var x = M (out x);" porque para hacer una resolución de sobrecarga en M, necesitamos saber el tipo de x, que es lo que estamos tratando de averiguar. ¿Sería legal decir "var s; if (b) M (out s); de lo contrario s = 0;" ?

Supongo que la respuesta a su pregunta es similar, considerando, por ejemplo,

D a = (out var x) => x = M(out x);

Varias preguntas de C # en StackOverflow preguntan cómo hacer delegados / lambdas anónimos out parámetros o ref . Ver, por ejemplo:

Para hacerlo, solo necesita especificar el tipo de parámetro, como en:

public void delegate D(out T p); // ... D a = (out T t) => { ... }; // Lambda syntax. D b = delegate(out T t) { ... }; // Anonymous delegate syntax.

Lo que me interesa es por qué el tipo se requiere explícitamente. ¿Hay alguna razón particular por la que este es el caso? Es decir, desde el punto de vista del compilador / idioma, ¿por qué no se permite lo siguiente?

D a = (out t) => { ... }; // Lambda syntax -- implicit typing. D b = delegate(out t) { ... }; // Anonymous delegate syntax -- implicit typing.

o incluso mejor, simplemente:

D a = (t) => { ... }; // Lambda syntax -- implicit typing and ref|out-ness. D b = delegate(t) { ... }; // Anonymous delegate syntax -- implicit typing and ref|out-ness.


Interesante pregunta.

Primero, considera la diferencia entre métodos anónimos y lambdas. Desde la perspectiva del escritor del compilador, la diferencia más importante es que las lambdas pueden requerir que el compilador deduzca el tipo de los parámetros del destino al que se asigna la lambda; Los métodos anónimos de C # 2 no tienen esta característica. Esta característica parece una pequeña diferencia, pero de hecho tiene importantes ramificaciones en la implementación del compilador. Vea mi serie de blogs sobre este tema para ver algunas ideas sobre por qué es eso:

http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx

Así que ahora vamos a su pregunta real: ¿por qué no podemos inferir la ausencia / refacción del tipo objetivo a los parámetros de la lambda? Es decir, si tenemos delegado void D (out int x) entonces seguramente D d = x => {x = 10; } podría inferir que x es "out int".

No hay ninguna razón técnica por la que sepa que no podríamos hacer eso. Internamente en el compilador, los tipos out / ref se representan como tipos como cualquier otro.

Sin embargo, las características no se hacen solo porque se pueden hacer; se hacen porque hay una razón de peso para hacerlo. Para las lambdas, la razón de peso para hacer la inferencia de tipos en primer lugar es LINQ; queremos poder realizar una transformación sintáctica simple en una comprensión de consulta en una llamada de método con lambdas, y dejar que el motor de inferencia de tipo de método resuelva los tipos de todos los parámetros de lambda. Ninguno de los métodos LINQ generados tienen delegados sin parámetros o ref.

Por lo tanto, no tenemos ninguna razón convincente para hacer la función. Los delegados que tienen parámetros de salida / referencia son relativamente raros. Y la asignación de lambdas a esos delegados es aún más rara. Así que esta es una característica que no necesitamos, y que no beneficia a casi nadie.

C # 3 fue el "polo largo" en el programa de Visual Studio; tuvimos el mayor número de días de trabajo programados de cualquier equipo que envíe un componente en VS. Eso significaba que cada día se nos escapaba el horario, toda la división se deslizaba. Eso fue un poderoso desincentivo para gastar tiempo en características innecesarias que no beneficiaron a nadie. Así que el trabajo nunca se hizo.

Estoy de acuerdo en que sería bueno ser más coherente aquí, pero es poco probable que suceda. Tenemos muchas prioridades más altas.