C# 中是否有某种相当于 Python 的
**kwargs
的东西?我希望能够将可变数量的命名参数传递到函数中,然后将它们作为类似于字典的内部函数并循环遍历它们。
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 { ... }”包装器。
如果您特别想要一系列
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);
是的。我相信 C# 4.0 中添加了使用可选参数和命名参数的功能。
http://msdn.microsoft.com/en-us/library/dd264739(v=vs.100).aspx
void paramsExample(object arg1, object arg2, params object[] argsRest)
{
foreach (object arg in argsRest)
{ /* .... */ }
}
这样称呼它,
paramsExample(1, 0.0f, "a string", 0.0m, new UserDefinedType());
您可以使用参数列表作为函数的最终参数,如下所示:
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");
另一种方法是使用
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);
}