【问题标题】:How to make an anonymous method accept variable number of arguments?如何使匿名方法接受可变数量的参数?
【发布时间】:2013-02-04 06:50:50
【问题描述】:

我希望能够使用可变数量的参数(有时不带参数,有时带 11 个参数)对匿名方法进行内联调用。

Dictionary<string, Action> ActionDic = new Dictionary<string, Action>();
int i = 0;
ActionDic["something"] = () => { i += 1; };           // this line is ok
ActionDic["somethingArgs"] = (int n) => { n += 1; };  // but this is not
    // Delegate 'System.Action' does not take 1 arguments

所以我不能让委托人接受这样的论点。我的语法是错误的,还是不可能?还是我必须更改我的字典应该使用的匿名方法的类型?

【问题讨论】:

  • 好的,我改了标题,这样更清楚我想要什么。
  • 无论ActionDic 是什么,它的字符串索引器都接受Action(或另一个没有返回类型的无参数委托)。如果是Action&lt;T&gt;,你可以像p =&gt; DoStuff(p) 那样做。
  • @user1306322 请考虑阅读How To pass Optional Arguments。虽然它与匿名方法无关,但它可能会给你一些关于如何传递可变数量参数的线索
  • @KonstantinVasilcov 我熟悉将参数设为可选,但感谢您提供的链接。

标签: c# syntax delegates arguments


【解决方案1】:

如果你想定义一个带有 1 个整数参数的委托,你可以使用Action&lt;int&gt;。例如:

Action<int> somethingArgs = (int n) => { n += 1; };

您尚未显示ActionDic 变量是什么,但如果它是IDictionary&lt;string, Action&gt;,您将无法完成这项工作,因为Action 不接受参数。

另一方面,您可以做的是使用代表字典:

IDictionary<string, Delegate> ActionDic = ...
ActionDic["something"] = (Action)(() => { i += 1; }); 
ActionDic["somethingArgs"] = (Action<int>)((int n) => { n += 1; });

【讨论】:

  • 如果我可以问,我怎样才能让代表可以返回一些东西? (非无效)
  • 您可以使用Func&lt;TResult&gt;。如果你想让它接受一个论点,你可以使用Func&lt;TArg, TResult&gt;。如果你想要 2 个参数:Func&lt;TArg1, TArg2, TResult&gt;。以此类推。
  • 所以我想我不能只使用一本字典,因为这些将是不同类型的匿名方法。
  • 当然可以使用字典。您只需要将其设为IDictionary&lt;string, Delegate&gt;,如我的回答所示。 Delegate 是所有委托的基类。
【解决方案2】:

你不能。 ActionAction&lt;T&gt; 是不同的、不兼容的委托类型。

有几种方法可以弥补这一点。

一种方法是将ActionDic 设为Dictionary&lt;string, Action&lt;int&gt;&gt;,但这可能无法满足您想要使用的所有可能的委托。

另一种方法是使ActionDic 类似于Dictionary&lt;string, Delegate&gt;,但这使用起来很麻烦,因为您需要确切知道要传递每个函数的参数数量(及其类型)。这些信息需要存储在另一个数据结构的某个地方。

第三种方法是使ActionDic 成为Dictionary&lt;string, Action&lt;object[]&gt;&gt; 并要求委托从输入中解压缩它需要的任何参数。调用者将负责确切知道要使用的参数。这将允许第二个选项的语法不那么笨拙,但每个委托中需要更多代码。

【讨论】:

  • 我已经准备好为此创建一个单独的委托管理器类,但我仍然想让每个委托的声明比 ActionDic["somethingArgs"] = (Action&lt;int&gt;)((int n) =&gt; { /* ... */ }); 更容易阅读,因为可能有大量论据。
  • @user1306322 我添加了第三种可能,它可能更容易阅读:ActionDic["somethingArgs"] = (object[] objs) =&gt; { int n = (int)objs[0]; /* ... */ };
  • 谢谢,现在我明白了如何提高代码的一部分的可读性可以杀死另一部分:)
【解决方案3】:

您在谈论两个不同的代表,即ActionAction&lt;T&gt;。您不能将Action&lt;T&gt; 分配给Action

Action a1 = () => { i += 1; };
Action<int> a2 = (n) => { n += 1; };

我想你有Dictionary&lt;string,Action&gt;,所以这个字典不能接受Action&lt;T&gt;的值。

作为旁注,我想说第二个委托绝对没用,因为它增加了一个 int 参数,按值传递,实际上什么也没做。

还可以考虑阅读How To pass Optional Arguments。虽然它与匿名方法无关,但它可能会给你一些关于如何传递可变数量参数的线索

【讨论】:

    【解决方案4】:

    Action 是一种创建返回 void 且不带参数的委托的简短方法。 如果你想要带参数的动作,你需要使用通用形式:

    Action&lt;int&gt; 是一个接受一个 int 参数的委托

    Action&lt;string, double&gt; 有 2 个参数:第一个是字符串,第二个是双精度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-28
      • 2013-07-06
      • 2015-07-22
      • 1970-01-01
      • 1970-01-01
      • 2018-07-04
      • 2013-08-09
      • 2011-05-24
      相关资源
      最近更新 更多