Как мне реализовать IEnumerable <T>

c# .net generics

126420 просмотра

6 ответа

Я знаю, как реализовать не универсальный IEnumerable, как это:

using System;
using System.Collections;

namespace ConsoleApplication33
{
    class Program
    {
        static void Main(string[] args)
        {
            MyObjects myObjects = new MyObjects();
            myObjects[0] = new MyObject() { Foo = "Hello", Bar = 1 };
            myObjects[1] = new MyObject() { Foo = "World", Bar = 2 };

            foreach (MyObject x in myObjects)
            {
                Console.WriteLine(x.Foo);
                Console.WriteLine(x.Bar);
            }

            Console.ReadLine();
        }
    }

    class MyObject
    {
        public string Foo { get; set; }
        public int Bar { get; set; }
    }

    class MyObjects : IEnumerable
    {
        ArrayList mylist = new ArrayList();

        public MyObject this[int index]
        {
            get { return (MyObject)mylist[index]; }
            set { mylist.Insert(index, value); }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return mylist.GetEnumerator();
        }
    }
}

Однако я также замечаю, что IEnumerable имеет универсальную версию IEnumerable<T>, но я не могу понять, как это реализовать.

Если я добавлю using System.Collections.Generic;к своим директивам использования, а затем изменить:

class MyObjects : IEnumerable

чтобы:

class MyObjects : IEnumerable<MyObject>

А затем щелкните правой кнопкой мыши IEnumerable<MyObject>и выберите Implement Interface => Implement Interface, Visual Studio услужливо добавляет следующий блок кода:

IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
    throw new NotImplementedException();
}

Возвращение неуниверсального объекта IEnumerable из GetEnumerator();метода на этот раз не работает, так что мне здесь поставить? CLI теперь игнорирует неуниверсальную реализацию и направляется прямо к универсальной версии, когда он пытается перечислить через мой массив во время цикла foreach.

Автор: JMK Источник Размещён: 12.11.2019 09:02

Ответы (6)


140 плюса

Решение

Если вы решите использовать универсальную коллекцию, например List<MyObject>вместо ArrayList, вы обнаружите, что она List<MyObject>будет предоставлять как универсальные, так и неуниверсальные перечислители, которые вы можете использовать.

using System.Collections;

class MyObjects : IEnumerable<MyObject>
{
    List<MyObject> mylist = new List<MyObject>();

    public MyObject this[int index]  
    {  
        get { return mylist[index]; }  
        set { mylist.Insert(index, value); }  
    } 

    public IEnumerator<MyObject> GetEnumerator()
    {
        return mylist.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
Автор: Monroe Thomas Размещён: 02.07.2012 03:45

61 плюса

Вы, вероятно, не хотите явной реализации IEnumerable<T>(что вы показали).

Обычная картина для использования IEnumerable<T>«S GetEnumeratorв явной реализации IEnumerable:

class FooCollection : IEnumerable<Foo>, IEnumerable
{
    SomeCollection<Foo> foos;

    // Explicit for IEnumerable because weakly typed collections are Bad
    System.Collections.IEnumerator IEnumerable.GetEnumerator()
    {
        // uses the strongly typed IEnumerable<T> implementation
        return this.GetEnumerator();
    }

    // Normal implementation for IEnumerable<T>
    IEnumerator<Foo> GetEnumerator()
    {
        foreach (Foo foo in this.foos)
        {
            yield return foo;
            //nb: if SomeCollection is not strongly-typed use a cast:
            // yield return (Foo)foo;
            // Or better yet, switch to an internal collection which is
            // strongly-typed. Such as List<T> or T[], your choice.
        }

        // or, as pointed out: return this.foos.GetEnumerator();
    }
}
Автор: user7116 Размещён: 02.07.2012 03:41

24 плюса

Почему вы делаете это вручную? yield returnавтоматизирует весь процесс обработки итераторов. (Я также написал об этом в своем блоге , в том числе посмотрите на код, сгенерированный компилятором).

Если вы действительно хотите сделать это самостоятельно, вам также нужно вернуть универсальный перечислитель. Вы не сможете использовать ArrayListбольше, поскольку это не является общим. Измените это List<MyObject>вместо. Это, конечно, предполагает, что MyObjectв вашей коллекции есть только объекты типа (или производных типов).

Автор: Anders Abel Размещён: 02.07.2012 03:37

4 плюса

Если вы работаете с дженериками, используйте List вместо ArrayList. В списке есть именно тот метод GetEnumerator, который вам нужен.

List<MyObject> myList = new List<MyObject>();
Автор: Amiram Korach Размещён: 02.07.2012 03:42

0 плюса

сделать Mylist в List<MyObject>, это один из вариантов

Автор: ColWhi Размещён: 02.07.2012 03:40

0 плюса

Обратите внимание, что IEnumerable<T>уже реализованный System.Collectionsдругой подход заключается в том, чтобы вывести ваш MyObjectsкласс System.Collectionsкак базовый класс ( документация ):

System.Collections: Предоставляет базовый класс для универсальной коллекции.

Мы можем позже сделать наши собственные реализации внешним переопределить виртуальные System.Collectionsметоды , чтобы обеспечить пользовательское поведение (только для ClearItems, InsertItem, RemoveItemи SetItemвместе с Equals, GetHashCodeи ToStringс Object). В отличие от того, List<T>который не предназначен для легкого расширения.

Пример:

public class FooCollection : System.Collections<Foo>
{
    //...
    protected override void InsertItem(int index, Foo newItem)
    {
        base.InsertItem(index, newItem);     
        Console.Write("An item was successfully inserted to MyCollection!");
    }
}

public static void Main()
{
    FooCollection fooCollection = new FooCollection();
    fooCollection.Add(new Foo()); //OUTPUT: An item was successfully inserted to FooCollection!
}

Обращаем ваше внимание, что ехать из collectionрекомендованного автомобиля рекомендуется только в том случае, если необходимо настраивать поведение при сборе, что случается редко. увидеть использование .

Автор: Shahar Shokrani Размещён: 27.09.2018 08:11
32x32