Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating delegates manually vs using Action/Func delegates

Today I was thinking about declaring this:

private delegate double ChangeListAction(string param1, int number); 

but why not use this:

private Func<string, int, double> ChangeListAction; 

or if ChangeListAction would have no return value I could use:

private Action<string,int> ChangeListAction; 

so where is the advantage in declaring a delegate with the delegate keyword?

Is it because of .NET 1.1, and with .NET 2.0 came Action<T> and with .NET 3.5 came Func<T>?

like image 691
Elisabeth Avatar asked Dec 19 '10 10:12

Elisabeth


People also ask

What is the difference between Func and Action delegate?

Action is a delegate (pointer) to a method, that takes zero, one or more input parameters, but does not return anything. Func is a delegate (pointer) to a method, that takes zero, one or more input parameters, and returns a value (or reference).

What is difference between delegate and method?

A Delegate is an object which refers to a method or you can say it is a reference type variable that can hold a reference to the methods. Delegates in C# are similar to the function pointer in C/C++.

Why we use Func delegates in C#?

Func is generally used for those methods which are going to return a value, or in other words, Func delegate is used for value returning methods. It can also contain parameters of the same type or of different types.

How do you use an Action delegate?

You can use the Action<T> delegate to pass a method as a parameter without explicitly declaring a custom delegate. The encapsulated method must correspond to the method signature that is defined by this delegate.


2 Answers

The advent of Action and Func family of delegates has rendered custom delegates less used, but the latter still finds uses. Advantages of custom delegates include:

  1. As others have pointed, conveys intent clearly unlike generic Action and Func (Patrik has a very good point about meaningful parameter names).

  2. You can specify ref/out parameters unlike the other two generic delegates. For eg, you can have

    public delegate double ChangeListAction(out string p1, ref int p2); 

    but not

    Func<out string, ref int, double> ChangeListAction; 
  3. Also, with custom delegates you need to write ChangeListAction (I mean the definition) only once somewhere in your code base, whereas if you don't define one you will have to litter everywhere Func<string, int, double> all over. Changing the signature will be a hassle in the latter case - a bad case of not being dry.

  4. Can have optional parameters.

    public delegate double ChangeListAction(string p1 = "haha", int p2); 

    but not

    Func<string, int, double> ChangeListAction = (p1 = "haha", p2) => (double)p2;  
  5. You can have params keyword for parameters of a method, not so with Action/Func.

    public delegate double ChangeListAction(int p1, params string[] p2); 

    but not

    Func<int, params string[], double> ChangeListAction; 
  6. Well, if you're truly out of luck and need parameters more than 16 (for the moment) :)


As to merits of Action and Func:

  1. It's quick and dirty, and I use it all over. It makes code short if the use-case is trivial (custom delegates have gone out of fashion with me).

  2. More importantly, its type compatible across domains. Action and Func are framework defined, and they operates seamlessly as long as the parameter types match. You can't have ChangeSomeAction for ChangeListAction. Linq finds great use of this aspect.

like image 149
nawfal Avatar answered Oct 13 '22 01:10

nawfal


The advantage is clarity. By giving the type an explicit name it is more clear to the reader what it does.

It will also help you when you are writing the code. An error like this:

cannot convert from Func<string, int, double> to Func<string, int, int, double> 

is less helpful than one which says:

cannot convert from CreateListAction to UpdateListAction 

It also means that if you have two different delegates, both of which take the same types of parameters but conceptually do two entirely different things, the compiler can ensure that you can't accidentally use one where you meant the other.

like image 26
Mark Byers Avatar answered Oct 12 '22 23:10

Mark Byers