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

Asked

Viewed 424 times

7

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

};

Might call it that

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

VS

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

Might call it that

Escrever("Algum texto aqui dentro");

or

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

Might call it that

Soma.Invoke(1,2);

VS

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

Might call it that

Soma(1,2)

In what situations should I use some and other?

What are the most efficient ways?

  • I think this isn’t about method being different, you’re just defining that return of Escrever will be class Action using string as Constraint.

  • 1

    The second case, usually Func is used to define local functions (or anonymous, I’m not sure what it’s called in C#). It’s very reminiscent of PHP closures and javascript.

1 answer

5


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

When you need the method to be customized into a class that derives from yours then you need to leave the method virtual. In this case it practically prevents optimization and there is an extra level of indirect to find out which is the concrete type of the object before deciding which method to call, whether it is from the base class or derivative. That’s the thing about polymorphism.

But it may be that you need more customization, you may want each instance of the object to have a custom action in that method, it is not enough to just let the derived class customize the method implementation. In this case you need to have an infrastructure within the instance that controls this, and that’s where the anonymous method comes in.

This form create a variable that is of a type delegate, so she’s an extra indirect like the virtual is, and today can never be optimized, even in the future few cases would be possible and with high cost for the compiler.

Done this you have the implementation of the field Escrever or Soma 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 statically bound name in it.

This way you can create an object and place the implementation you want and change the execution. You can determine a different way of doing such writing or summing that is to be done. You can even switch in the middle of the execution. In the declared form, the value is free to be exchanged, as well as any variable of the type int or string, then you can say 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 field Escrever. To perform this you have to call:

objeto.Escrever()

No need to use the Invoke().

In general you don’t want the implementation to be changed on the object in the middle of its execution, so you can do so:

public readonly Action<string> Escrever;

And then in the builder do something like this:

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

The this probably not necessary, it was more to illustrate.

If you just do

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

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

And if you do

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

there is only a much more complicated and inefficient way of doing

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

There are some questions that explain better the internal mechanism of anonymous function, especially me . And there are also others who talk about the loading of cloistered variables.

Both can use the type syntax lambda (=>) 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;

I put in the Github for future reference.

See more in:

  • public int Sum(int n1, int N2) => n1 + N2; only applies when you only have one line?

  • Yes, although you can use some trick for more, but it’s abuse.

  • show then :)

  • I’ll be prosecuted for bombing if I can :D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.