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.

187 votes
Vote
Sign in
Check!
(thinking…)
Reset
or sign in with
  • facebook
  • google
    Password icon
    I agree to the terms of service
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    JMCF125JMCF125 shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    19 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      Submitting...
      • Joe AmentaJoe 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.

      • SergeySergey commented  ·   ·  Flag as inappropriate

        Yes only for:
        IEnumerable<T>
        IReadOnlyCollection<T>
        IReadOnlyList<T>

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

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

      • JMCF125JMCF125 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 GrunwaldDaniel Grunwald commented  ·   ·  Flag as inappropriate

        I think this is a great idea; but it should allow only the following interfaces:
        IEnumerable[T]
        IReadOnlyCollection[T]
        IReadOnlyList[T]

        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.

      • JMCF125JMCF125 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.

      • JMCF125JMCF125 commented  ·   ·  Flag as inappropriate

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

      • SamCPPSamCPP commented  ·   ·  Flag as inappropriate

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

      • JMCF125JMCF125 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

        -3

        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.

      • JMCF125JMCF125 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?

      • Visual Studio TeamAdminVisual 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)
        f(1,2,3)
        ===> 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);
        f(tmp);

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

      • JMCF125JMCF125 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();
        l.Add(_1stElement);
        l.Add(_2ndElement);
        ...
        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.

      • MiralityMirality 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