13

是否有可能有一个 C# lambda/delegate 可以接受可变数量的参数,这些参数可以通过 Dynamic-invoke 调用?

我在这种情况下使用“params”关键字的所有尝试都失败了。


使用来自答案的工作代码进行更新:

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

5 回答 5

15

将参数直接传递给它时不起作用的原因DynamicInvoke()是因为DynamicInvoke()需要一个对象数组,目标方法的每个参数都有一个元素,并且编译器会将单个数组解释为params数组DynamicInvoke()而不是单个参数到目标方法(除非您将其转换为单个object)。

您还可以DynamicInvoke()通过传递包含目标方法参数数组的数组来调用。外部数组将被接受为DynamicInvoke()的单个params参数的参数,内部数组将被接受为目标方法的params数组。

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"
}
于 2010-08-27T03:31:44.447 回答
1

不,但它所采用的任何参数都可以是一个数组。

没有更多细节,这就是它的长短。

于 2010-08-27T03:38:29.427 回答
0

不,但有一点帮助,你几乎可以伪造它:

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

// :

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

CWL("{0}, {1}", Params(1,2));
于 2010-08-27T03:52:23.720 回答
0

添加到马克的答案,我会创建一个扩展方法来清理一下:

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

然后你只需要说:

paramsDelegate.DyanamicInvokeParams(1, 2, 3);
于 2010-08-27T03:58:18.720 回答
0

我觉得这里没有讨论一个非常关键的点,那就是如果你定义了一个带params参数的委托类型,那么调用DynamicInvoke它就没有什么意义了。我能想象到的唯一一种情况是,如果你有一个自定义类型的委托,并且你将它作为参数传递给某个接受Delegate参数并调用DynamicInvoke的方法。

但是让我们看看 OP 更新中的这段代码:

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

上面的DynamicInvoke调用完全是多余的。最后一行改为:

x("1", "2", "3");
于 2010-08-27T04:08:55.100 回答