Можем ли мы использовать GetEnumerator() без использования интерфейса IEnumerable?

У меня есть класс Primes, и этот класс реализует GetEnumerator() без реализации интерфейса IEnumerable.

public class Primes
{
    private long min;
    private long max;

    public Primes()
        : this(2, 100)
    {
    }

    public IEnumerator GetEnumerator()
    {...}

Я не понимаю. Я что-то упускаю?


person Bon_chan    schedule 25.05.2010    source источник


Ответы (4)


Во-первых, как говорили другие, вы все равно можете вводить свои собственные методы без реализации интерфейсов - вы можете написать свой собственный метод Dispose без реализации IDisposable и т. д. Для известных интерфейсов я бы сказал, что это почти плохая идея (поскольку читатели будут иметь определенные ожидания), но это полностью справедливо.

Что еще более важно, оператор foreach в C# может работать без участия IEnumerable. Компилятор эффективно выполняет утиную печать во время компиляции для имен GetEnumerator(), Current и MoveNext(). В первую очередь это было сделано для того, чтобы разрешить строго типизированную (и неупаковочную) итерацию в C# 1 до дженериков. Дополнительные сведения см. в разделе 8.8.4 спецификации C# 3.

Однако, как правило, это плохая идея делать это сейчас, если вы делаете хотите иметь возможность легко перебирать содержимое экземпляра как коллекции - и действительно, я бы предложил реализовать IEnumerable<T> вместо просто IEnumerable .

person Jon Skeet    schedule 25.05.2010
comment
На самом деле может быть хорошей* идеей пропустить интерфейсы, если ваш перечислитель является struct. Реализуя интерфейсы, вы позволите разработчику непреднамеренно ввести бокс вашего перечислителя везде, где он упоминается как IEnumerable<T>, что часто бывает, например. в LINQ. - person l33t; 02.05.2019
comment
@l33t: я бы хотя бы имел метод, который возвращает IEnumerable<T>, чтобы пользователи, которые хотят удобства, но не возражают против штрафа за бокс, были удовлетворены. - person Jon Skeet; 02.05.2019

Да, ты можешь. даже вы можете использовать его в foreach. Единственная проблема в том, что объекты этого класса нельзя привести к IEnumerable, хотя они реализуют нужный метод.

person Andrey    schedule 25.05.2010

Нет причин, по которым вам нужно реализовывать IEnumerable, чтобы создать функцию с именем GetEnumerator, которая возвращает IEnumerator, это просто означает, что вы не сможете предоставить экземпляр этого типа чему-то, что ожидает IEnumerable.

person Adam Robinson    schedule 25.05.2010

интерфейс обеспечивает контракт, это не означает, что у вас не может быть метода с той же сигнатурой, что и в интерфейсе, в классе, который не реализует интерфейс.

person Pharabus    schedule 25.05.2010