将参数数组传递到 C# 中的多参数函数中
本文关键字:参数 函数 数组 | 更新日期: 2023-09-27 18:24:03
人生苦短
def foo(b,a,r):
# bla bla bla
pass
mylist = ['b','a','r']
foo(*mylist)
这就是在 Python 中将参数列表传递到方法多个位置参数中的方式。
但是在 C# 中,我发现使用 params 关键字将数组传递到数组的参数中,如下所示:
void foo(params string[] bar)
{
// bla bla bla
}
string[] mylist = {"b", "a", "r"};
foo(mylist)
想象一下,如果我无法触摸该功能,有没有更简单的方法有没有办法做到这一点?
我的意思是:
void foo (string b, string a, string r)
{
// bla bla bla
}
string[] mylist = {"b", "a", "r"};
foo(mylist[0],mylist[1],mylist[2]); // This line makes my life difficult
我在网上搜索,找不到它的替代品。只是想确保我没有错过 C# 提供的隐藏功能。谁知道我们有这样的捷径呢?
不,C# 中没有任何功能允许您直接执行此操作。但是,您可以使用一些方法来解决此问题:
-
创建一个方法,该方法将具有多个参数的方法转换为具有一个数组参数的方法:
static Action<T[]> ToArrayMethod<T>(Action<T, T, T> original) { return array => original(array[0], array[1], array[2]); }
然后像这样使用它:
此方法string[] array = {"b", "a", "r"}; var arrayFoo = ToArrayMethod(foo); arrayFoo(array);
的缺点是此方法仅适用于具有正好三个参数且返回类型为
void
的方法。如果您希望它适用于具有 4 个参数的方法或返回某些值的方法,则需要编写另一个ToArrayMethod()
重载。 -
使用反射。执行此操作时,参数使用数组传入:
var foo = typeof(SomeType) .GetMethod("foo", BindingFlags.Instance | BindingFlags.NonPublic); object[] array = {"b", "a", "r"}; foo.Invoke(somTypeInstance, array);
使用静态语言有缺点,如果你的函数签名定义为:
void foo (string a, string b, string c);
然后你被迫传入 3 个单独的字符串
foo(mylist[0],mylist[1],mylist[2]);
在 C# 中具有灵活输入的唯一方法是使用您现在已有的参数,或使用默认值 (C# 4.0(:
void foo (string a, string b = null, string c = null)
这意味着如果我不传递 b 或 c,只需将它们设置为 null,现在您可以像这样调用您的函数:
foo(mylist[0])
您可以使用反射; 但是,通常不建议这样做,因为它会牺牲编译时类型安全检查。
下面是一个示例方法:
string[] mylist = { "b", "a", "r" };
((Action<string,string,string>)foo).DynamicInvoke(mylist);
没有捷径。如果你想发疯并且能够稍微修改函数,你可以重载它以使用params
关键字拥有一个签名,并让原始重载将其参数传递到新签名中。
因此,要在这里总结很多回复,您需要对此进行某种黑客攻击,在我看来,最干净的方法是以下几行:
为枚举项创建扩展函数:
public static class Extensions
{
public static void SendToMethod<T>(this IEnumerable<T> self, Delegate func )
{
Contract.Requires(func.Method.GetParameters().Length == self.Count());
func.DynamicInvoke(self.Cast<object>().ToArray());
}
}
然后,您可以将数组发送到参数计数等于可枚举长度的任何函数:
public void foo(string a, int b, bool c, string d) {}
public void foo2(string a, string b, string c) {}
...
var test1 = new object[] {"ASDF", 10, false, "QWER"};
var test2 = new[] {"A", "B", "C"};
test2.SendToMethod((Action<string, string, string>)foo);
test1.SendToMethod((Action<string, int, bool, string>)foo2);