Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

params TCollection<T> #2141

Closed
TonyValenti opened this issue Jan 14, 2019 · 11 comments
Closed

params TCollection<T> #2141

TonyValenti opened this issue Jan 14, 2019 · 11 comments

Comments

@TonyValenti
Copy link

Hi All,
I've seen different requests for params IEnumerable and such and I had a though I wanted to share.
Right now params requires a single dimension array. What if Params would allow any type with a default constructor and collection initializer method/extension methods?

private void MyMethod(params List<int> Items){ ... }

MyMethod(1,2,3,4,5);

Could be transformed by the compiler into:

MyMethod(new List<int>(){
  1,2,3,4,5
});

This would basically give people the ability to determine the type of params they want. LinkedList, List, HashSet, etc.

#1366
#619
#1757
#178

@YairHalberstadt
Copy link
Contributor

YairHalberstadt commented Jan 14, 2019

How would you create a params of an interface. Specifically IEnumerable?

@TonyValenti
Copy link
Author

@YairHalberstadt Because interfaces are not types, you cannot create them. This is no different than everywhere else in the framework. That's why you specifically provide a concrete type that implements your ideal preference of IEnumerable.

So, depending on your situation, you might want to do any of the following:

private void MyMethod(params List<int> Items){ ... }
private void MyMethod(params LinkedList<int> Items){ ... }
private void MyMethod(params HashSet<int> Items){ ... }

In all three of those situations, Items is IEnumerable and it gives me the advantage of being able to pick the specific implementation of IEnumerable that best fits my needs.

@YairHalberstadt
Copy link
Contributor

@TonyValenti
But what if I want to accept any IEnumerable in my method, or allow the user to use params?

That would be the advantage of allowing params IEnumerable instead.

I do like your proposal, and I think it is probably better than allowing IEnumerable params, I'm just raising a potential limitation with it.

@bbarry
Copy link
Contributor

bbarry commented Jan 14, 2019

A method shouldn't dictate the concrete type of parameters that it is using though beyond what is necessary to implement the algorithm that the method is encapsulating. And that encapsulation never includes the construction of the parameter because that happens outside of the method call.

@YairHalberstadt
Copy link
Contributor

A method shouldn't dictate the concrete type of parameters that it is using though beyond what is necessary to implement the algorithm that the method is encapsulating. And that encapsulation never includes the construction of the parameter because that happens outside of the method call.

Meh

That's more of a heuristic than a hard and fast rule. Over here I think there is very little harm that would cause, and the benefit outways any code purity concerns I have.

@TonyValenti
Copy link
Author

@bbarry, while I do agree with you, params functions differently than most because, in its current implementation, params is a shortcut for new[] { ... } . Currently, you still have to specify the type, however, presently, the only available type is an array.

@YairHalberstadt
I'm not sure what you mean by 'allow the user to use params'.

If I have:

private void MyMethod(params HashSet<int> Items){ ... }

I should still be able to call it using any of the following methods:

MyMethod();
MyMethod(1,2,3,1,2,3,1,2,3,4); //Note that this would collapse to 1,2,3,4 since I'm backing with a hashset.  Cool!)
MyMethod(new HashSet<int>(){1,2,3});

I do suppose that it could be agreed that something like:

private void MyMethod(params IEnumerable<int> Items){ ... }

Would result in a call-site transformation to List if the 'params' items are listed.
For example:

private void MyMethod(params IEnumerable<int> Items){ ... }

MyMethod(1,2,3,4,5);
//Becomes MyMethod(new List<int>(){1,2,3,4,5});

MyMethod(new HashSet<int>(){1,2,3,4,5});
//Stays the same.

@YairHalberstadt
Copy link
Contributor

Also not that params T[] would be inconsistent, as it doesn't have a default constructor, nor a usable add method.

However I don't think that's a genuine issue, as it's already special cased for collection initialisers.

@bartdesmet
Copy link

Also linking #179 which has a link to a proposal for a builder pattern to construct params collections. This can help to construct types such as ImmutableArray<T> more efficiently, by leveraging the compile-time knowledge of the length and by emitting calls against a builder pattern that can avoid copies. In a way, it goes beyond just calling Add for initializers, which are subject to dynamic resizing of the collection. E.g. constructing a List<T> using params would benefit from getting the length fed in to the capacity parameter on the constructor.

@SilentSin
Copy link

It gets a bit verbose, but the params keyword could take a type in the same way default does:

private void MyMethod(params(List<int>) IEnumerable<int> Items){ ... }

That would allow you to pick the most efficient enumerable type for your particular algorithm rather than always using the same default. Users could even consider that as a useful hint on which type works best with your method in case they are constructing their own collection.

@HaloFour
Copy link
Contributor

@SilentSin

What collection would be more efficient than an array? Per #179 that's what the client would generate. Your suggestion would make the feature vastly more complicated and I don't see any benefit to it.

@333fred
Copy link
Member

333fred commented Sep 26, 2022

Converting to a discussion. This should be considered as part of #179.

@dotnet dotnet locked and limited conversation to collaborators Sep 26, 2022
@333fred 333fred converted this issue into discussion #6491 Sep 26, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants