What's the difference between using normal methods and Action or Func?

6
public Action<string> Escrever = (texto) => 
{
        Console.WriteLine(texto);

};

Being able to call so

 Escrever.Invoke("Algum texto aqui dentro");

VS

public string Escrever(string texto)
{
   Console.WriteLine(texto);
}

Being able to call so

Escrever("Algum texto aqui dentro");

or

public Func<int, int, int> Soma = (n1, n2) => {
    return n1 + n2;
};

Being able to call so

Soma.Invoke(1,2);

VS

public int Soma(int n1, int n2)
{
   return n1 + n2;
}

Being able to call so

Soma(1,2)

In what situations should I use one or the other?

What are the most effective ways?

    
asked by anonymous 22.08.2018 / 16:55

1 answer

4

By default use methods, it has the lowest possible indirection . If it is a static or simple instance method there is only the minimum necessary indirection that is to send to the part of the code where it is written or even in some cases with optimizations it can even eliminate it and copy the code and be faster, is a fairly simple mechanism.

When you need the method to be customized in a class derived from your own, you need to leave the virtual method. in this case practically prevents optimization and there is an extra level of indirection to find out what the concrete type of the object is before deciding which method to call, whether it is the base class or derived. This is the polymorphism .

But it might require a greater customization, you may want each instance of the object to have a custom action on that method, not just letting the derived class customize the implementation of the method. In this case you need to have an infrastructure inside the instance that controls this, and that's where the anonymous method comes in.

This way to create a variable that is of type delegate , so it is an extra indirection as virtual is, and today can never be optimized, even in the future few cases would be possible and with high cost for the compiler.

When you do this you have the implementation of the Escrever or Soma field as an object that will have as its basic value the implementation of a method, which is nothing more than a body of a normal method, but it will not have a name linked to it statically.

In this way you can create an object and put the implementation you want and change the execution. It may determine a different way of making such writing or summation than it is to do. You can even swap in the middle of the run. In the declared form, the value is free to be changed, as well as any variable of type int or string , so you can tell that "now" the method to be executed has another implementation, for example:

objeto.Escrever => Write($"Tenho um texto para te dizer: {texto}");

This will not execute anything, it will only change the value of the Escrever field. To execute this you have to call:

objeto.Escrever()

You do not need to use Invoke() .

In general you do not want the implementation to be changed in the object in the middle of its execution, so you can do this:

public readonly Action<string> Escrever;

And then in the constructor do something assism:

this.Escrever = (texto) => WriteLine(texto);

this probably is not needed, it was more to illustrate.

If you do only

public readonly Action<string> Escrever = (texto) => WriteLine(texto);

It does not make sense, in this case it is better to use a normal method, after all you can not customize in any moment that would be the purpose of it.

And if you do

public static readonly Action<string> Escrever = (texto) => WriteLine(texto);

It's just a much more complicated and inefficient way to do

public void Escrever(texto) => WriteLine(texto);

You have some questions that best explain the internal mechanism of the anonymous function, especially me . And there are also others that talk about the loading of variables in cloister.

Both can use the lambda syntax ( => ) and make the code less verbose.

public Func<int, int, int> Soma = (n1, n2) => n1 + n2;

public int Soma(int n1, int n2) => n1 + n2;

See more at:

22.08.2018 / 17:25