'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.
16 comments
-
JMCF125 commented
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
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.
-
JMCF125 commented
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.
-
SamCPP
commented
You have the array functions:
http://msdn.microsoft.com/en-us/library/system.array_methods.aspxIs there something outside those?
-
JMCF125 commented
The benefit is inside the method; you can use all members of whatever list-like type you're using.
-
SamCPP
commented
Really not sure what you are gaining by this. What's wrong with getting an array?
-
JMCF125 commented
A solution looking for a problem? How?
-
Ermagerd
commented
This really seems more like a solution looking for a problem.
-
JMCF125 commented
What the **** happened to all the votes???
-
JMCF125 commented
Looks like someone just added 3 for your -3.
-
JMCF125 commented
"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
-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.
-
JMCF125 commented
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?
-
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.
-
JMCF125 commented
@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.
-
Mirality
commented
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.)