Small perf tweaks for Select#11841
Conversation
Isn't this a breaking change? For example, consider this code: IEnumerable<string> GetStrings()
{
yield return "not int";
}
…
GetStrings().Select(int.Parse).Count();With the current implementation, this code throws Though this was already changed for arrays (e.g. |
| public override bool MoveNext() | ||
| { | ||
| if (_state == 1 && _index < _source.Length) | ||
| if (_state == 0 | _state == _source.Length + 1) |
There was a problem hiding this comment.
I used | to be consistent with other parts of the LINQ codebase where bitwise instead of logical operators are being used, e.g. here. Since it will be very rare for _state to be 0 (only happens when someone casts the result of Select to an IEnumerator) this will save us a branch.
|
@svick Yeah, it could be considered breaking if the input is lazy and the selector has side effects, such as throwing an exception/mutating state. As you pointed out, though, this has already been changed for arrays/lists/other LINQ iterators so I thought we might as well do it here too. If someone wants to force evaluation of the selector then they are more likely to use a |
|
Test Innerloop Ubuntu14.04 Release Build and Test |
|
LGTM |
Small perf tweaks for Select Commit migrated from dotnet/corefx@9c784ce
Selectcall) so we can return a cached result.ToArray,TryGetFirstandTryGetLastfor specially handling empty arrays._state - 1can be used as the index into the array instead of a separate_indexfield. This leaves only 2 pointer-sized fields inSelectArrayIterator.Count()aSelectEnumerableIterator, we don't have to run the selector on each element of the sequence.cc @stephentoub @JonHanna @VSadov