EnumerableSelectIterator invokes selector in MoveNext() #99359
-
re: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/Select.cs I understand why invoking the selector function is necessary in iterators that use predicates. However, I must be missing the reason why this is necessary in the case of Select(). If Count() or Skip() is used on such an iterator, the result of the selector function is repeatedly assigned to a member field, and tossed on each subsequent call to MoveNext(). Wouldn't a more-lazy pattern that only sets a flag in MoveNext(), telling the getter for Current that it must invoke the selector be more-efficient? A conceptual distillation (sans error checks):
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Can you point to the existing line(s) of code you're asking about? |
Beta Was this translation helpful? Give feedback.
-
If the selector function throws, or has other side effects, those should be observed by Count(); etc. e.g. private static int s_count = 0;
...
var enumerable = data.Select(e => { s_count++; return e; });
enumerable.Count();
foreach (var item in enumerable)
{
...
} Changing the implementation to only invoke the selector when the item is being extracted would change the value of s_count produced by the above code. Furthermore, it would be quite surprising if A) private static int Count<T>(IEnumerable<T> data)
{
IEnumerable<T> enumerable = data.Select(selector);
int count = 0;
IEnumerator<T> iterator = enumerable.GetEnumerator();
while (iterator.MoveNext()) { count++; }
return count;
} and B) private static int Count<T>(IEnumerable<T> data)
{
IEnumerable<T> enumerable = data.Select(selector);
int count = 0;
foreach (T item in enumerable) { count++; }
return count;
} invoked the selector a different number of times. So, while it could improve performance; changing the number of times that a callback is called is a complicated breaking change (in the event of side effects) that we try really hard to avoid. |
Beta Was this translation helpful? Give feedback.
If the selector function throws, or has other side effects, those should be observed by Count(); etc.
e.g.
Changing the implementation to only invoke the selector when the item is being extracted would change the value of s_count produced by the above code. Furthermore, it would be quite surprising if
A)