我可以传递任意数量的命名参数到 C# 中的函数吗?

问题描述 投票:0回答:6

C# 中是否有某种相当于 Python 的

**kwargs
的东西?我希望能够将可变数量的命名参数传递到函数中,然后将它们作为类似于字典的内部函数并循环遍历它们。

c# function named-parameters
6个回答
14
投票

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 { ... }”包装器。


3
投票

如果您特别想要一系列

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<object, object>
的数组,您可以对其进行迭代或转换为字典,如上所示。但请注意,如果您使用相同的键传递多个
KeyValuePair<>
,则转换为字典可能会失败。在转换为字典之前,您可能需要提前进行一些检查。

你可以这样称呼它:

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

1
投票

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

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


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

这样称呼它,

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

0
投票

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

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


0
投票

另一种方法是使用

params
匿名元组列表。

    [Fact]
    public void TestKwArgs()
    {
        var expected = new Dictionary<string, string>
        {
            ["key1"] = "value1",
            ["key2"] = "value2"
        };

        IReadOnlyDictionary<string, string> Convert(params (string, string)[] kwargs)
        {
            return kwargs.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
        }
        
        var actual = Convert(("key1", "value1"), ("key2", "value2"));
        actual.Should().NotBeEmpty();
        
        actual.Should().BeEquivalentTo(expected);
    }

© www.soinside.com 2019 - 2024. All rights reserved.