1

Why is Square() being called again in the code below? I suppose values is being recalculated, but why? We got the values earlier, why is it being called again? Why does the compiler issue a warning "Possible multiple enumeration"?

static IEnumerable<int> Square(IEnumerable<int> a)
{
    foreach(var r in a)
    {
        Console.WriteLine($"From Square {r * r}");
        yield return r * r;
    }
}
class Wrap
{
    private static int init = 0;
    public int Value
    {
        get { return ++init; }
    }
}

static void Main(string[] args)
{
    var w = new Wrap();
    var wraps = new Wrap[3];
    for(int i=0; i<wraps.Length; i++)
    {
        wraps[i] = w;
    }

    var values = wraps.Select(x => x.Value);
    var results = Square(values);
    int sum = 0;
    int count = 0;
    foreach(var r in results)
    {
        count++;
        sum += r;
    }
    Console.WriteLine("Count {0}", count);
    Console.WriteLine("Sum {0}", sum);

    Console.WriteLine("Count {0}", results.Count());
    Console.WriteLine("Sum {0}", results.Sum());
}

Results:

From Square 1
From Square 4
From Square 9
Count 3
Sum 14
From Square 16
From Square 25
From Square 36
Count 3
From Square 49
From Square 64
From Square 81
Sum 194
Drompai
  • 111
  • 1
  • 7
  • That is fundamentally how [`yield`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/yield) works in C#. There is a lot to say, but basically, the values of the enumeration or only produced "on demand": each time the calling code "needs" a new value, a new one is created (your function is called). Simply assigning the result of your function to a local variable does not do that, but only when you actually access the "content" of the enumerable itself ("materialize" it). – Christian.K Jun 27 '22 at 14:04

1 Answers1

1

Square(values) returns an IEnumerable, which is iterated over (called) each time it is accessed.

If you cast the result to a List(), the results are concreted into a List().

var results = Square(values).ToList();

Results with .ToList()

From Square 1
From Square 4
From Square 9
Count 3
Sum 14
Count 3
Sum 14
Morphed
  • 3,527
  • 2
  • 29
  • 55
  • Why aren't we iterating on `results`? I mean `Square()` has already returned `IEnumerable`, why are we calling something else. I probably don't fully understand how `IEnumerable` works. – Drompai Jun 27 '22 at 14:20
  • Think of `IEnumerable` as 'something that _can_ be iterated over'. Upon every access it is iterated over. Formally, `IEnumerable` is lazy, while a `List` is eager – Morphed Jun 27 '22 at 14:23