sek w tym, ze jesli implementuje sie swoj pierwszy IEnumerable<>, to jest to ... nieoczywiste.
IEnumerable<X> to interfejs wymagajacy dostarczenia m.in GetEnumerator() -- i to zrobiles, jest ok.
Jednak, to co przegapiles to fakt, ze System.Collections.Generic.IEnumerable<X> dziedziczy po System.Collections.IEnumerable (inny namespace, i bez <X>) ktore z kolei wymaga, abyc zaimplementowal IEnumerator GetEnumerator() -- zwroc uwage, ze jest to INNA SYGNATURA niz tej metody ktora masz, ktora wymagalo IEnumerable<X> !
co wiecej... metoda ta sie nazywa tak samo i ma takie same (żadne) parametry - wiec jest jestes w przyslowiowek "*upie", gdyz nie mozesz napisac overloadow takich, aby spelnic oba interfejsy..
rozwiazaniem jest paskudny hack'o'ficzer jezyka C# ktory sie nazywa "explicit interface implentation" i wyglada tak:
Kopiuj
class Y : IEnumerable<X> // btw. pacnij prawym na IEnumerable i nacisnij "implement interface" :))
{
public IEnumerator<X> GetEnumerator() // normalna metoda implementujaca IEnumerable<X>::GetEnumerator
{
......
}
// ta metoda, #1, jest widoczna normalnie, gdy napiszesz obeiktT.GetEnumerator() czy this.GetEnumerator(),
// zwraca typowany IEnumerator<X>
IEnumerator System.Collecitons.IEnumerable.GetEnumerator()
// NIEnormalna metoda, PRYWATNA, implementujaca IEnumerable::GetEn,
// jedynie dostepna poprzez przerzutowanie obiektu na ten interfejs. NAWET THIS jej nie widzi normalnie!!!!
{
return this.GetEnumerator();
// i dlatego wlasnie to NIE wykona stackoverflow, tylko wywola metode #1,
// a my jestesmy happy, gdyz IEnumerator<X> przez nia zwracany implementuje takze NIEtypowany IEnumerator, ktory tutaj ta metoda ma generowac
}
// jesli chcialbys jednak wywolac metode #2, musialbys napisac ((System.Collections.IEnumerator)this).GetEnumerator()
}
IMHO, jest to skitrane, ale da sie przywyknac i nauczyc z tym żyć