Robię co w mojej mocy, aby kodować na interfejsy, gdy tylko jest to możliwe, ale mam pewne problemy, jeśli chodzi o kolekcje. Na przykład tutaj mam kilka interfejsów, których chciałbym użyć.Wyraźna implementacja interfejsu GetEnumerator interfejsu powoduje przepełnienie stosu
public interface IThing {}
public interface IThings : IEnumerable<IThing> {}
Oto przykłady wdrożeń. Aby wdrożyć IEnumerable <IThing> muszę jawnie implementować IEnumerable <IThing> .GetEnumerator() w Things.
public class Thing : IThing {}
public class Things : List<Thing>, IThings
{
IEnumerator<IThing> IEnumerable<IThing>.GetEnumerator()
{
// This calls itself over and over
return this.Cast<IThing>().GetEnumerator();
}
}
Problem polega na tym, że implementacja GetEnumerator powoduje przepełnienie stosu. Powtarza się w kółko. Nie mogę dowiedzieć się, dlaczego zdecydowałby się nazwać tę implementację GetEnumerator zamiast implementacji dostarczonej przez wynik tego .Cast <IThing>(). Jakieś pomysły, co robię źle? Jestem gotów się założyć, że to coś bardzo głupie ...
Oto niektóre proste kodu testu dla powyższych klas:
static void Enumerate(IThings things)
{
foreach (IThing thing in things)
{
Console.WriteLine("You'll never get here.");
}
}
static void Main()
{
Things things = new Things();
things.Add(new Thing());
Enumerate(things);
}
Oooh, dobrze. To czyni oczywistym, że base.GetEnumerator() powinien działać, jeśli zrozumiał kowariancję i contravaraince jak Frank powiedział. Ale ponieważ tak nie jest, robi to całkiem dobrze! – Joe
tak, C# 4 będzie wielki:^p również, byłem zaskoczony, że "((Lista) to) .Cast () .GetEnumerator();" nie działało: s –
Stormenet
Po obejrzeniu reflektora oczywiste jest, dlaczego Cast nie działa. Zasadniczo rzuca każdy z elementów pojedynczo, jeśli musi. W tym przypadku widzi, że "to" jest niezliczone, więc po prostu to zwraca. To zbyt mądre dla własnego dobra. :) –
Joe