views:

428

answers:

8

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.

+2  A: 

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.

Michael Bray
what about performance issues?
Yaron Naveh
This isn't the type of issue that you really should be worrying about performance - I'm sure there are much larger performance hogging problems in whatever you are considering. The performance is virtually the same, because of the fact (I think) that it's mainly just a compiler syntax, and has nothing to do with the way the function itself gets called once it's in IL.
Michael Bray
A: 

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});
Secret Agent Man
what about performance issues?
Yaron Naveh
+2  A: 

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

Lucero
what about performance issues?
Yaron Naveh
What about them?
Anon.
+1 for IList<T>, or any other relevant interface depending on what your collection needs to do.
Joe Lloyd
If you only need to enumerate the items, then IEnumerable<T> is a better choice than IList<T>, allowing you to pass in a bunch of different collection implementations as well as LINQ query results, etc.
X-Cubed
A: 

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.

Igor Zevaka
A: 

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");
Kris Krause
Also, the params "smells" like it used frequently for Interop.
Kris Krause
Well, you wouldn't have that problem if you grouped your defined members in a single object, like `Credentials`.
Dynami Le Savard
Dynami, you are absolutely correct. Bad code... bad use of params.
Kris Krause
A: 

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.

Joe Lloyd
+2  A: 

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);
    }
}
Orion Edwards
That's because List creation time is slow. if you call A method that takes IEnumerable with say, a string[] instead of a List<string> the performance would be nearly equivalent to the params method.
Jimmy
Sure it would, but it doesn't matter!
Orion Edwards
+3  A: 

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.

Jimmy