-
Notifications
You must be signed in to change notification settings - Fork 416
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
Flatten consecutive chaining of Concat & Prepend #319
Conversation
I like the idea, but the implementation is problematic due to the shared buffer: var firstSequence = new [] { 1, }.Concat(2);
var second = firstSequence.Concat(3);
var third = firstSequence.Concat(4);
third.Dump(); // prints 1, 2, 4
second.Dump(); // also prints 1, 2, 4 Usually LINQ operators are immutable, in that applying an additional operator does not alter the source sequence, and this PR breaks this expectation. |
Using ImmutableList would fix the issue, but that would add a dependency. |
@fsateler That's a great catch! Pity that the tests didn't pick it up. Goes to show you'll always miss something so thanks for the review. BTW, |
@fsateler I have added tests and fixed the sharing bug. The implementation may be suboptimal, especially for concatenations, but that can be tweaked and improved with time (unless you have some suggestions right away). |
- Use pre-allocated array as count is known - Skip array allocation for <= 4 concatenations
@fsateler Are you happy with this now? |
@fsateler I want to get this into the June release that I was planning for today. I'm assuming you haven't found the time to finish your review but I'll go ahead and merge nonetheless and if you see a glaring issue later then it can always be addressed in a 2.6 patch version. |
This PR optimises
Prepend
andConcat
such that if they are chained to the same operation or either operation in succession then there's a flat (as opposed to nested today) iteration that takes place.Before this PR, calling
xs.Prepend(2).Prepend(1).Concat(10)
will create 3 distinct enumerables, which when iterated will make nested (MoveNext
) calls into each iterator. Done in a loop (e.g.xs = xs.Concat(x);
and the iteration performance will explode. With this PR, there will be a single enumerable resulting across all consecutive calls and the final iteration will be flat (a single call throughMoveNext
).