i've read eric's article here foreach enumeration , different scenarios foreach can work
in order prevent old c# version boxing , c# team enabled duck typing foreach run on non- ienumerable collection.(a public getenumerator return has public movenext , current property sufficient(.
so , eric wrote sample :
class myintegers : ienumerable { public class myenumerator : ienumerator { private int index = 0; object ienumerator.current { return this.current; } int current { return index * index; } public bool movenext() { if (index > 10) return false; ++index; return true; } } public myenumerator getenumerator() { return new myenumerator(); } ienumerator ienumerable.getenumerator() { return this.getenumerator(); } } but believe has typos (missing accessor @ current property implementation) prevent compiling (i've emailed him).
anyway here working version :
class myintegers : ienumerable { public class myenumerator : ienumerator { private int index = 0; public void reset() { throw new notimplementedexception(); } object ienumerator.current { { return this.current; } } int current { { return index*index; } } public bool movenext() { if (index > 10) return false; ++index; return true; } } public myenumerator getenumerator() { return new myenumerator(); } ienumerator ienumerable.getenumerator() { return this.getenumerator(); } } ok.
according msdn :
a type
csaidcollection typeif implementssystem.collections.ienumerableinterface or implementscollection patternmeeting all of following criteria:
c contains public instance method signature getenumerator() returns struct-type, class-type, or interface-type, called e in following text.
e contains public instance method signature movenext() , return type bool.
e contains public instance property named current permits reading current value. type of property said element type of collection type.
ok. let's match docs eric's sample
eric's sample is said collection type because implements system.collections.ienumerable interface ( explicitly though). not(!) collection pattern because of bullet 3 : myenumerator not public instance property named current.
msdn says :
if collection expression of type implements collection pattern (as defined above), expansion of foreach statement is:
e enumerator = (collection).getenumerator(); try { while (enumerator.movenext()) { elementtype element = (elementtype)enumerator.current; statement; } } { idisposable disposable = enumerator system.idisposable; if (disposable != null) disposable.dispose(); } otherwise , collection expression of type implements system.ienumerable (!), , expansion of foreach statement is:
ienumerator enumerator = ((system.collections.ienumerable)(collection)).getenumerator(); try { while (enumerator.movenext()) { elementtype element = (elementtype)enumerator.current; statement; } } { idisposable disposable = enumerator system.idisposable; if (disposable != null) disposable.dispose(); } question #1
it seems eric's sample neither implements collection pattern nor system.ienumerable - it's not supposed match any of condition specified above. how come can still iterate via :
foreach (var element in (new myintegers() ienumerable )) { console.writeline(element); } question #2
why have mention new myintegers() ienumerable ? it's ienumerable (!!) , after , isn't compiler doing job via casting :
((system.collections.ienumerable)(collection)).getenumerator() ? it right here :
ienumerator enumerator = ((system.collections.ienumerable)(collection)).getenumerator(); try { while (enumerator.movenext()) { ... so why still wants me mention ienumerable ?
myenumerator not has required public methods
yes - or rather, if current public. that's required has:
- a public, readable
currentproperty - a public
movenext()method no type arguments returningbool
the lack of public here typo, basically. is, example doesn't it's meant (prevent boxing). it's using ienumerable implementation because you're using new myintegers() ienumerable - expression type ienumerable, , uses interface throughout.
you claim doesn't implement ienumerable, (which system.collections.ienumerable, btw) does, using explicit interface implementation.
it's easiest test sort of thing without implementing ienumerable @ all:
using system; class bizarrecollection { public enumerator getenumerator() { return new enumerator(); } public class enumerator { private int index = 0; public bool movenext() { if (index == 10) { return false; } index++; return true; } public int current { { return index; } } } } class test { static void main(string[] args) { foreach (var item in new bizarrecollection()) { console.writeline(item); } } } now if make current private, won't compile.
Comments
Post a Comment