Why use the params keyword?
With params
you can call your method like this:
addTwoEach(1, 2, 3, 4, 5);
Without params
, you can’t.
Additionally, you can call the method with an array as a parameter in both cases:
addTwoEach(new int[] { 1, 2, 3, 4, 5 });
That is, params
allows you to use a shortcut when calling the method.
Unrelated, you can drastically shorten your method:
public static int addTwoEach(params int[] args)
{
return args.Sum() + 2 * args.Length;
}
Why use the params keyword
Which of these calls to Console.WriteLine
do you find clearer?
Console.WriteLine("Hello {0}, you are {1}", person.Name, person.Age);
or
Console.WriteLine("Hello {0}, you are {1}",
new object[] { person.Name, person.Age });
(You can't even use implicitly typed arrays (new[]
) in the above case, unless either person.Name
or person.Age
is of type object
... If they were both of type string
you'd be okay, but it would create a string array...)
I prefer the first. It's simpler to read. That's all there is to params
- it just allows the callers to use more concise syntax. You can still pass an array reference in the normal way, as you do in your code - but you could also just write:
Prints("cs150", "cs250", "cs270", "cs300", "cs350");
... which again, is simpler to read than declaring a separate variable.
C#: params keyword vs. list
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.
What does params keyword in method signature really mean
Have you ever used Console.WriteLine
?
Console.WriteLine("{0}: The value of {1} is {2}.", lineNumber, foo, bar);
This sort of call is where params
can be useful. Having to explicitly construct an array to contain your parameters is just noise which makes the code harder to read without adding any value. Compare to the how it would look if params
weren't used:
Console.WriteLine("{0}: The value of {1} is {2}.", new object[] { lineNumber, foo, bar });
The second version adds no useful information to the code, and moves the values further from the format string, making it harder to see what is going on.
Is params Keyword supports with ValueTuple as a parameter C# 7.0?
A parameter array is a very specific language feature that is only applicable to method parameters. A value tuple is a struct with variable length generic parameters and has been given a special syntax for initialization and usage (most of which are just smoke an mirrors).
var asd = ("asd","asd");
Is basically just syntactic sugar for
ValueTuple<string, string> valueTuple = new ValueTuple<string, string>("asd", "asd");
There isn't even anything overly magical about named tuples.
var asd = (bob1 : "asd", bob2 : "asd");
Console.WriteLine(asd.bob1);
Basically converts to the following
ValueTuple<string, string> valueTuple = new ValueTuple<string, string>("asd", "asd");
Console.WriteLine(valueTuple.Item1);
So you are essentially asking, why you can't use params
in a tuple initializer syntax.
Well, as discussed, because a value tuple initializer actually isn't a method, and as much as it looks like it, the arguments you give it are not a method parameters. Tuple syntax is it's own very special language feature. However, you do have options.
So let's look at what you are trying to achieve. If you had a method parameter as such
public void Test((string arg1, params string[] args) tuple)
the only advantage would be you could supply a comma separated list.
Test(("bob","args1","args2","args3"));
Since we can't, your options are
Test(("bob",new []{"args1","args2","args3"}));
Or with some tomfoolery you could use an explicit operator on your own struct.
public readonly struct Testing
{
public Testing(ITuple x)
{
CategoryName = (string) x[0];
Properties = EnumerateTuple<string>(x).ToArray();
}
public Testing(string categoryName,string[] properties)
{
CategoryName = categoryName;
Properties = properties;
}
private static IEnumerable<T> EnumerateTuple<T>(ITuple x)
{
for (var i = 1; i < x.Length; i++)
yield return (T) x[i];
}
public string CategoryName { get; }
public string[] Properties { get; }
public static implicit operator Testing((string, string[]) x) => new Testing(x.Item1,x.Item2);
public static implicit operator Testing(string x) => new Testing(x, Array.Empty<string>());
public static implicit operator Testing((string, string) x) => new Testing(x);
public static implicit operator Testing((string, string,string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string, string, string) x) => new Testing(x);
public static implicit operator Testing((string, string, string, string, string, string, string, string, string, string, string, string) x) => new Testing(x);
}
Which would allow shenanigan's such as this
public static void Test(Testing something)
{
Console.WriteLine(something.Category);
Console.WriteLine(string.Join(", ", something.Properties);
}
private static void Main(string[] args)
{
Test("asd");
Test(("asd"));
Test(("asd", "args1"));
Test(("asd", "args1", "args2"));
Test(("asd", new []{"args1", "args2"}));
}
Note : This was only for academic purposes, I really wouldn't expect anyone to want to do this
What is a real example of when to use params as a method argument?
Math.Min
takes exactly two arguments. This is a stupid limitation. Many other languages allow you to write:
double x, y, z, w;
double least = min(x, y, z, w);
If you wanted to write a min
function that could be used like that, you'd want to use params
.
Can you use the params keyword in a delegate?
You can't have custom attributes on a generic type argument (the CLI doesn't permit it), and the C# compiler implements the params
keyword by emitting the System.ParamArrayAttribute
on the relevant method parameter.
This stops you from using it with the System.Func<...> generic delegates, but you can always create your own delegate type that does use params
.
Params vs. List T , When should I use params keyword and when to use List t
params
as it will give you the ability to pass in an array. It doesn't seem like you would want to pass in a list because that would give you extra functionality on the parameter that doesn't make sense. Like Add
for example.
Params keyword in JSON object
Use @params so you can escape special keywords
Related Topics
Why Do Assignment Statements Return a Value
How to Read a Specified Line in a Text File
How to Abort a Task Like Aborting a Thread (Thread.Abort Method)
How to Read a File Even When Getting an "In Use by Another Process" Exception
How Using Try Catch for Exception Handling Is Best Practice
Keeping ASP.NET Session Open/Alive
How to Get the Unix Timestamp in C#
Cannot Delete Directory with Directory.Delete(Path, True)
Get Connection String from App.Config
How to Change Network Settings (Ip Address, Dns, Wins, Host Name) with Code in C#
Resize Image Proportionally with Maxheight and Maxwidth Constraints
Save and Load Memorystream To/From a File
How to Dump Entire Objects to a Log in C#