C# .NET Unexpected Typing - Expanded foreach explanation -
as refactoring code morning, noticed weird behavior. iterating on collection of type a. declaration , usage of enumerable split (i declaring , defining variable using linq, iterating on later via foreach). however, when changed type of enumerable ienumerable<a> ienumerable<b>, left foreach following enumerable of type ienumerable<b>.
ienumerable<b> enumerable = someenumerableofb foreach(a in enumerable) following contrived example of behavior found:
ienumerable<ienumerable> enumerables = enumerable.range(1, 5).select(x => new list<int> { x }); foreach (stringcomparer in enumerables) //this compiles { //do here } foreach (int in enumerables) //this doesn't compile { //do here } ienumerable<stringbuilder> stringbuilders = enumerable.range(1, 5).select(x => new stringbuilder(x.tostring())); foreach (filestream sb in stringbuilders) //this doesn't compile { //do here } i surprised see first 1 compile. can explain why works? assume has fact ienumerable of interface, can't explain it.
according algorithm described section §15.8.4. of specification, compiler expand foreach following:
{ ienumerator<ienumerable> e = ((ienumerable<ienumerable>)(x)).getenumerator(); try { stringcomparer v; while (e.movenext()) { v = (stringcomparer)(ienumerable)e.current; // (*) // here } } { // dispose of e } } the line i've marked asterisk reason why compiles first , not second. valid cast because can have subclass of stringcomparer implements ienumerable. change to:
v = (int)(ienumerable)e.current; // (*) and doesn't compile, because not valid cast: int not implement ienumerable, , can't have subclasses.
Comments
Post a Comment