将参数数组传递到 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# 中的多参数函数中

不,C# 中没有任何功能允许您直接执行此操作。但是,您可以使用一些方法来解决此问题:

  1. 创建一个方法,该方法将具有多个参数的方法转换为具有一个数组参数的方法:

    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() 重载。

  2. 使用反射。执行此操作时,参数使用数组传入:

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