Жалуется, потому что GetEnumerator () возвращает IEnumerator<T>
для интерфейса IEnumerable<T>
. Для удовлетворения ваш тип должен возвращать IEnumerator<T>
(и явный также для IEnumerator
).
Но во многих случаях желательно, чтобы класс возвращал более конкретный тип, чем тот, который указан в интерфейсе, но интерфейсы не допускают ковариантные типы возврата, подобные этому. Таким образом, чтобы сделать это, вы можете делать то, что List<T>
делает, и GetEnumerator()
возвращает ваш конкретный перечислитель, но вы также должны реализовать явные реализации для IEnumerable.GetEnumerator()
, которые возвращают IEnumerator
и для IEnumerable<T>.GetEnumerator()
который возвращает IEnumerator<T>
:
// This is your specific version, like List<T> does
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
// This is the one with the return value IEnumerator<T> expects
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator(this);
}
// Plus, it also expects this as well to satisfy IEnumerable
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
Если вы посмотрите на List<T>
, вы увидите, что он реализует GetEnumerator()
три раза:
- Однажды явно для
IEnumerable<T>
- Однажды явно для
Enumerable
- Однажды с очень специфичным для списка возвратом
Вы могли бы сделать то же самое в своем классе, если хотите (что, как он и задумал, это способ, которым вы начали), но если вы делаете это, вы должны явно реализовать IEnumerable<T>.GetEnumerator()
и IEnumerable.GetEnumerator()
Если вы перейдете к определению, вы можете увидеть другие определения в браузере объектов, выбрав различные интерфейсы, которым он удовлетворяет (или назначив экземпляр List<T>
для ссылки IEnumerable
или IEnumerable<T>
и перейдя к определению ):