Yeo
Yeo

Reputation: 11814

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?

Upvotes: 6

Views: 4680

Answers (5)

svick
svick

Reputation: 244968

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

Upvotes: 3

edvaldig
edvaldig

Reputation: 2299

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

Upvotes: 0

Douglas
Douglas

Reputation: 54897

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

Upvotes: 1

KurToMe
KurToMe

Reputation: 166

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.

Upvotes: 0

Bassam Mehanni
Bassam Mehanni

Reputation: 14944

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

Upvotes: 1

Related Questions