-
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
LINQ Api support for static lambda's #45197
Comments
Tagging subscribers to this area: @eiriktsarpalis, @jeffhandley Issue DetailsBackground and MotivationC# 9 has support for static lambdas. They can avoid memory allocations. Wouldn't it be nice if the LINQ extension methods got an extra overload which support these. Proposed APIIn the example below I have created an extra overload for the FirstOrDefault() method. This is just an example, it should be optimized similar to the current implementation. The same solution (overloads) should also be added to all other methods like, Where(), Last(), Count(), etc. public static TSource FirstOrDefault<TSource, TState>(this IEnumerable<TSource> source, Func<TSource, TState, bool> predicate, TState state) {
foreach (var item in source) {
if (predicate(item, state)) return item;
}
return default;
} --> Usage ExamplesThe call of this overloaded FirstOrDefault() method would not allocate anything. var l = new List<Employee> {
new Employee("Fons", 2000),
new Employee("Jim", 4000),
new Employee("Ellen", 3000),
};
var limit = 3500;
var emp = l.FirstOrDefault(static (emp, limit) => emp.Salary > limit, limit);
Console.WriteLine(emp); The call of this current/normal FirstOrDefault() method will allocate 64 bytes (size of the delegate). var l = new List<Employee> {
new Employee("Fons", 2000),
new Employee("Jim", 4000),
new Employee("Ellen", 3000),
};
var limit = 3500;
var emp = l.FirstOrDefault(emp => emp.Salary > limit);
Console.WriteLine(emp); Alternative DesignsRisksThese methods should probably also be Entity Framework Core and other LINQ providers.
|
You still need to pay for overhead for indirect invoke here. When talking about LINQ's performance, only reducing closure allocation is typically not enough. |
Related: #19534 |
To clarify, the ability to add |
LINQ prioritizes convenience over performance, so I don't see much point in effectively doubling our API surface in order to avoid a few allocations. I'm also concerned about the ergonomics of applying this optimization in chained calls. It makes code look more convoluted and increases the probability of introducing bugs. Finally, it is not evident that the proposed alternative is necessarily faster. People could use heap allocated state objects (negating the point of the optimization) or large structs (which would need to be copied on each invocation). But even if you're careful, the state passing comes at a cost: consider this benchmark. |
I'm going to close this issue. Feel free to reopen if you would like to continue contributing to this conversation. |
Background and Motivation
C# 9 has support for static lambdas. They can avoid memory allocations. Wouldn't it be nice if the LINQ extension methods got an extra overload which support these.
Proposed API
In the example below I have created an extra overload for the FirstOrDefault() method. This is just an example, it should be optimized similar to the current implementation. The same solution (overloads) should also be added to all other methods like, Where(), Last(), Count(), etc.
-->
Usage Examples
The call of this overloaded FirstOrDefault() method would not allocate anything.
The call of this current/normal FirstOrDefault() method will allocate 64 bytes (size of the delegate).
A more complex example is the use of a ValueTuple for if you want to use multiple 'states'.
Alternative Designs
Risks
These methods should probably also be Entity Framework Core and other LINQ providers.
The text was updated successfully, but these errors were encountered: