Coding interviews
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
int visits = 0;
IEnumerable<int> Source() { foreach (int x in new[] { 2, 4, 6 }) { visits++; yield return x; } }
var repeated = Source(); int sum = repeated.Sum(); int count = repeated.Count();
Console.WriteLine($"repeated:{sum}/{count};visits:{visits}");
visits = 0; int[] snapshot = Source().ToArray();
Console.WriteLine($"snapshot:{snapshot.Sum()}/{snapshot.Length};visits:{visits}");
Reveal answer and reasoning
The output lines, in order, are “repeated:12/3;visits:6”; “snapshot:12/3;visits:3”. Sum visits two, four and six, producing twelve; Count then visits those three values again, giving six visits overall. After resetting the counter, ToArray visits the source three times total and stores three integers. Sum over that array and Length do not execute the original iterator again. The printout measures visits, not allocations or elapsed time.
The local counter increments immediately before each yielded value, which makes it an observation of original-source production. It does not count later array reads. Writing down the two enumeration phases prevents a misleading conclusion that Count is always constant-time merely because it is constant-time for some collection implementations.
Both versions are O(n) in big-O time because two times n remains linear. The snapshot version allocates O(n) additional storage, whereas a fused one-pass sum-and-count loop can use O(1) auxiliary state for this task. Source cost and repeatability can matter more than the asymptotic label. A second enumeration might perform I/O again, observe changed values or be unsupported. Calling ToArray everywhere is not a free optimization: it changes evaluation timing and retains all items.
An array visit counter is evidence about traversal count, not proof of zero allocation or a performance benchmark.
What a strong answer covers
- Exact output: repeated:12/3;visits:6 | snapshot:12/3;visits:3
- Sum visits two, four and six, producing twelve; Count then visits those three values again, giving six visits overall.
- A second enumeration might perform I/O again, observe changed values or be unsupported.
Common pitfall
A second enumeration might perform I/O again, observe changed values or be unsupported. Calling ToArray everywhere is not a free optimization: it changes evaluation timing and retains all items. An array visit counter is evidence about traversal count, not proof of zero allocation or a performance benchmark.
Follow-up questions
- Replace the snapshot with one foreach loop that accumulates sum and count using checked arithmetic. Hint: no downstream consumer needs the individual elements here. Verify the same twelve and three while keeping source visits at three.
- What should happen if a one-shot source throws when a second enumerator is requested?
Self-review
Choose what to revisit. These marks are your own assessment and are separate from lesson completion.