I suggest you ...

'params' keyword for every list

If you're a C# developer, I bet you've used something like this before:

***** SomeType DoSomething(params AnotherType[] array){...}

It is a lot easier to use the 'params' modifier than to create a new array with all the paremeters of the same type you want to insert in a method, specially when it comes to small test projects.

However, using this comes with a disadvantage: you MUST use the array type. No IList, List<T>, Dictionary<TKey, TValue>, etc.. I believe there is no such reason not to allow these list-like types to use the params keyword. Example:

***** SomeType DoSomething(params ListType list){...}

Of course you may wonder how is the compiler going to know witch types to accept. Well, for that I have several suggestions: there may be an obligation to derive it from IList<T> or to have at least one indexer... I don't know. What I do know is that this would be a good feature.

190 votes
Sign in
Password icon
Signed in as (Sign out)
You have left! (?) (thinking…)
JMCF125 shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →


Sign in
Password icon
Signed in as (Sign out)
  • Joe Amenta commented  ·   ·  Flag as inappropriate

    I approve of params IEnumerable<T> as a counterpart to params T[], and I approve of having this be the only new "params type". While "params IReadOnlyCollection<T>" / "params IReadOnlyList<T>" would be marginally useful in narrow circumstances where we'd like to know the number of elements or access them by index, a "try-cast" approach could be done with a "params IEnumerable<T>" solution to get this behavior where available without terrible grief.

    "params IEnumerable<T>" solves a significant wart with the current "params T[]" approach. If I want to have a method with "params" goodness but also loop over the input lazily, I need to have one overload that takes "IEnumerable<T>" (no "params") and an overload that takes "params T[]", where the latter probably just calls the former. This is ugly. With "params IEnumerable<T>", I would write just one method that does everything I want.

  • Sergey commented  ·   ·  Flag as inappropriate

    Yes only for:

    void f(params IReadOnlyList<int> args) {...}

    ===> the compiler internally recognizes this pattern and generates
    f(new int[] {1,2,3})

  • JMCF125 commented  ·   ·  Flag as inappropriate

    params IEnumerable<T> on its own would be fine by me. Every custom list-like type I've created so far derives at the very least from it, so the autoimatic mplicit cast makes my original idea possible.

  • Daniel Grunwald commented  ·   ·  Flag as inappropriate

    I think this is a great idea; but it should allow only the following interfaces:

    These three are implemented by arrays, so the compiler can just pass in a simple array at the call site. And they don't allow the method to pass any modifications back to the caller.

    The current workaround is to use two overloads - one that accepts the interface type, and one that accepts arrays only so that it can use params.

  • JMCF125 commented  ·   ·  Flag as inappropriate

    Some of the members of List<T> are outside those (althought extension methods in System.Linq.Enumerable class complement them, but not completely). And what if someone makes another list-like class, which I consider relatively frequent, how will that person be able to simply write the mebers to make a new list?

    Of course it's possible, the purpose is to add a bit of syntatic sugar, like operators. Yes, we all know we could have int.Add(int.Add(a, b) ,c) to add the 32 bit integers a, b and c, however, we all prefer to use a + b + c.

  • JMCF125 commented  ·   ·  Flag as inappropriate

    The benefit is inside the method; you can use all members of whatever list-like type you're using.

  • SamCPP commented  ·   ·  Flag as inappropriate

    Really not sure what you are gaining by this. What's wrong with getting an array?

  • JMCF125 commented  ·   ·  Flag as inappropriate

    "Why should I need...": that's an hateful anti-progressive argument. Why should you need classes? You can write it all with simple intructions in assembly language. The purpose of classes is to simplify your work. I could generalize: many great ideas came from the pettiest things. This is an extreme example, I'm not saying params for lists is even NEARLY as important as classes, but it is a simple little tool like many others.

    These small tools are the ones that make a language. "Oh, we don't need this and that, so lets remove it." In the end you get a toolbox with a hammer but no nails. Good small things make a great big language.

    If this is about the immutability of the elements of the list, there's a propertie in System.Collections.Genric.ICollection<T> called IsReadOnly. If you try to reassign such object, an error will come up.

  • Anonymous commented  ·   ·  Flag as inappropriate


    Number of arguments to 'params' array is known at compile time, and the array is immutable. So why should I need 'params IEnumerable<T>' or a list? Read the sources of .NET, List<T> is internally backed up by an array, so you just want bloat.

  • JMCF125 commented  ·   ·  Flag as inappropriate

    Yes, you're right, it would be too expensive that way. However, couldn't the List<T> be converted to an array (since the System.Array type derives at least from System.Collections.IList) in which the elements would be created (like in your 1st example, for IEnumerable<int>) and then be converted back to IList<T>?

    Yet rejecting that hypothesis, you could at least accept, as you said, the IEnumerable and IEnumerable<T>. Is that ok?

  • AdminVisual Studio Team (Product Team, Microsoft Visual Studio) commented  ·   ·  Flag as inappropriate

    We've been kicking around the idea of allowing precisely two things:
    params T[]
    params IEnumerable<T>

    Rationale: "params T[]" is already in the language, and IEnumerable<T> is pretty much the standard type that everything uses. Here's an example:

    void f(params IEnumerable<int> args)
    ===> the compiler internally recognizes this pattern and generates
    f(new int[] {1,2,3})

    Note: if we allowed arbitrary list types such as IList<T>, then the callee would naturally believe that it could add/remove elements, which would make it more costly. The compiler would have to generate something like this:
    var tmp = new List<int>();
    tmp.Add(1); tmp.Add(2); tmp.Add(3);

    This is more overhead than is nice to see in a language feature.

  • JMCF125 commented  ·   ·  Flag as inappropriate

    @Mirality, I see your point, but that way your not taking advantage of the 'params' modifier. I mean, with a method like this:

    SomeType DoSomething(params ListType list){...}

    Doing this:

    SomeType a = DoSomething(_1stElement, _2ndElement, etc.);

    Instead of this:

    ListType l = new ListType();
    SomeType b = DoSomething(l);

    Being all of the parameters of DoSomething (the following: _1stElement, _2ndElement, etc.) "addable" (with Add method of IList<T> or IList) to the list. Now compare the 2 ways of applying the method. Which one do you prefer? I certanly prefer the first, although they do basicallly the same. In the way you said it, it would be impossible. That's why I want to make it possible, it's just better.

    Any replies to the post or the comment itself, please post them.

  • Mirality commented  ·   ·  Flag as inappropriate

    You can do that yourself with overloading.

    SomeType DoSomething(params AnotherType[] array)

    SomeType DoSomething(IList<AnotherType> list)
    return DoSomething(list.ToArray());

    (Or you can go the other way with ToList(), if you prefer.)

Feedback and Knowledge Base