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.
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 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.
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()
).
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("[email protected]", "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.
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);
}
}
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.