Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the C# compiler use duck typing with foreach over a generic type?

It's been established that the compiler can do duck typing to remove some overhead when iterating over a List or an Array (see Duck typing in the C# compiler), as those types implement their IEnumerator as a stack-allocated struct.

Is this the case even when the type is generic, but constrained to implement IEnumerable?

To give more specifity, could option B run with less overhead than A?

A:

public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> collection)
{
    foreach (var subCollection in collection)
        foreach (var element in subCollection)
            yield return element;
}

B:

public static IEnumerable<T> Flatten<TList, T>(this TList collection)
    where TList : IEnumerable<IEnumerable<T>>
{
    foreach (var subCollection in collection)
        foreach (var element in subCollection)
            yield return element;
}
like image 491
Emanuel Strömgren Avatar asked Mar 04 '23 09:03

Emanuel Strömgren


1 Answers

No, basically. The only use for "B" is when the TList itself is actually a struct; the IL can then use "constrained call" to call the original GetEnumerator() without any part having to box the original struct TList value.

But: once you've called GetEnumerator(), you're back into IEnumerator<T> land, and it will not use the custom iterator.

All of which is mostly moot in this case, because iterator blocks are also fairly "allocatey". So... if avoiding boxing the TList is your concern, you are presumably obsessive about allocations: in which case you wouldn't write the iterator block this way, either.

like image 58
Marc Gravell Avatar answered Mar 20 '23 00:03

Marc Gravell