Action doesnt seem to support params string[] as a param so i wrote
delegate void WriteFn(string s, params string[] ls);
i have this function
void blah(WriteFn Write, string fmt, params string[] a)
Now i would like to write an function but i cant seem to figure the syntax out. It something like
{
var sw = ...
blah(new WriteFn(s, ls) { sw.write(s, ls); }, fmt, a);
//not what i want to do but close enough. remember sw isnt a param in WriteFn
How do i write this?
Your question is not clear. Are we suppose to guess that sw is a StreamWriter? If so, it looks like this would work:
blah((s, ls) => sw.Write(s, ls), fmt, a);
I think you can't do this because variable argument lists is NOT compatible with anonymous methods, according to MSDN.
Related
I am trying to develop a template engine in c# and in my concept I will need to read to read methods as well as parameters from text files.This shows something could be done , but it does not work if the parameter is also read from the text.Is there a way to achieve this?
private static void Main(string[] args)
{
string returnValue = Execute("AMethod(\"Hello\")");
//the result in retunValue is same as from code commented below:
// string returnValue= AMethod("Hello");
}
public static string AMethod(string parameter)
{
return "xyz" + parameter;
}
The problem here is how to write the Execute Method
The link you provided has the answer you are looking for. Look at the line
object[] parametersArray = new object[] { "Hello" };
and change it to
object[] parametersArray = new object[] { parameter };
There are really 3 ways to accomplish what you are trying to accomplish:
Reflection (this is what is explained in the article you reference)
Reflection.Emit
Dynamic compilation
2 & 3 are more complicated and heavy weight, but depending on the syntax you are trying to achieve in your template engine, one of those might be the best way to go. Reflection requires that you handle each aspect of the invocation--binding to the correct method, passing arguments as arrays, etc. Dynamic compilation would allow you to take a line a C# code formatted exactly how you would write it in a .cs file, compile it to a new method, load the assembly, and execute it. This is all a bit of a hassle, so if you aren't married to having to execute a string that looks like AMethod("Hello"), I highly recommend the reflection route.
Here is an example of what you are trying to achieve with pure reflection:
private static void Main(string[] args)
{
string methodName = "AMethod";
object[] parameters = new object [] {"Hello", "foo"};
MethodInfo method = typeof(Program).GetMethod(methodName, BindingFlags.Static);
string returnValue = (string)method.Invoke(null, parameters);
}
public static string AMethod(string parameter1, string parameter2)
{
return "xyz" + parameter1 + "abc" + parameter2;
}
For examples of 2 & 3, you can take a look at this question: Compiling code dynamically using C#
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 };
}
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);
I'm able to compile code that includes this:
OperationDelegate myOpDelegate;
static OperatorDefinition[] definitions ={
new OperatorDefinition("+",2,3,true, new OperationDelegate(OperationAdd)),
};
delegate double OperationDelegate(double[] args);
static double OperationAdd(double[] args)
{
return args[0] + args[1];
}
but I think my code would look cleaner if I could do something more like this:
OperationDelegate myOpDelegate;
static OperatorDefinition[] definitions ={new OperatorDefinition("+",2,3,true, new OperationDelegate({return args[0]+args[1]}))};
delegate double OperationDelegate(double[] args);
because I want to define everything about each OperatorDefinition in a single place, rather than defining the functions separately. Is there some way to do this in C#?
(any other criticism about my code would be welcome, too)
Look into anonymous methods... for example this: C# - Anonymous delegate
You can use Lambda expressions as from .Net 3.5:
static OperatorDefinition[] definitions ={
new OperatorDefinition("+",2,3,true,
args => args[0] + args[1])
};
In your OperatorDefinition constructor, last parameter should be of type Func<double[],double>
See:
http://msdn.microsoft.com/en-us/library/bb397687.aspx
What are the pro/cons of using the params keyword vs. a List as input to some c# function?
Mainly what are the performance considerations and other trade offs.
The params keyword is syntactic sugar handled by the C# compiler. underneath the hood, it's actually turning
void Foo(params object[] a) { ... }
Foo(1,2,"THREE");
into
void Foo(object[] a) { ... }
Foo(new object[] { 1, 2, "THREE" })
From a performance perspective like you're asking about, the params call is simply faster because it is a bit faster to create an array than it is to create a List<>. There is no performance difference between the two snippets above.
Personally I use params when writing functions that take a number of inputs provided by another programmer (for example String.Format), and IEnumerable when writing functions that take a list of data items provided by the computer (for example File.Write).
The performance implications are negligible. Worrying about the performance of a trivial thing like this is exactly what Donald Knuth was talking about in the famous "premature optimization is the root of all evil" quote.
That said, the asker seems to be fixated on it, so here you go:
Results for 10 million iterations:
params took 308 ms
list took 879 ms
From these results we can see that the params array is just over twice as fast. The simple fact that you can call either of these things Ten Million Times in under a second means that you're completely wasting your time by worrying about it. Use whatever suits your code the best.
The code to test it (compiled and run in release mode using VS2008)
class Program
{
const int COUNT = 10000000;
static IEnumerable<string> m_value = null;
static void ParamsMethod(params string[] args)
{ m_value = args; } // do something with it to stop the compiler just optimizing this method away
static void ListMethod(List<string> args)
{ m_value = args; } // do SOMETHING with it to stop the compiler just optimizing this method away
static void Main(string[] args)
{
var s = new Stopwatch();
s.Start();
for (int i = 0; i < COUNT; ++i)
ParamsMethod("a", "b", "c");
Console.WriteLine("params took {0} ms", s.ElapsedMilliseconds);
s.Reset();
s.Start();
for (int i = 0; i < COUNT; ++i)
ListMethod(new List<string> { "a", "b", "c" });
Console.WriteLine("list took {0} ms", s.ElapsedMilliseconds);
}
}
Well, with the params keyword you could enter arguments into a method like this:
MethodName(1, 2, 3, 4);
But with a list, you'd do it like this:
MethodName(new List<int> {1, 2, 3, 4});
The syntax can be a bit more clear in the former than the latter. This is useful when you just have one parameter to pass in:
// params
MethodName(1);
// List
MethodName(new List<int> {1});
Well, the params allows for a nicer syntax when calling it, but the list (assuming you mean IList<>) is more flexible because different classes may implement the interface. Passing a List<> only makes sense if you need to perform specific operations on the list which are not supported by the interface (such as ToArray()).
The params keyword allows you to dynamically pass a variable number of arguments to the function without worrying about compiler errors like this:
public string PrefixFormatString(string p, string s, params object[] par)
{
return p + string.Format(s, par);
}
...
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", errNum, errStr);
If you pass a list, you have to construct the list before you can pass it in:
public string PrefixFormatString(string p, string s, List<object> par)
{
return p + string.Format(s, par.ToArray());
}
...
List<object> l = new List<object>(new object[] { errNum, errStr });
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", l);
and it tends to hide the meaning of what type of data the function is expecting.
Note that this is very similar to passing a simple array variable. The only difference is that the compiler will fix up the parameters into an array for you... I'm not 100% sure, but I think the technical difference is just syntactical sugar - in either case you are really passing an array of whatever type the parameter is.
params is a language construct for functions taking a variable number of parameters. It is similar to C elipses specifier - i.e. printf(char* fmt, ...). The language supports this kind of operation, might as well use it, especially if it makes the code easier to read.
Personally, I would skip the params. I've been bitten by it once or twice. How? Let me explain.
You write a public method with this signature:
public static void LogInUser(string username, string password, params string[] options)
You test it, it works, its done... and another assembly/application is calling your function.
Now, a month later you want to change your signature to add user role:
public static void LogInUser(string username, string password, string role, params string[] options)
Oh how things have changed for anything calling your method.
LogInUser("z#z.com", "zz", "Admin", "rememberMe", "800x600");
The main difference between the two that I can see is that the number of parameters passed into the method is set at compile time using params, while with a List<T> it depends on the list passed in at runtime.
Whether fixing the number of arguments that your method must be called with at compile time is a pro or a con depends entirely upon your design and intent for it. Either can be a benefit depending on what you are hoping to achieve.
Params helps on the readability front, and is as close to an optional parameter that you're going to get to in C#. I would only use the List<T> implementation personally if I needed to consume an unknown number of parameters at any point.
Edit: just spotted your edit regarding performance issues. On that topic I'm unsure, although if you could potentially expect a large number of 'parameters' using List<T>, whereas params has a sanity cap on it due to them having to be coded.
The performance of the programmer calling your method can sometimes be improved by your usages of the params keyword.
(Given that programmers cost so much more then computers, why are you thinking of any other sort of performance.)