-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add new overloads for Select and other LINQ methods #34553
Comments
Tagging @eiriktsarpalis as an area owner |
This is what I like to call "the |
Func<int, string> MakeStringWrapper(bool toLower) => x => MakeString(x, toLower)
var results2 = Enumerable.Range(1, 10).Select(MakeStringWrapper(toLower)); This is no better than 1. in regards to allocations and worse in readability, this just moves the closure allocation to the expression The only true allocation free solution is the explicit
|
@Suchiman Yep, you are right. I somehow overlooked that. I quickly wrote the example code in LINQPad 6 (free edition) so I didn't see any warnings. Next time I'll use VS or VS Code 😄 IMHO having a few overloads would be great. Covering all the cases up to arity of 3 means 5 more overloads. |
Considering that LINQ is inherently fairly allocation-heavy, would this actually significantly decrease the allocations? |
My feeling is that if allocations are a source of concern, then you shouldn't be using LINQ in the first place. For the particular issue you bring up, I believe it is almost always the case that you could refactor the code in a way such that only one closure is allocated, the one being passed to the Given that we'd probably also need to support arities > 2, and the fact that it can be implemented trivially as an extension method like you demonstrated, I don't believe there would be a lot of value in adding this to the main API, though happy to be corrected. |
@eiriktsarpalis Yes, I could write the code so that I have only 1 closure allocated. This is not pressing. Thanks for looking into this. |
@AjayKMehta thank you for your proposal I agree with all the points that @eiriktsarpalis has made and having said that I am going to close the issue. |
Currently, if you want to use a partially applied version of a function of arity greater than one (e.g.
Func<T, A, R>
) in a call toSelect<T, R>(IEnumerable<T>, Func<T,R>)
where the argument of typeA
is a local variable, you have 2 options, neither of which is great.To illustrate these 2 options, consider the contrived example where you have the function defined below and want to use this in a call to
Select
for anIEnumerable<int>
:This is not too bad since C# now supports local functions so you no longer have to pollute your code with private helper methods but this is still not ideal.
I propose adding an overload as an improvement over both these options:
Simplified implementation (I get that actual implementation is more complex and specialized based on runtime types) would look like:
This is not a fringe issue as I have seen this a lot in LINQ code in the wild. Similar overloads could be added for other LINQ methods like
GroupBy
,OrderBy
.More overloads could possibly be added for the case where parameter order is switched for
selector
, i.e.Func<TArg,TSource,TResult>
instead ofFunc<TSource,TArg,TResult>
as shown above and for more arities.The idea for this came from thinking of how adding
*args
and/or**kwargs
to function signatures in Python addresses this situation 😀The text was updated successfully, but these errors were encountered: