Does C# support a variable number of arguments, and how? - c#

Does C# support a variable number of arguments?
If yes, How does C# support variable no of arguments?
What are the examples?
How are variable arguments useful?
EDIT 1: What are the restrictions on it?
EDIT 2: The Question is not about Optional param But Variable Param

Yes. The classic example wourld be the params object[] args:
//Allows to pass in any number and types of parameters
public static void Program(params object[] args)
A typical usecase would be passing parameters in a command line environment to a program, where you pass them in as strings. The program has then to validate and assign them correctly.
Restrictions:
Only one params keyword is permitted per method
It has to be the last parameter.
EDIT: After I read your edits, I made mine. The part below also covers methods to achieve variable numbers of arguments, but I think you really were looking for the params way.
Also one of the more classic ones, is called method overloading. You've probably used them already a lot:
//both methods have the same name and depending on wether you pass in a parameter
//or not, the first or the second is used.
public static void SayHello() {
Console.WriteLine("Hello");
}
public static void SayHello(string message) {
Console.WriteLine(message);
}
Last but not least the most exiting one: Optional Arguments
//this time we specify a default value for the parameter message
//you now can call both, the method with parameter and the method without.
public static void SayHello(string message = "Hello") {
Console.WriteLine(message);
}
http://msdn.microsoft.com/en-us/library/dd264739.aspx

C# supports variable length parameter arrays using the params keyword.
Here's an example.
public static void UseParams(params int[] list)
{
for (int i = 0; i < list.Length; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine();
}
There's more info here.

Yes, params:
public void SomeMethod(params object[] args)
params has to be the last argument and can be of any type. Not sure if it has to be an array or just an IEnumerable.

I assume you mean a variable number of method parameters. If so:
void DoSomething(params double[] parms)
(Or mixed with fixed parameters)
void DoSomething(string param1, int param2, params double[] otherParams)
Restrictions:
They must all be the same type (or of a child type) as is true for arrays as well
There can only be one for each method
They must come last in the parameter list
That's all I can think of at the moment though there could be others. Check the documentation for more information.

Related

How does params work in c# (One method allegedly hiding another) [duplicate]

This question already has answers here:
How does C# choose with ambiguity and params
(3 answers)
Closed 8 years ago.
How does c# make params work.
When you have code like
static string Concat(int arg)
{
return arg.ToString();
}
static string Concat(int arg, params string[] p)
{
string result = string.Empty;
result = result + arg.ToString();
foreach (var s in p)
{
result = result + s;
}
return result;
}
Resharper says the method with params hides the other method. Does this imply that under the hood The other method is being defined and calling the one with params passing in an empty array? Or something else entirely?
(please don't get bogged down on the crappy code - its just an example)
Edit to explain:
If i do not define the static string Concat(int arg) method i can still call the second as
var s = Concat(123);
despite that method not being defined .... so the question is: is the first method defined implicitly under the hood and calling the second with an empty array. Note i changed the arg type from string to int.
to explain the weirdness as i see it. When you call as above ... it hits the params object with an empty array, the param is not null - which is what i expected. When i first wrote that foreach loop i had a null check on params then discovered i didn't need it.
So ... you reason that it must be wrapping any params after the first parameter in an array right? A little bit of inlined code? ... so if you passed in "dave" you would get freddave as the output ....
However pass null into it ....
static void Main(string[] args)
{
Console.WriteLine(Concat("fred",null));
}
//static string Concat(string arg)
//{
// return arg;
//}
static string Concat(string arg, params int[] p)
{
string result = string.Empty;
result = result + arg;
if (p != null)
{
foreach (var s in p)
{
result = result + s.ToString();
}
}
return result;
}
and you discover in this case p is actually null ...
If you do that with the string example ... id of expected an array with 1 element of null ... instead the entire params object is null.
I think calling it "hiding" is misleading here, to be honest.
Both methods are definitely created, but if you call:
Concat(5);
then for that invocation both methods are applicable (in the terminology of the C# spec section 7.5.3.1) but the first method is better (section 7.5.3.2) because of this:
Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ.
So in that case, the first method would be called.
The second method cannot be called using params expansion without specifying at least one string. It can still be called with an empty array, of course:
Concat(5, new string[0]);

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

Function with variable number of arguments

As the title says I need to know if there is a corresponding syntax as java's ... in method parameters, like
void printReport(String header, int... numbers) { //numbers represents varargs
System.out.println(header);
for (int num : numbers) {
System.out.println(num);
}
}
(code courtesy of wikipedia)
Yes you can write something like this:
void PrintReport(string header, params int[] numbers)
{
Console.WriteLine(header);
foreach (int number in numbers)
Console.WriteLine(number);
}
Try using the params keyword, placed before the statement, eg
myFunction(params int[] numbers);
Yes, there is. As Adriano said you can use C# 'params' keyword.
An example is the in link below:
params (C# Reference)
http://msdn.microsoft.com/en-us/library/w5zay9db.aspx
"The params keyword lets you specify a method parameter that takes a variable number of arguments.
You can send a comma-separated list of arguments of the type specified in the parameter declaration, or an array of arguments of the specified type. You also can send no arguments.
No additional parameters are permitted after the params keyword in a method declaration, and only one params keyword is permitted in a method declaration."
You can declare a method to har a variable number of parameters by using the params keyword. Just like when using ... in Java, this will give you an array and let you call the metods with a variable number of parameters:
http://msdn.microsoft.com/en-us/library/w5zay9db(v=vs.71).aspx
This should be
void printReport(String header, params int[] numbers)
I believe you mean params
public void printReport(string header, params int[] list)
{
Console.WriteLine(header);
for (int i = 0 ; i < list.Length; i++)
{
Console.WriteLine(list[i]);
}
Console.WriteLine();
}
You can use params, although this must always come last in the list:
public void PrintReport(string header, params int[] numbers)
{
It is however possible to combine params optional parameters (such as [CallerMemberName]) by using named arguments, which works even if the parameters are of the same type.
Declare the method like this:
public static void PrintReport(
[CallerMemberName] string callerName = "",
[CallerFilePath] string sourceFilePath = "",
params string[] inputStrings)
{
and call it like this:
PrintReport(inputStrings: new[] { "string 1", "string 2" } );

Converting to Enum using type variable

Part of my software is using reflection. The issue I am having is that while I can get the type of the property, I cannot convert the string value using the Type from the PropertyInfo. This is the reason why i am using t in the sample code.
The below code demonstrates the issue with the error message as a code comment. The syntax error is on the t. how can I fix this problem? thanks
class Program
{
static void Main(string[] args)
{
Type t = typeof(Letters);
Letters letter = "A".ToEnum<t>(); //-- Type or namespace expected.
}
}
public enum Letters { A, B, C }
//-- This is a copy of the EmunHelper functions from our tools library.
public static class EnumExt
{
public static T ToEnum<T>(this string #string)
{
int tryInt;
if (Int32.TryParse(#string, out tryInt)) return tryInt.ToEnum<T>();
return (T)Enum.Parse(typeof(T), #string);
}
public static T ToEnum<T>(this int #int)
{
return (T)Enum.ToObject(typeof(T), #int);
}
}
Solution:
The following works because when the value is set using reflection, the actual type of Enum is accepted. Where myObject.Letter = result is not.
Type t = currentProperty.PropertyType;
Enum result = Enum.Parse(t, #string) as Enum;
ReflectionHelper.SetProperty(entity, "LetterPropertyName", result);
Thank you all for your help.
Enum.Parse(t, #string) as Enum;
That accomplishes the same thing as the solution you posted.
To be able to call a generic method, the type must be known at compile time. Your use is invalid syntax.
To be able to call your method, you'll have to use reflection to get a reference to the correct generic function so you may call it.
public static object ToEnum(this string s, Type type)
{
var eeType = typeof(EnumExt);
var method = eeType.GetMethod("ToEnum", new[] { typeof(string) })
.MakeGenericMethod(type);
return method.Invoke(null, new[] { s });
}
Then you could call it:
Letters letter = (Letters)"A".ToEnum(t);
p.s., I strongly urge you to change your variable names to something else. Just because you can name your variables as keywords, doesn't mean that you should.
I'm not an expert with reflection, but this works:
static void Main(string[] args)
{
Type t = typeof(Letters);
MethodInfo info = typeof(EnumExt).GetMethod("ToEnum", new Type[] { typeof(string) });
var method = info.MakeGenericMethod(new Type[] { t });
var result = (Letters)method.Invoke(null, new [] { "A" });
Console.ReadLine();
}
I think your question can be understood in two ways:
i) you want to fix a syntax error
ii) you need a working implementation for the function you provide
For i), I would suggest you to change:
Letters letter = "A".ToEnum<t>()
into
Letters letter = "A".ToEnum<Letters>()
because generics are solved at compile time, hence you cannot use variables as parameters.
For ii), you may change the way you provide the type argument, from "generic" argument to "normal" argument (as proposed by Jeff Mercado). By doing so the prototype of your function becomes:
public static T ToEnum(this string #string, Type t)
I conclude with two remarks:
reflection is VERY slow to my experience. I once wrote an assembly parser making extensive use of reflection on enums for register names. It used to run for minutes (which used to make VS debugger complain about non-responsiveness) when an equivalent version without any reflection used to execute in less than 10 seconds.
as Jeff Mercado pointed out, I cannot see any good reason for you to use the same vocable for type names and variable names

C#: params keyword vs. list

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

Categories