13

Is it possible to have a C# lambda/delegate that can take a variable number of parameters that can be invoked with a Dynamic-invoke?

All my attempts to use the 'params' keyword in this context have failed.


UPDATE WITH WORKING CODE FROM ANSWER:

delegate void Foo(params string[] strings);

static void Main(string[] args)                       
{
    Foo x = strings =>
    {
        foreach(string s in strings)
            Console.WriteLine(s);
    };

    //Added to make it clear how this eventually is used :)
    Delegate d = x;

    d.DynamicInvoke(new[]{new string[]{"1", "2", "3"}});
}
2
  • Can you post the code that you've tried so far to give a better idea of what you're looking for? Commented Aug 27, 2010 at 3:27
  • I think he's trying to do Func<params TIn[] list, TOut> func Commented Aug 27, 2010 at 3:31

5 Answers 5

15

The reason that it doesn't work when passing the arguments directly to DynamicInvoke() is because DynamicInvoke() expects an array of objects, one element for each parameter of the target method, and the compiler will interpret a single array as the params array to DynamicInvoke() instead of a single argument to the target method (unless you cast it as a single object).

You can also call DynamicInvoke() by passing an array that contains the target method's parameters array. The outer array will be accepted as the argument for DynamicInvoke()'s single params parameter and the inner array will be accepted as the params array for the target method.

delegate void ParamsDelegate(params object[] args);

static void Main()
{  
   ParamsDelegate paramsDelegate = x => Console.WriteLine(x.Length);

   paramsDelegate(1,2,3); //output: "3"
   paramsDelegate();      //output: "0"

   paramsDelegate.DynamicInvoke((object) new object[]{1,2,3}); //output: "3"
   paramsDelegate.DynamicInvoke((object) new object[]{}); //output: "0"

   paramsDelegate.DynamicInvoke(new []{new object[]{1,2,3}}); //output: "3"
   paramsDelegate.DynamicInvoke(new []{new object[]{}});      //output: "0"
}
Sign up to request clarification or add additional context in comments.

3 Comments

I must be missing something. What would be the point of calling DynamicInvoke on a ParamsDelegate? Or do you think it's just in case you have a ParamsDelegate typed as Delegate?
+1 for approach without DynamicInvoke. DynamicInvoke is something I would try my best to avoid even without benchmarking. It's just a little too slow.
In 2015, paramsDelegate(new object[] { 1, 2, 3} ); works just fine.
1

No, but any of the parameters it does take can be an array.

Without more details, that's the long and short of it.

Comments

0

No, but with a little help, you can almost fake it:

object[] Params(params object[] args) { return args;}

// :

Action<string, object[]> CWL = 
                  (format,  args) => Console.WriteLine(format, args);

CWL("{0}, {1}", Params(1,2));

1 Comment

Man, once Microsoft introduced those Action* and Func* delegates it's like everybody forgot that you're actually allowed to declare your own as well...
0

Adding to Mark's answer, I'd create an extension method to clean up a bit:

static DynamicInvokeParams(this ParamsDelegate delegate, params object[] args)
{
  delegate.DynamicInvoke(new [] {args});
}

And then you just have to say:

paramsDelegate.DyanamicInvokeParams(1, 2, 3);

2 Comments

But why would you do this when you could just write paramsDelegate(1, 2, 3);?
Fair point; I guess the OP probably wants to use DynamicInvoke because they have an array, so it's more likely to be paramsDelegate.DynamicInvokeParams(new []{1, 2, 3}) which is still a bit nicer.
0

I feel like there's a very crucial point that isn't being discussed here, and that's that if you've defined a delegate type that takes a params argument, there's very little point to calling DynamicInvoke on it at all. The only scenario I can imagine in which this would come into play is if you have a delegate of your custom type and you are passing it as a parameter to some method that accepts a Delegate argument and calls DynamicInvoke on that.

But let's look at this code in the OP's update:

delegate void Foo(params string[] strings);

static void Main(string[] args)                       
{
    Foo x = strings =>
    {
        foreach(string s in strings)
            Console.WriteLine(s);
    };

    x.DynamicInvoke(new[]{new string[]{"1", "2", "3"}});
}

The DynamicInvoke call above is totally superfluous. It would be much more sensible for that last line to read:

x("1", "2", "3");

4 Comments

Yes in this simplified case it would be useless but in the actual implementation case its not as it gets turned into a general delegate that is called elsewhere. I will update my post to make this more obvious.
@wb: OK, in that case then I can understand your need to work this out. I'm going to update my answer with an explanation that I think will help you.
I am still a little unsure why the ..new[]{... part is needed though I should add.
I have the same question as above! Why is there double boxing needed on this for DynamicInvoke()? foo.DynamicInvoke(new object[] { new[] { arg1, arg2 } }); Argument expected is object[] and putting all the arguments into a string[] to match the delegate makes sense. But type conversion?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.