【问题标题】:Can I pass arbitrary number of named parameters to function in C#?我可以将任意数量的命名参数传递给 C# 中的函数吗?
【发布时间】:2012-12-05 18:10:11
【问题描述】:

在 C# 中是否有某种与 Python 的 **kwargs 等价的东西?我希望能够将可变数量的命名参数传递给函数,然后将它们作为类似于字典的内部函数获取并循环它们。

【问题讨论】:

  • 我最初在考虑 params 关键字,但后来我注意到您说的是“可变数量的命名参数”。我能想到的唯一方法是创建一个字典并将其传入。
  • 在考虑了所有选项后,我决定采纳您的建议。

标签: c# function named-parameters


【解决方案1】:

C# 中没有任何东西可以让你像这样传入任意命名参数。

您可以通过添加Dictionary<string, object> 参数来接近,这可以让您执行类似的操作,但需要一个构造函数,“参数名称”是字符串和一些额外的大括号:

static void Method(int normalParam, Dictionary<string, object> kwargs = null)
{
   ...
}

Method(5, new Dictionary<String, object>{{ "One", 1 }, { "Two", 2 }});

您可以使用the ObjectToDictionaryRegistry here 更接近,它允许您传入一个匿名对象,不需要您命名字典类型、将参数名称作为字符串传递或添加相当多的大括号:

static void Method(int normalParam, object kwargs = null)
{
    Dictionary<string, object> args = ObjectToDictionaryRegistry(kwargs);
    ...
}

Method(5, new { One = 1, Two = 2 });

但是,这涉及动态代码生成,因此会降低性能。

在语法方面,我怀疑你永远能够摆脱这需要的 `new { ... }' 包装器。

【讨论】:

  • 感谢您抓住我的问题的精髓,而我却忘了概述它:)
【解决方案2】:

如果您特别想要一系列 KeyValuePairs 而不是值数组,您可以执行以下操作:

public class Foo
{
    public Foo(params KeyValuePair<object, object>[] myArgs)
    {
        var argsDict = myArgs.ToDictionary(k=>k.Key, v=>v.Value);
        // do something with argsDict
    }
}

myArgs 将是KeyValuePair&lt;object, object&gt; 的数组,您可以对其进行迭代或转换为字典,如上所示。不过请注意,如果您使用相同的键传递多个KeyValuePair&lt;&gt;s,则转换为字典可能会失败。在转换为字典之前,您可能需要提前进行一些检查。

你可以这样称呼它:

KeyValuePair<object, object> myKvp1 = new KeyValuePair<object, object>(someKey1, someValue1);
KeyValuePair<object, object> myKvp2 = new KeyValuePair<object, object>(someKey2, someValue2);
KeyValuePair<object, object> myKvp3 = new KeyValuePair<object, object>(someKey3, someValue3);

Foo foo = new Foo(myKvp1, myKvp2, myKvp3);

【讨论】:

  • 谢谢,它完成了工作,但我希望我可以通过调用fun(a:1, b:2) 而不是fun(new Dictionary&lt;string, string&gt;{ {"a", 1}, {"b", 2} }) 来减少代码量。在这方面,传递字典比你的方法更短。
  • @Anton 直接传递字典会更快(更清晰)是的。我的示例更多地是关于使用 KeyValuePairs 传递半命名参数。转换为字典更多的是说明了在构造函数中可以对数据做什么。
【解决方案3】:

是的。我相信 C# 4.0 中添加了使用可选参数和命名参数的功能。

http://msdn.microsoft.com/en-us/library/dd264739(v=vs.100).aspx

【讨论】:

  • 不满足“任意数量”部分。
  • 已编辑。如果您转到该链接,则同时添加了可选参数。
  • 是的,但是您仍然不能使用它来使函数接受“任意数量的命名参数”。照原样,您受到在接收函数的类型签名中定义的可选参数的限制。我认为这澄清了一些事情:stackoverflow.com/questions/1769403/…
【解决方案4】:
void paramsExample(object arg1, object arg2, params object[] argsRest)
{
    foreach (object arg in argsRest)
    { /* .... */ }
}

这样称呼,

paramsExample(1, 0.0f, "a string", 0.0m, new UserDefinedType());

【讨论】:

    【解决方案5】:

    您可以使用参数列表作为函数的最终参数,如下所示:

    void paramsExample(object arg1, object arg2, params object[] argsRest) {
        foreach (object arg in argsRest)
        { /* .... */ }
    }
    

    可以使用任意数量的任意类型的参数调用该方法。

    paramsExample(1, 0.0f, "a string", 0.0m, new UserDefinedType());
    

    这是一个强类型参数,所以如果我想使用字符串列表,我可以这样做:

     public string Concat(string separator, params string[] strings) {
          string result = "";
          for (int i = 0; i < strings.Length; i++) {
              if (i > 0)
                  result += separator;
              result += strings[i];
          }    
          return result;
     }
    

    调用:

    MessageBox.Show(Concat("+", "Anders", "Eric", "Scott", "Duncan") + " = great team");
    

    在此处查看更多信息: http://blogs.msdn.com/b/csharpfaq/archive/2004/05/13/how-do-i-write-a-method-that-accepts-a-variable-number-of-parameters.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-11
      • 2017-12-18
      • 1970-01-01
      • 2011-09-15
      • 2012-09-24
      • 1970-01-01
      • 2011-06-07
      相关资源
      最近更新 更多