Variable parameters in C# Lambda

落爺英雄遲暮 提交于 2020-01-10 17:48:15

问题


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"}});
}

回答1:


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"
}



回答2:


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

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




回答3:


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));



回答4:


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);



回答5:


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");


来源:https://stackoverflow.com/questions/3581118/variable-parameters-in-c-sharp-lambda

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!