18

I have a function of this sort

void func(params object[] parameters) { 
    //Function Body
}

It can accept parameters of the following sort

func(10, "hello", 30.0);
func(10,20);

and so on.

I wanted to create an Action delegate for the above function. Is it possible? If not then why?

SohamC
  • 2,367
  • 6
  • 22
  • 34

2 Answers2

24

You can't use the existing Action delegates with params, but you can declare your own delegate that way:

public delegate void ParamsAction(params object[] arguments)

Then:

// Note that this doesn't have to have params, but it can do
public void Foo(object[] args)
{
    // Whatever
}

...

ParamsAction action = Foo;
action("a", 10, 20, "b");

Of course you can create an Action<object[]> for your existing method - but you lose the params aspect of it, as that's not declared in Action<T>. So for example:

public static void Foo(params object[] x)
{
}

...

Action<object[]> func = Foo;
func("a", 10, 20, "b"); // Invalid
func(new object[] { "a", 10, 20, "b" }); // Valid

So if you're calling the delegate from code which wants to use params, you need a delegate type which includes that in the declaration (as per the first part). If you just want to create a delegate which accepts an object[], then you can create an instance of Action<object[]> using a method which has params in its signature - it's just a modifier, effectively.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

This is where you run up against the limitations of functional programming in C#: you can not have a delegate with a variable number of generically-typed parameters (the Action delegates have a fixed number of generic parameters). But you may find it useful to create generic overloads for each number of parameters:

void func<T1>(T1 parameter1) { ... }
void func<T1,T2>(T1 parameter1, T2 parameter2) { ... }
void func<T1,T2,T3>(T1 parameter1, T2 parameter2, T3 parameter3) { ... }

What this gains you is the ability to pass those functions as parameters (ie, to pass them simply without using lambda expressions). So if you have a function like this:

void anotherFunc(Action<string, int> parameter) { ... }

Then you can call it like this:

anotherFunc(func);
McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • 1
    `you can not have a delegate with a variable number of parameters` Sure you can. – Servy Sep 05 '14 at 16:50
  • @Servy right, you can, but you can't use one of the `Action` delegates. – McGarnagle Sep 05 '14 at 16:54
  • 1
    That's true, but that's not what you said in your answer. You said that you can't have a delegate with a variable number of parameters, not that you can't have an `Action` with a variable number of parameters. – Servy Sep 05 '14 at 16:56
  • 1
    @Servy well, the OP asked specifically for an `Action` delegate, which is what I was working off. Anyway, I've updated my answer to clarify my meaning. – McGarnagle Sep 05 '14 at 17:05
  • 1
    He wasn't asking for a delegate with an unknown number of generic arguments in which each parameter has its own argument, he's asking to match a given method that he already has that is `params object[]`. The answer to that is simple, you can create a `delegate` that does that, just not an `Action` that does that. – Servy Sep 05 '14 at 17:08
  • 1
    @Servy it does depend on how you interpret the question. You guessed that the request for an `Action` was arbitrary or mistaken. My answer is admittedly a bit orthogonal, but my hunch was that the OP needs to make use of the delegate in the way I suggested. – McGarnagle Sep 05 '14 at 17:20