Разница между IEnumerable и IEnumerable?

в чем разница между IEnumerable и IEnumerable<T>?

Я видел много классов framework, реализующих оба этих интерфейса, поэтому я хотел бы знать, какие преимущества можно получить, реализуя оба?

пожалуйста, посмотрите, как они были определены:

public interface IEnumerable
{
    [DispId(-4)]
    IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

как мы видим, IEnumerable<T> происходит от IEnumerable, что бы IEnumerable есть, IEnumerable<T> наследует, тогда почему мы реализуем оба, а не просто IEnumerable<T>? Осуществляет IEnumerable<T> не хватает?

кроме того, есть и другие подобные пары:

  • IList и IList<T>
  • ICollection и ICollection<T>

Я хотел бы знать о них.

4 ответов


в основном неуниверсальные интерфейсы, в .Чистая 1.0 и 1.1. Затем, когда .NET 2.0 вышел, вышли общие эквиваленты. Жизнь была бы намного проще, если бы дженерики сделали это в .NET 1.0:)

С точки зрения реализации "только"IEnumerable<T> вместо обоих - в основном есть для реализации, и вы должны использовать явную реализацию интерфейса, учитывая, что оба определения параметров GetEnumerator метод. As IEnumerator<T> выходит IEnumerator кроме того, это обычно что-то вроде этого:

public IEnumerator<T> GetEnumerator()
{
    // Return real iterator
}

// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
    // Delegate to the generic implementation
    return GetEnumerator();
}

С другой стороны, с блоками итератора, введенными в C# 2 (с yield return etc) вам редко нужно осуществлять эти вещи полностью вручную, к счастью. Возможно, вам придется написать что-то подобное выше, а затем использовать yield return на GetEnumerator метод.

отметим, что IList<T> тут не расширения IList и ICollection<T> тут не расширения ICollection. Это потому, что это менее безопасно для типа так поступать... в то время как любой универсальный итератор можно рассматривать как неуниверсальные итератор из-за (потенциально бокс) преобразования любого значения!--12-->, IList и ICollection разрешить значения добавил в коллекцию; и нет смысла добавлять (скажем) строку в IList<int>.

EDIT: причина, по которой нам нужно IEnumerable<T> Так, что мы можем итерировать безопасным для типа способом и распространять эту информацию. Если я верну IEnumerable<string> - вы знаете, что вы можете спокойно предположим, все вернулись из него будет ссылка строки или null. С IEnumerable, мы должны эффективно бросить (часто неявно в foreach оператор) каждый элемент, который был возвращен из последовательности, потому что Current собственность IEnumerator просто типа object. Что касается того, почему мы еще нужно IEnumerable - потому что старые интерфейсы не уходят, в основном. Слишком много существующего кода использует его.

это было бы возможно для IEnumerable<T> не продлевать IEnumerable, но тогда любой код, желающий использовать IEnumerable<T> не удалось вызвать метод, принимающий IEnumerable - и было много таких методов, как .NET 1.1 и 1.0.


возвращает объект типа object, другой возвращает объект типа T.


Что касается того, почему вы видите классы, определяющие оба, достаточно, хотя IEnumerable реализует IEnumerable, его не нужно, но хорошо в самодокументировании, чтобы иногда перечислять подинтерфейсы. Считать

interface IA { }
interface IB : IA { }

class A : IB {} // legal, IB implements IA

class B : IA, IB {} // also legal, possible more clear on intent

при итерации по циклу IEnumerator поддерживает состояние. Он запоминает положение курсора, а IEnumerable-нет.