简体   繁体   中英

Passing array of Argument into multiple parameter function in C#

Life is short

def foo(b,a,r):
    # bla bla bla
    pass

mylist = ['b','a','r']
foo(*mylist) 

That's how passing a list of arguments into method multiple positional parameters in Python .

But in C# I found out passing an array into a parameter of array using the params keywords, like this one:

void foo(params string[] bar)
{
    // bla bla bla
}

string[] mylist = {"b", "a", "r"};
foo(mylist)

Imagine how If I cannot touch the function, is there an easier way Is there a way to do that?

Here is what I mean:

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

I search online and can't found an alternative of it. Just want to make sure that I didn't miss the hidden feature that C# provide. Who know there's such shortcut for us?

No, there is no feature in C# that allows you to do this directly. But there are some ways you can use to work around that:

  1. Create a method that converts a method with several parameters into a method with one array parameter:

     static Action<T[]> ToArrayMethod<T>(Action<T, T, T> original) { return array => original(array[0], array[1], array[2]); } 

    And then use it like this:

     string[] array = {"b", "a", "r"}; var arrayFoo = ToArrayMethod(foo); arrayFoo(array); 

    The downside of this approach is that this method works only on methods with exactly three parameters with a void return type. You would need to write another overload of ToArrayMethod() if you wanted this to work for methods with, say, 4 parameters, or for those that return some value.

  2. Use reflection. When doing that, arguments are passed in using an array:

     var foo = typeof(SomeType) .GetMethod("foo", BindingFlags.Instance | BindingFlags.NonPublic); object[] array = {"b", "a", "r"}; foo.Invoke(somTypeInstance, array); 

There is downsides to using static languages, and this is one of them, if your function signature is defined as:

void foo (string a, string b, string c);

then you are forced to pass in 3 separate strings

foo(mylist[0],mylist[1],mylist[2]);

the only way to have flexible inputs in C# is by using params which you already now, or by using default values (C# 4.0):

void foo (string a, string b = null, string c = null)

meaning that if I don't pass b or c just set them to null, and now you can call your function like this:

foo(mylist[0]) 

You could use reflection; however, that typically isn't recommended because it makes you sacrifice compile-time type-safety checking.

Here is a sample approach:

string[] mylist = { "b", "a", "r" };
((Action<string,string,string>)foo).DynamicInvoke(mylist);

There is no shortcut. If you want to get crazy and you're able to modify the function somewhat, you could overload it to have one signature with the params keyword, and have the original overload pass its arguments into the the new one.

So to summarize a lot of replies here, you'll need a sort of a hack for this and the cleanest way in my opinion is something along these lines:

Create an extension function for enumerables:

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

Then you can send the array to any function having an argument count equal to the length of the enumerable:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM