c# - remedios - posicion para defecar estreñimiento
¿Por qué no puede c#usar lambdas anónimos en línea o delegados? (4)
Esta pregunta ya tiene una respuesta aquí:
Espero haber redactado el título de mi pregunta de manera apropiada.
En c # puedo usar lambdas (como delegados), o la sintaxis de delegado anterior para hacer esto:
Func<string> fnHello = () => "hello";
Console.WriteLine(fnHello());
Func<string> fnHello2 = delegate()
{
return "hello 2";
};
Console.WriteLine(fnHello2());
Entonces, ¿por qué no puedo "en línea" el lambda o el cuerpo de delegado, y evitar capturarlo en una variable con nombre (por lo que es anónimo)?
// Inline anonymous lambda not allowed
Console.WriteLine(
(() => "hello inline lambda")()
);
// Inline anonymous delegate not allowed
Console.WriteLine(
(delegate() { return "hello inline delegate"; })()
);
Un ejemplo que funciona en javascript (solo para comparar) es:
alert(
(function(){ return "hello inline anonymous function from javascript"; })()
);
Que produce el cuadro de alerta esperado.
ACTUALIZACIÓN : parece que puedes tener una lambda anónima en línea en C #, si lanzas apropiadamente, pero la cantidad de () comienza a hacerlo ingobernable.
// Inline anonymous lambda with appropriate cast IS allowed
Console.WriteLine(
((Func<string>)(() => "hello inline anonymous lambda"))()
);
Quizás el compilador no puede inferir la sig del delegado anónimo para saber a qué Console.WriteLine () está tratando de llamar. ¿Alguien sabe por qué se requiere este elenco específico?
Cuando escribe Func<string> = ...
, el compilador sabe que tiene que crear un objeto de tipo Func<string>
. Pero cuando escribe ese delegado en línea, el compilador no conoce el objeto del tipo que debe crear.
Habiendo dicho lo anterior, se puede sacar una conclusión obvia: simplemente dígale al compilador el tipo explícitamente.
Console.WriteLine( new Func<string>( () => "Hello" )() );
ACTUALIZAR
Ok, mientras escribía la respuesta, actualizaste tu publicación. Creo que mi respuesta anterior ya responde a la pregunta "por qué se requiere este tipo específico". Para reiterar: porque el compilador no conoce el objeto de qué tipo crear.
Ahora para elaborar un poco sobre la parte " el compilador no puede inferir la sig del delegado anónimo ". Ya ves, no es como en JavaScript. En C #, no hay un tipo genérico de "función" (o "método"). Cada delegado debe tener una firma y un nombre de tipo explícitamente especificados. Y cuando está creando un delegado, el compilador debe saber qué tipo.
Ahora, puedo ver cómo puede implicar que el compilador podría simplemente construir un tipo de delegado sobre la marcha, como lo hace con los tipos de objetos anónimos (también conocido como new { a = 1, b = "xyz" }
). Pero piénselo un momento: probablemente no habría ningún uso para tal delegado de todos modos. Quiero decir, no puedes pasarlo a otro método, porque ese método primero tiene que declarar los tipos de sus argumentos. Y puede crear un evento, porque, nuevamente, debe tener un tipo con nombre.
Algo como eso...
Las lambdas en C # no tienen tipos, hasta que se usan en un contexto que las envía a un delegado o tipo de Expresión. Es por eso que no puedes decir
var x = () => "some lambda";
Puede disfrutar
Parece funcionar si le das un elenco de tipo:
String s = ((Func<String>) (() => "hello inline lambda"))();
¿Es inútil? No completamente. Tome el siguiente:
String s;
{
Object o = MightBeNull();
s = o == null ? "Default value" : o.ToString();
}
Ahora considera esto:
String S = ((Func<Object,String>)(o => o == null ? "Default value" : o.ToString())
)(MightBeNull());
Es un poco feo, pero es compacto.
Puede usar expresiones lambda en línea para métodos que toman en un parámetro delegado.
Sin embargo, hay una pequeña pega: si el parámetro se escribe como el tipo de delegado base, deberá convertirlo explícitamente en una derivación específica de Delegado (por ejemplo, Acción); de lo contrario, el compilador se quejaría.
Preguntas similares:
Método anónimo en Invocar llamada
Métodos anónimos y delegados