Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 21 de febrero de 2023
C#

Aunque muchos de nosotros trabajamos a diario con C#, siempre hay algo nuevo por aprender o formas de utilizar algunas características que nunca se nos habían ocurrido. Siempre.

En un nuevo capítulo de la serie de C# bizarro, hoy os planteo un reto sobre este código:

var sum = (int a, int b) => a + b;
var sub = (int a, int b) => a - b;
var mul = (int a, int b) => a * b;
var result = sum - sub + mul;

Console.WriteLine("Resultado: " + result(3, 2));
¿Compila? Y si es así, ¿qué aparece por consola? ¡No sigáis leyendo! Echad un vistazo al código e intentad averiguarlo antes de ver la solución pulsando aquí :)
Pues sí, este código es totalmente válido y compilará sin problema. Y al ejecutarlo, por consola veremos lo siguiente.
Resultado: 6

En primer lugar el código compila correctamente porque las variables sum, sub y mult, que hemos definido usando expresiones lambda de tipo Func<int, int, int>, a la postre son simplemente delegados.

Además, los tres delegados tienen la firma idéntica (reciben dos valores int y retornan un int), podemos utilizar los operadores de combinación suma "+" y resta "-", lo que da lugar a un delegado de multidifusión (multicast delegate).

En nuestro código, creamos el nuevo delegado de multidifusión result combinando sum y mult, que son los dos delegados que se suman. Por otra parte, la resta de sub es simplemente una maniobra de distracción, pues se intentará eliminar de la combinación un delegado que no existía previamente, por lo que la operación será ignorada.

var result = sum - sub + mul;

Tras ejecutar esta línea, result será un Func<int, int, int> cuya invocación provocará que se ejecuten secuencialmente, y por orden de llegada, los delegados que han sido combinados.

Por tanto, cuando se evalúa la expresión result(3, 2), se ejecutará primero la función sum(3, 2) y luego mul(3, 2), y será el resultado de esta última la que se retorne finalmente. De ahí obtenemos el 6 que va a la consola.

¿Qué, habías acertado?


Publicado en Variable not found.

9 Comentarios:

Anónimo dijo...

Si, compila, pero el resultado pondría 10.

result = (3+2) - (3-2) + (3*2) = 5 - 1 + 6 = 4 + 6 = 10

Anónimo dijo...

Yo diría lo mismo

Anónimo dijo...

Yo también

José María Aguilar dijo...

Pues quizás no... ;)

Anónimo dijo...

Y porque da ese resultado tan poco intuitivo?

José María Aguilar dijo...

La respuesta está en el post ;)

Básicamente, las operaciones de suma y resta lo único que hacen es configurar un multicast delegate, que luego ejecutará cada operación secuencialmente, retornándose el resultado del último delegado invocado ("mul(3, 2)" en este caso.

Saludos!

Oscar dijo...

Buenas noches,

suma delegados o restarlos de como esta en el código no es habitual.

var result=sum+sub+mul; da el mismo resultado porque el resultado es del ultimo delegado invocado.

lo que si es más habitual es usa += o -= sobre un evento.

Un código equivalente seria el siguiente:

public struct DelegateTest
{
public static event Func result;

public static void Test()
{
var sum = (int a, int b) => a + b;
var sub = (int a, int b) => a - b;
var mul = (int a, int b) => a * b;

result += sum;
result -= sub;
result += mul;

Console.WriteLine("Resultado: " + result(3, 2));
}
}

Anónimo dijo...

Lo que no entendí fue por qué se elimina uno, aunque lo pones en el artículo, aún así sigo sin comprenderlo

José María Aguilar dijo...

Hola,

como se comenta en el artículo, la eliminación de ese delegado es pura maldad, una maniobra de distracción ;) Realmente eliminarlo no hace nada porque no estaba previamente asociado al delegado multicast.

Es decir, el código:

var result = sum - sub + mul;

Es totalmente equivalente a:

var result = sum + mul;

Saludos!