【问题标题】:Variable parameters in C# LambdaC# Lambda 中的可变参数
【发布时间】:2010-08-27 03:24:09
【问题描述】:

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

我在此上下文中使用“params”关键字的所有尝试都失败了。


使用来自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"}});
}

【问题讨论】:

  • 您能否发布到目前为止您尝试过的代码,以便更好地了解您要查找的内容?
  • 我认为他正在尝试做Func<params TIn[] list, TOut> func

标签: c# lambda params


【解决方案1】:

直接将参数传递给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"
}

【讨论】:

  • 我一定错过了什么。在ParamsDelegate 上调用DynamicInvoke 有什么意义?还是您认为只是以防万一您将ParamsDelegate 输入为Delegate
  • +1 表示没有DynamicInvoke 的方法。 DynamicInvoke 即使没有基准测试,我也会尽力避免。只是有点太慢了。
  • 2015 年,paramsDelegate(new object[] { 1, 2, 3} ); 工作正常。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    object[] Params(params object[] args) { return args;}
    
    // :
    
    Action<string, object[]> CWL = 
                      (format,  args) => Console.WriteLine(format, args);
    
    CWL("{0}, {1}", Params(1,2));
    

    【讨论】:

    • 伙计,一旦微软引入了 Action* 和 Func* 代表,就像每个人都忘记了你实际上也可以声明自己的代表......
    【解决方案4】:

    除了马克的回答,我会创建一个扩展方法来清理一下:

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

    然后你只需要说:

    paramsDelegate.DyanamicInvokeParams(1, 2, 3);
    

    【讨论】:

    • 但是当你可以写paramsDelegate(1, 2, 3);时你为什么要这样做呢?
    • 公平点;我猜 OP 可能想使用 DynamicInvoke 因为他们有一个数组,所以它更有可能是 paramsDelegate.DynamicInvokeParams(new []{1, 2, 3}) 这仍然更好一点。
    【解决方案5】:

    我觉得这里没有讨论一个非常关键的点,那就是 如果你定义了一个接受 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");
    

    【讨论】:

    • 是的,在这种简化的情况下它是无用的,但在实际的实现情况下它不是因为它变成了在其他地方调用的通用委托。我将更新我的帖子以使这一点更加明显。
    • @wb:好的,在这种情况下,我可以理解您需要解决这个问题。我将用我认为对您有帮助的解释来更新我的答案。
    • 我仍然有点不确定为什么需要 ..new[]{... 部分,但我应该添加。
    • 我和上面有同样的问题!为什么 DynamicInvoke() 需要双重装箱? foo.DynamicInvoke(new object[] { new[] { arg1, arg2 } });预期的参数是 object[] 并将所有参数放入 string[] 以匹配委托是有意义的。但是类型转换?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 2015-09-20
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多