As I was refactoring some code this morning, I noticed some weird behavior. I was iterating over a collection of type A
. The declaration and usage of the Enumerable were split (I was declaring and defining a variable using some Linq, then iterating over it later via foreach). However, when I changed the type of the enumerable from IEnumerable<A>
to IEnumerable<B>
, I left the foreach as the following where enumerable was of type IEnumerable<B>
.
IEnumerable<B> enumerable = someEnumerableOfB
foreach(A a in enumerable)
Following is a contrived example of the behavior I found:
IEnumerable<IEnumerable> enumerables = Enumerable.Range(1, 5).Select(x => new List<int> { x });
foreach (StringComparer i in enumerables) //this compiles
{
//do something here
}
foreach (int i in enumerables) //this doesn't compile
{
//do something here
}
IEnumerable<StringBuilder> stringBuilders = Enumerable.Range(1, 5).Select(x => new StringBuilder(x.ToString()));
foreach (FileStream sb in stringBuilders) //this doesn't compile
{
//do something here
}
I was surprised to see the first one compile. Can someone explain exactly why this works? I assume it has something to do with the fact that the IEnumerable
is of an interface, but I can't explain it.