Función local vs Lambda C # 7.0

Estoy viendo las nuevas implementaciones en C # 7.0 y me parece interesante que hayan implementado funciones locales, pero no puedo imaginar un escenario donde una función local sería preferible a una expresión lambda, y cuál es la diferencia entre las dos.

Entiendo que las lambdas son funciones anonymous , mientras que las funciones locales no lo son, pero no puedo imaginar un escenario del mundo real, donde la función local tenga ventajas sobre las expresiones lambda

Cualquier ejemplo sería muy apreciado. Gracias.

Esto fue explicado por Mads Torgersen en C # Design Meeting Notes donde las funciones locales se discutieron por primera vez :

Quieres una función auxiliar. Solo lo está usando desde una sola función, y probablemente use variables y escriba parámetros que están dentro del scope de esa función que lo contiene. Por otro lado, a diferencia de un lambda, no lo necesita como un objeto de primera clase, por lo que no le importa darle un tipo de delegado y asignar un objeto delegado real. También es posible que desee que sea recursivo o genérico, o que lo implemente como un iterador.

Para ampliarlo un poco más, las ventajas son:

  1. Actuación.

    Al crear un lambda, se debe crear un delegado, que es una asignación innecesaria en este caso. Las funciones locales son en realidad funciones justas, no se necesitan delegates.

    Además, las funciones locales son más eficientes con la captura de variables locales: lambdas generalmente capturan variables en una clase, mientras que las funciones locales pueden usar una estructura (pasada usando ref ), que de nuevo evita una asignación.

    Esto también significa que llamar a las funciones locales es más barato y pueden incluirse, posiblemente aumentando aún más el rendimiento.

  2. Las funciones locales pueden ser recursivas.

    Lambdas también puede ser recursivo, pero requiere un código incómodo, donde primero asigna null a una variable de delegado y luego a la lambda. Las funciones locales pueden ser recursivas de forma natural (incluso mutuamente recursivas).

  3. Las funciones locales pueden ser genéricas.

    Lambdas no puede ser genérico, ya que deben asignarse a una variable con un tipo concreto (ese tipo puede usar variables genéricas del scope externo, pero eso no es lo mismo).

  4. Las funciones locales se pueden implementar como un iterador.

    Lambdas no puede utilizar la palabra clave yield return (y yield break ) para implementar la función IEnumerable -return. Las funciones locales pueden.

  5. Las funciones locales se ven mejor.

    Esto no se menciona en la cita anterior y podría ser simplemente mi sesgo personal, pero creo que la syntax de la función normal se ve mejor que la asignación de una lambda a una variable de delegado. Las funciones locales también son más sucintas.

    Comparar:

     int add(int x, int y) => x + y; Func add = (x, y) => x + y; 

Además de la gran respuesta de svick, hay una ventaja más para las funciones locales:
Se pueden definir en cualquier lugar de la función, incluso después de la statement de return .

 public double DoMath(double a, double b) { var resultA = f(a); var resultB = f(b); return resultA + resultB; double f(double x) => 5 * x + 3; } 

Me sorprende que nadie haya mencionado que las funciones locales no crean cierres => sin variables copiadas por el valor dentro de la función, funcionan como parámetros ref (¡lo cual es una ventaja increíble!)

Si incrementa int i dentro de la función local, también lo incrementa fuera de esta función, con lambdas solo incrementa su copia local dentro.

Utilizo funciones en línea para evitar la presión de recolección de basura, especialmente cuando se trata de métodos de ejecución más largos. Digamos que a uno le gustaría obtener 2 años o datos de mercado para un símbolo de cotización dado. Además, uno puede empaquetar mucha funcionalidad y lógica de negocios si es necesario.

lo que uno hace es abrir una conexión de socket al servidor y recorrer el enlace de datos de un evento a un evento. Se puede pensar de la misma manera que se diseña una clase, solo uno no está escribiendo métodos de ayuda en todo el lugar que realmente solo funcionan para un elemento de funcionalidad. A continuación se muestra una muestra de cómo podría ser esto, tenga en cuenta que estoy usando variables y los métodos de “ayuda” están debajo del final. Finalmente, elimino muy bien los controladores de eventos, si mi clase de Exchange fuera externa / inyectada, no registraría ningún controlador de eventos pendiente

 void List RequestData(Ticker ticker, TimeSpan timeout) { var socket= new Exchange(ticker); bool done=false; socket.OnData += _onData; socket.OnDone += _onDone; var request= NextRequestNr(); var result = new List(); var start= DateTime.Now; socket.RequestHistoricalData(requestId:request:days:1); try { while(!done) { //stop when take to long…. if((DateTime.Now-start)>timeout) break; } return result; }finally { socket.OnData-=_onData; socket.OnDone-= _onDone; } void _OnData(object sender, HistoricalData data) { _result.Add(data); } void _onDone(object sender, EndEventArgs args) { if(args.ReqId==request ) done=true; } } 

Puede ver las ventajas que se mencionan a continuación, aquí puede ver una implementación de muestra. Espero que eso ayude a explicar los beneficios.