Given the following struct:
struct Foo : IEnumerable<int>, IEnumerable<string> {
public IEnumerator<int> GetEnumerator() { yield return 1; }
public IEnumerator<string> IEnumerable<string>.GetEnumerator() {
yield return "One"
}
public IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
and the following generic method:
void Bar<TEnum, T>(TEnum iterable) where TEnum : IEnumerable<T> {
foreach (T item in iterable) Console.WriteLine(item);
}
I tried the following:
Foo foo = new Foo();
Bar<Foo, int>(foo); //prints 1
Bar<Foo, string>(foo); //prints One (How does this work)
foreach(int i in foo) Console.WriteLine(i); //prints 1
foreach (string s in foo) Console.WriteLine(s);
// Error: connot convert from string to int
Now my question would be: what code does the Compiler generate, when it evalueates these generics to a certain type? AFAIK the generic type would just be replaced with the concrete type. However as can be seen above, this wouldn't work for this example. So how can the compiler choose the correct type in the foreach? My only guess would be that it adds a cast to it. i.e.:
foreach(string item in (IEnumerable<string>)iterable) ...
But I chose to declare the Method like this to avoid a cast. Otherwise I could have just done it like this:
void Bar<T>(IEnumerable<T> iterable) { ... }
So I really hope it works without casting...
Edit: My question here is not why I get an error in the last foreach (I know that I can't access explicit interface implementations directly on the type), but how it works in the generic method, which AFAIK should evaluate to the exact same code as the last foreach.