Passing array of Argument into multiple parameter function in C# - 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:
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.
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);

Related

how to execute a method based on a string which contains its name

I have an Object which contains several methods and outside of it I have a list of strings where each of the strings value is the name of the Method. I would like to Execute the the method based on the name. From expirience, in python it is deadly simple. In c# I assume that it should be done with delegates I suposse. Or with methodInvoking?
I wanted to ignore reflection on this one.
i python you can store methods as objects, because it is an object.
def a():
return 1
def b():
return 2
def c():
return 3
l= [a,b,c]
for i in l:
print i()
The output would be:
>>> 1
>>> 2
>>> 3
If you want to ignore reflection, you can create a delegate for each method call and store in a Dictionary.
Heres how you do it:
var methods = new Dictionary<string, Action >() {
{"Foo", () => Foo()},
{"Moo", () => Moo()},
{"Boo", () => Boo()}
};
methods["Foo"].Invoke();
Note that in your Python example, you are not "[executing] a method based on a string which contains its name" but rather adding the method to a collection.
You can do basically the same thing as you are doing in Python in C#. Take a look at the Func delegate.
class FuncExample
{
static void Main(string[] args)
{
var funcs = new List<Func<int>> { a, b, c };
foreach (var f in funcs)
{
Console.WriteLine(f());
}
}
private static int a()
{
return 1;
}
private static int b()
{
return 2;
}
private static int c()
{
return 3;
}
}
and the output is
1
2
3
If you need to execute a function based on its name as a string, Uri-Abramson's answer to this very question is a good place to start, though you may want to reconsider not using reflection.

Implicit cast an object to an array with one element. Is it possible?

Can I implicitly create an array from one single element in C#?
For instance, I have this method
public void MyMethod(string[] arrayString)
At some point in my code I have
string str = "myStr";
MyMethod(str)
Of course the second linhe is an error, because I am passing a string while MyMethod expects a string[].
Is there any clean way to call MyMethod without using
MyMethod(new string[] {str})
If you use a params array, this will be fine:
public void MyMethod(params string[] arrayString)
string str = "myStr";
MyMethod(str)
The only way I know would be to overload the method, so that you also have
MyMethod(string)
{
return MyMethod(new string[] {str});
}
You might be able to do it with a params array, but I'm not entirely sure how that would work if you tried to pass in a string array, rather than multiple strings.
I would just add a second overload of MyMethod
public void MyMethod(string str)
{
MyMethod(new[]{str});
}
For the sake of completeness, here's another couple of options, though surely not recommended -- I'd use params as in the accepted answer.
MyMethod(Enumerable.Repeat(str, 1).ToArray());
I've also seen this on occasion, though it's hard to justify unless you're unaware of array initializers:
T[] MakeArray<T>(params T[] elements)
{
return elements;
}
used thus:
string[] grades = MakeArray("A", "B", "C", "D", "F", "Incomplete");
or, in this case:
MyMethod(MakeArray(str));
How about an extension method?
public static T[] WrapInArray<T>(this T t)
{
return new T[]{ t };
}

Can I forward/delegate a params list to another method?

Can I forward a params parameter to another method?
e.g.,
void MyStringMethod(string format, params object[] list)
{
String.Format(format, list);
}
Works for me.
void Main()
{
Method1("{0},{1},{2},{3}","Can","I","do","this").Dump();
}
String Method1(string format, params object[] list)
{
return String.Format(format,list);
}
returns
Can,I,do,this
yes ... but!
I know this is technically not a different answer, however I've been burned so many times with really hard to debug errors (caused by using params in what looked like really simple scenarios) that I feel compelled to post this comment.
Please be very careful when you use params. Ideally don't use them, unless you feel you absolutely have to, and then make sure you don't use the same data type in front of the params! This can make quickly reading the code (scanning) it and knowing what it will do very difficult, or worse, give you an unexpected and hard to find bug.
For example, in the code below, it's not easy to see what will be printed to the Console. Is the (1,2,3) being passed to WhoKnocked actually being identified as int 1 followed by int[] [2,3] or perhaps int[] [1,2,3]?
void Main()
{
Console.WriteLine(WhoKnocked(1,2,3));
}
public string WhoKnocked(int x, params int[] knocks)
{
return "It's mee!";
}
public string WhoKnocked(params int[] knocks)
{
return "No, it's not, its you!";
}
lastly, here's another example that might give you some surprising results.
void Main()
{
Greet(1,"foo", "bar");
Greet(1, 2, "bar");
Greet(1,"foo", new object());
Greet(1,2,3);
Greet(1,2,3,4);
}
public void Greet(int i, params object[] foo)
{
Console.WriteLine("Number then param array of objects!");
}
public void Greet(int i, int x, params object[] foo)
{
Console.WriteLine("Number, ...nuther number, and finally object[]!");
}
public void Greet(int i, string x, params object[] foo)
{
Console.WriteLine("number, then string, then object[]!");
}
produces the following output
Number, then String, then Object[]!
Number, ...nuther Number, and finally Object[]!
Number, then String, then Object[]!
Number, ...nuther Number, and finally Object[]!
Number, ...nuther Number, and finally Object[]!
The params keyword is just a form of syntactic sugar designed to allow you to make method calls as if they had a dynamic parameter count. All it is really is just a compiler transformation of multiple arguments to an array instantiation. That's all it is, an array.
An array is just another object that could be passed to other methods and whatnot so yes, you can forward that array of you wish.
I believe you can, it is just an array of objects. If you then call another function that expects a param list then you can get unexpected results (depending on what you expect of course:-). Notice in the third case you only get 2 params.
void Test()
{
DoIt(1, 2, 3, 4);
}
private void DoIt(params object[] p)
{
Console.WriteLine(p.Length);
DoIt2(p);
DoIt2(p, 5);
}
private void DoIt2(params object[] p)
{
Console.WriteLine(p.Length);
}

Is there a way to distingish myFunc(1, 2, 3) from myFunc(new int[] { 1, 2, 3 })?

A question to all of you C# wizards. I have a method, call it myFunc, and it takes variable length/type argument lists. The argument signature of myFunc itself is myFunc(params object[] args) and I use reflection on the lists (think of this a bit like printf, for example).
I want to treat myFunc(1, 2, 3) differently from myFunc(new int[] { 1, 2, 3 }). That is, within the body of myFunc, I would like to enumerate the types of my arguments, and would like to end up with { int, int, int} rather than int[]. Right now I get the latter: in effect, I can't distinguish the two cases, and they both come in as int[].
I had wished the former would show up as obs[].Length=3, with obs[0]=1, etc.
And I had expected the latter to show up as obs[].Length=1, with obs[0]={ int[3] }
Can this be done, or am I asking the impossible?
Well this will do it:
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("First call");
Foo(1, 2, 3);
Console.WriteLine("Second call");
Foo(new int[] { 1, 2, 3 });
}
static void Foo(params object[] values)
{
foreach (object x in values)
{
Console.WriteLine(x.GetType().Name);
}
}
}
Alternatively, if you use DynamicObject you can use dynamic typing to achieve a similar result:
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic d = new ArgumentDumper();
Console.WriteLine("First call");
d.Foo(1, 2, 3);
Console.WriteLine("Second call");
d.Bar(new int[] { 1, 2, 3 });
}
}
class ArgumentDumper : DynamicObject
{
public override bool TryInvokeMember
(InvokeMemberBinder binder,
Object[] args,
out Object result)
{
result = null;
foreach (object x in args)
{
Console.WriteLine(x.GetType().Name);
}
return true;
}
}
Output of both programs:
First call
Int32
Int32
Int32
Second call
Int32[]
Now given the output above, it's not clear where your question has really come from... although if you'd given Foo("1", "2", "3") vs Foo(new string[] { "1", "2", "3" }) then that would be a different matter - because string[] is compatible with object[], but int[] isn't. If that's the real situation which has been giving you problems, then look at the dynamic version - which will work in both cases.
OK, so let's say that we abandon the other question where you incorrectly believe that any of this is a compiler bug and actually address your real question.
First off, let's try to state the real question. Here's my shot at it:
The preamble:
A "variadic" method is a method which takes an unspecified-ahead-of-time number of parameters.
The standard way to implement variadic methods in C# is:
void M(T1 t1, T2 t2, params P[] p)
that is, zero or more required parameters followed by an array marked as "params".
When calling such a method, the method is either applicable in its normal form (without params) or its expanded form (with params). That is, a call to
void M(params object[] x){}
of the form
M(1, 2, 3)
is generated as
M(new object[] { 1, 2, 3 });
because it is applicable only in its expanded form. But a call
M(new object[] { 4, 5, 6 });
is generated as
M(new object[] { 4, 5, 6 });
and not
M(new object[] { new object[] { 4, 5, 6 } });
because it is applicable in its normal form.
C# supports unsafe array covariance on arrays of reference type elements. That is, a string[] may be implicitly converted to object[] even though attempting to change the first element of such an array to a non-string will produce a runtime error.
The question:
I wish to make a call of the form:
M(new string[] { "hello" });
and have this act like the method was applicable only in expanded form:
M(new object[] { new string[] { "hello" }});
and not the normal form:
M((object[])(new string[] { "hello" }));
Is there a way in C# to implement variadic methods that does not fall victim to the combination of unsafe array covariance and methods being applicable preferentially in their normal form?
The Answer
Yes, there is a way, but you're not going to like it. You are better off making the method non-variadic if you intend to be passing single arrays to it.
The Microsoft implementation of C# supports an undocumented extension that allows for C-style variadic methods that do not use params arrays. This mechanism is not intended for general use and is included only for the CLR team and others authoring interop libraries so that they can write interop code that bridges between C# and languages that expect C-style variadic methods. I strongly recommend against attempting to do so yourself.
The mechanism for doing so involves using the undocumented __arglist keyword. A basic sketch is:
public static void M(__arglist)
{
var argumentIterator = new ArgIterator(__arglist);
object argument = TypedReference.ToObject(argumentIterator.GetNextArg());
You can use the methods of the argument iterator to walk over the argument structure and obtain all the arguments. And you can use the super-magical typed reference object to obtain the types of the arguments. It is even possible using this technique to pass references to variables as arguments, but again I do not recommend doing so.
What is particularly awful about this technique is that the caller is required to then say:
M(__arglist(new string[] { "hello" }));
which frankly looks pretty gross in C#. Now you see why you are better off simply abandoning variadic methods entirely; just make the caller pass an array and be done with it.
Again, my advice is (1) under no circumstances should you attempt to use these undocumented extensions to the C# language that are intended as conveniences for the CLR implementation team and interop library authors, and (2) you should simply abandon variadic methods; they do not appear to be a good match for your problem space. Do not fight against the tool; choose a different tool.
Yes, you can, checking the params length and checking the argument type, see the following working code sample:
class Program
{
static void Main(string[] args)
{
myFunc(1, 2, 3);
myFunc(new int[] { 1, 2, 3 });
}
static void myFunc(params object[] args)
{
if (args.Length == 1 && (args[0] is int[]))
{
// called using myFunc(new int[] { 1, 2, 3 });
}
else
{
//called using myFunc(1, 2, 3), or other
}
}
}
You can achieve something like this by breaking the first element out of the list and providing an extra overload, for example:
class Foo
{
public int Sum()
{
// the trivial case
return 0;
}
public int Sum(int i)
{
// the singleton case
return i;
}
public int Sum(int i, params int[] others)
{
// e.g. Sum(1, 2, 3, 4)
return i + Sum(others);
}
public int Sum(int[] items)
{
// e.g. Sum(new int[] { 1, 2, 3, 4 });
int i = 0;
foreach(int q in items)
i += q;
return i;
}
}
This is not possible in C#. C# will replace your first call by your second call at compile time.
One possibility is to create an overload without params and make it a ref parameter. This probably won't make sense. If you want to change behavior based on the input, perhaps give the second myFunc another name.
Update
I understand your issue now. What you want is not possible. If the only argument is anything that can resolve to object[] it's impossible to distinguish from this.
You need an alternative solution, maybe have a dictionary or array created by the caller to build up the parameters.
Turns out that there was a real issue, and it comes down to the way that C# does type inference. See the discussion on this other thread

Odd Lambda Expression Question

List<string> a = new List<string>() { "a", "b", "c" };
List<string> b = new List<string>() { "a", "b", "c", "d", "e", "f" };
b.RemoveAll(a.Contains);
If you loop through b it will now only contain d e and f. Can anyone expand out whats actually happening, because currently it doesnt make any sense at all.
Edit: I was more talking about the use of predicates. How does know how to pass what into where?
b.RemoveAll(<function that takes a string and returns true if we want to remove it>)
no lambda expression required.
perhaps you'd like for the line to read
b.RemoveAll(x => a.Contains(x))
however, the function x=> a.Contains(x) is simply a function that takes a string and returns a bool indicating whether a contains x. a.Contains is already a function that does that.
The { } Syntax is a collection initializer. The code is equivalent to
List<string> a = new List<string>();
a.Add("a");
a.Add("b");
a.Add("c");
List<string> b = new List<string>();
b.Add("a");
b.Add("b");
b.Add("c");
b.Add("d");
b.Add("e");
b.Add("f");
b.RemoveAll is a function that calls another function and passes in a string. It's like this:
foreach(string s in b) {
if(FunctionToCall(s) == true) b.Remove(s);
}
a.Contains is a function that takes a string and returns a bool. So the code can be changed to:
foreach(string s in b) {
if(a.Contains(s)) b.Remove(s);
}
Note that in this Lambda-Syntax, you are passing the "a.Contains" function - not the result of the function! It's like a function pointer. RemoveAll expects to take a function in the form of "bool FunctionName(string input)".
Edit: Do you know what delegates are? They are a bit like function pointers: A delegate specifies a signature ("Takes 2 strings, returns an int"), and then you can use it like a variable. If you don't know about delegates, read Karl Seguins article.
Some delegates are needed extremely often, so the .net Framework developers added three types of extremely common delegates:
Predicate: A delegate that takes a T and returns a bool.
Action: A delegate that takes 1 to 4 parameters and returns void
Function: A delegate that takes 0 to 4 parameters and returns a T
(Shamelessly copied from Jon Skeet's Answer here)
So predicate is just the name given for a delegate, so that you don't have to specify it yourself.
If you have ANY function in your assembly with the signature
"bool YourFunction(string something)", it is a Predicate<string> and can be passed into any other function that takes one:
public bool SomeFunctionUsedAsPredicate(string someInput)
{
// Perform some very specific functionality, i.e. calling a web
// service to look up stuff in a database and decide if someInput is good
return true;
}
// This Function is very generic - it does not know how to check if someInput
// is good, but it knows what to do once it has found out if someInput is good or not
public string SomeVeryGenericFunction(string someInput, Predicate<string> someDelegate)
{
if (someDelegate.Invoke(someInput) == true)
{
return "Yup, that's true!";
}
else
{
return "Nope, that was false!";
}
}
public void YourCallingFunction()
{
string result = SomeVeryGenericFunction("bla", SomeFunctionUsedAsPredicate);
}
The whole point is separation of concerns (see the comment in SomeGenericFunction) and also to have very generic functions. Look at my generic, extensible string encoding function. This uses the Func rather than the Predicate delegate, but the purpose is the same.
look at it like this:
foreach(string s in b)
{
if(a.Contains(s))
b.Remove(s);
}
You passing the bit in the if evaluation clause as a delegate (managed equivalent of a function pointer). The RemoveAll method unrolls the list and does the rest.
It says 'remove all elements in b that are contained in a'. So you're left only with the one's in b that weren't also present in a.
Here is a slightly expanded version of your code that shows what's happening:
List<string> a = new List<string> () { "a", "b", "c" };
List<string> b = new List<string> () { "a", "b", "c", "d", "e", "f" };
Predicate<string> ps = a.Contains;
b.RemoveAll (ps);
For every element in b, a.Contains() is being evaluated for that element. If it's true, it is removed.
So, you're removing every element from b that is also contained in a.
The function "a.Contains" is being passed as an argument to RemoveAll.
The signature for RemoveAll looks like this ...
public int RemoveAll(Predicate<T> match);
A Predicate<T> is a delegate that takes Ts and returns bools ...
public delegate bool Predicate<T>(T obj)
RemoveAll is thus asking for a reference to a method that will, in your case, take strings and return bools. List<T>.Contains is such a method. You will note that the signature for List<T>.Contains matches the Predicate delegate (it takes Ts and returns bools) ...
public bool Contains(T item);
RemoveAll will apply whatever Predicate is passed as "match" to each element of the list upon which it is called (b in your case). So, if a.Contains("a"), for example, returns true, then all the a's will be removed from the b list. Thus, in your example, all the a's, b's and c's are removed.
Using a tool like .NET Reflector will let you look at the code of RemoveAll and that might help clarify what's happening under the covers.

Categories