2012-04-17 11 views
22

¿Hay alguna manera de ejecutar una expresión lambda inmediatamente después de su definición?¿Ejecuta la expresión lambda inmediatamente después de su definición?

En otras palabras (no válida de código C#):

(() => { Console.WriteLine("Hello World"); }).Invoke(); 
+0

Espera ... ¿qué? ¿Por qué es una expresión lambda? – scottheckel

+4

El motivo por el cual su código no es válido es porque no le ha dicho al compilador si desea 'Action' o' Expression '. Si lanzas esa expresión lambda a 'Action', podrás invocar' Invoke' en ella o utilizar la sintaxis method-call '()' para invocarla. – phoog

+4

Mi imaginación podría estar fallando, ¿hay una necesidad real de hacer esto? –

Respuesta

32

seguro.

new Action(() => { Console.WriteLine("Hello World"); })(); 

Eso debería hacer el truco.

3

Usted debe ser capaz de hacer esto:

Action runMe =() => { Console.WriteLine("Hello World"); }; 
runMe(); 
+0

Correcto. El compilador interpretará la sintaxis lambda como abreviación de un delegado. Solo si asigna en un tipo 'Expresión ' que construirá el árbol de expresiones. – Tejs

+3

Esto no se compilará porque el compilador no puede determinar si desea 'Action' o' Expression '. – phoog

+1

@phoog es correcto. Esto no compilará "No se puede asignar la expresión lambda a una variable local implícitamente tipada." –

12

Otra "opción", que se encuentra a las otras dos respuestas en una apariencia ligeramente diferente:

((Action)(() => { Console.WriteLine("Hello World"); }))(); 

La razón, tan directamente tomado del comentario de phoog:

... no le has dicho al compilador si Quiere un Action o un Expression<Action>. Si emite esa expresión lambda al Action, podrá invocar Invoke o usar la sintaxis method-call() para invocarlo.

Seguro que pone feo sin embargo, y no sé de un lugar donde esta forma es siempre útil, ya que no se puede utilizar para la recursividad sin nombre ...

+0

Totalmente puede hacer recursividad con esto, usando el combinador Y:' delegado público T Recursivo (Recursivo f, T n); vacío estático Principal (cadena [] args) {System.Console. WriteLine ("factorial 5 = {0}", nuevo Recursive ((f, n) => f (f, n)) (nueva Recursive ((f, n) => (n == 0) 1?: n * f (f, n - 1)), 5));} '. Es un truco del mundo puramente funcional, que básicamente declara que una función' f' se toma a sí misma como un parámetro y se llama a sí misma de manera recursiva al pasar 'f '. Para iniciar la recursión, esta función se pasa a otra que llama a' f' con 'f' y al valor inicial del parámetro. –

1

He aquí un ejemplo de cómo esto podría ser utilizado. Desea inicializar un constructor con el resultado de unas pocas líneas de código que no pueden escribirse como una función porque así es como se estructura la API de terceros.

Es solo un código de pegamento para evitar escribir una función independiente que nunca se llama en ningún otro lado. Estoy usando Func en lugar de Action, pero la respuesta es la misma que user166390.

 // imagine several dozens of lines that look like this 
     // where the result is the return value of a function call 
     fields.Add(new ProbeField(){ 
      Command = "A", 
      Field = "Average", 
      Value = be.GetAverage() 
     }); 

     // now you need something that can't be expressed as function call 
     // so you wrap it in a lambda and immediately call it. 
     fields.Add(new ProbeField(){ 
      Command = "C", 
      Field = "Cal Coeff", 
      Value = ((Func<string>)(() => { 
       CalCoef coef; 
       Param param; 
       be.GetCalibrationCoefficients(out coef, out param); 
       return coef.lowDet1.ToString(); 
      }))() 
     }); 
Cuestiones relacionadas