Función local vs Lambda C#7.0
function c#-7.0 (4)
Estoy mirando las nuevas implementaciones en C # 7.0 y me parece interesante que hayan implementado funciones locales, pero no puedo imaginar un escenario en el que se preferiría una función local sobre 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 entender un escenario del mundo real, donde la función local tiene ventajas sobre las expresiones lambda
Cualquier ejemplo sería muy apreciado. Gracias.
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 declaración 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;
}
Si también se pregunta cómo probar la función local, debe verificar JustMock ya que tiene la funcionalidad para hacerlo. Aquí hay un ejemplo de clase simple que se probará:
public class Foo // the class under test
{
public int GetResult()
{
return 100 + GetLocal();
int GetLocal ()
{
return 42;
}
}
}
Y así es como se ve la prueba:
[TestClass]
public class MockLocalFunctions
{
[TestMethod]
public void BasicUsage()
{
//Arrange
var foo = Mock.Create<Foo>(Behavior.CallOriginal);
Mock.Local.Function.Arrange<int>(foo, "GetResult", "GetLocal").DoNothing();
//Act
var result = foo. GetResult();
//Assert
Assert.AreEqual(100, result);
}
}
Aquí hay un enlace a la documentation JustMock.
Renuncia. Soy uno de los desarrolladores responsables de JustMock .
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 teletipo dado. Además, uno puede empacar 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 los datos que vinculan un evento a un evento. Uno puede pensarlo de la misma manera que se diseña una clase, solo uno no está escribiendo métodos auxiliares en todo el lugar que realmente solo funcionan para un nivel de funcionalidad. a continuación se muestra una muestra de cómo se vería esto, tenga en cuenta que estoy usando variables y los métodos "auxiliares" están debajo de finalmente. En Finalmente, elimino muy bien los controladores de eventos, si mi clase de Exchange fuera externa / inyectada, no tendría ningún controlador de eventos pendiente registrado
void List<HistoricalData> 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<HistoricalData>();
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 ayude a explicar los beneficios.
Quieres una función auxiliar. Solo lo está utilizando desde una única función, y es probable que use variables y parámetros de tipo que están dentro del alcance 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 de 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:
-
Actuación.
Al crear una lambda, se debe crear un delegado, que es una asignación innecesaria en este caso. Las funciones locales son realmente solo funciones, no se necesitan delegados.
Además, las funciones locales son más eficientes con la captura de variables locales: las lambdas generalmente capturan variables en una clase, mientras que las funciones locales pueden usar una estructura (aprobada mediante
ref
), que de nuevo evita una asignación.Esto también significa que llamar a las funciones locales es más barato y pueden estar en línea, posiblemente aumentando aún más el rendimiento.
-
Las funciones locales pueden ser recursivas.
Las lambdas también pueden ser recursivas, pero requieren un código incómodo, donde primero se asigna
null
a una variable delegada y luego la lambda. Las funciones locales pueden ser naturalmente recursivas (incluidas las recursivas recíprocas). -
Las funciones locales pueden ser genéricas.
Las lambdas no pueden ser genéricas, ya que deben asignarse a una variable con un tipo concreto (ese tipo puede usar variables genéricas del ámbito externo, pero eso no es lo mismo).
-
Las funciones locales se pueden implementar como un iterador.
Lambdas no puede usar la palabra clave
yield return
(andyield break
) para implementar la funciónIEnumerable<T>
-returning. Las funciones locales pueden. -
Las funciones locales se ven mejor.
Esto no se menciona en la cita anterior y podría ser solo mi sesgo personal, pero creo que la sintaxis de la función normal se ve mejor que asignar una lambda a una variable delegada. Las funciones locales también son más sucintas.
Comparar:
int add(int x, int y) => x + y; Func<int, int, int> add = (x, y) => x + y;