2

Apologizing in advance for the newbie kinda question (as I am one in C#):

While studying delegates, it seems to me that the combination of Action and Func covers the entire "functionality" of the delegate keyword.

In other words, there is nothing that you can do with the delegate keyword but cannot do with either Action or Func.

I've tried the following examples (which work fine):

Func<int,int,int,int> func = (x,y,z) => (x<<9)|(y<<6)|(z<<3);
Action<int,int,int> action = (x,y,z) => Console.WriteLine(x|y|z);

Am I wrong? If yes, then can you please provide a counterexample?

barak manos
  • 29,648
  • 10
  • 62
  • 114
  • I would define Action and Func als Wrapper/helper classes that allow programmes Easy to use, and standardized delegates. – Venson Jun 04 '14 at 16:50
  • Take a look at http://stackoverflow.com/q/11376657/1284902 – Tarec Jun 04 '14 at 16:52
  • Thanks @Tarec. I'd expect my question to be a duplicate of some previous post, but haven't been quite able to find one. Your link provides a partial answer to my question, but it kind of explains something that I already know. So basically I'm just trying to figure out whether once you have `Action` and `Func` it "covers the whole thing", or am I missing something here? Thanks again. – barak manos Jun 04 '14 at 16:55
  • @barakmanos you are right, that answer doesn't explain the difference in purposes of using both. Please check this explanation, I hope it helps ;) http://stackoverflow.com/a/18741018/1284902 – Tarec Jun 04 '14 at 17:04

3 Answers3

7

You will need to use a delegate other than Action or Func if you want to have:

  1. More than 16 parameters to your method.

  2. Any parameters be ref or out parameters.

  3. A params parameter.

  4. Optional arguments for any of your parameters.

  5. Constraints on any of the generic arguments. (Ensuring a parameter is any type that extends a type, that it has a parameterless constructor, that it is a value/reference type, etc.)

  6. unsafe types used in the signature of the method, such as pointers as parameters.

  7. Have a parameter that isn't contravariant, or a return type that's not covariant. Func and Action both apply variance wherever possible, so if its important that your delegate not be variant, you would need your own.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • `out`, `params` and optional arguments are actually three results of one common and more general impossibility with `Action`/`Func`: the ability to specify custom attributes. –  Jun 04 '14 at 17:04
  • You could add the case of `unsafe` types, i.e. a delegate type where some parameters, or the return value, are of pointer types. For example `public unsafe delegate string GetString(char* value);`. – Jeppe Stig Nielsen Jan 19 '15 at 14:32
  • Yet another use if you do not want the type parameters to be marked as co- or contravariant. Note that `System.EventHandler` is not contravariant (not "`in`") in `TEventArgs` because it can lead to problem with multicast delegates. So it is different from `Action` in that regard. – Jeppe Stig Nielsen Jan 19 '15 at 14:40
2

You can create delegates that take ref or out parameters. You cannot define a Func or an Action that has ref or out parameters.

For example:

delegate void MyDelegate(ref string val);

Cannot be expressed as an Action.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
1

My two cents: With your own generic delegates you can apply generic constraints which is not provided by Func or Action

delegate void MyDelegate<T>(T input) where T : struct;

Compiler will make sure MyDelegate<T> will always have value types as T, reference types are not allowed.

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189