猿问

如何实现IEnumerable <T>

我知道如何实现非通用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;到我的using指令,然后更改:


class MyObjects : IEnumerable

至:


class MyObjects : IEnumerable<MyObject>

然后右键单击IEnumerable<MyObject>并选择Implement Interface => Implement Interface,Visual Studio会帮助添加以下代码块:


IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()

{

    throw new NotImplementedException();

}

这次从该GetEnumerator();方法返回非通用IEnumerable对象不起作用,那么我在这里放什么呢?现在,CLI会忽略非通用实现,并在foreach循环中尝试枚举数组时直接进入通用版本。


慕尼黑的夜晚无繁华
浏览 573回答 3
3回答

慕丝7291255

如果您选择使用通用集合(例如List<MyObject>而不是)ArrayList,则会发现List<MyObject>会同时提供您可以使用的通用和非通用枚举器。using System.Collections;class MyObjects : IEnumerable<MyObject>{&nbsp; &nbsp; List<MyObject> mylist = new List<MyObject>();&nbsp; &nbsp; public MyObject this[int index]&nbsp;&nbsp;&nbsp; &nbsp; {&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; get { return mylist[index]; }&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; set { mylist.Insert(index, value); }&nbsp;&nbsp;&nbsp; &nbsp; }&nbsp;&nbsp; &nbsp; public IEnumerator<MyObject> GetEnumerator()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return mylist.GetEnumerator();&nbsp; &nbsp; }&nbsp; &nbsp; IEnumerator IEnumerable.GetEnumerator()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return this.GetEnumerator();&nbsp; &nbsp; }}

慕村225694

您可能不想要显式的实现IEnumerable<T>(这就是您所显示的)。通常的模式是使用IEnumerable<T>的GetEnumerator在明确的执行IEnumerable:class FooCollection : IEnumerable<Foo>, IEnumerable{&nbsp; &nbsp; SomeCollection<Foo> foos;&nbsp; &nbsp; // Explicit for IEnumerable because weakly typed collections are Bad&nbsp; &nbsp; System.Collections.IEnumerator IEnumerable.GetEnumerator()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // uses the strongly typed IEnumerable<T> implementation&nbsp; &nbsp; &nbsp; &nbsp; return this.GetEnumerator();&nbsp; &nbsp; }&nbsp; &nbsp; // Normal implementation for IEnumerable<T>&nbsp; &nbsp; IEnumerator<Foo> GetEnumerator()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; foreach (Foo foo in this.foos)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return foo;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //nb: if SomeCollection is not strongly-typed use a cast:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // yield return (Foo)foo;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Or better yet, switch to an internal collection which is&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // strongly-typed. Such as List<T> or T[], your choice.&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // or, as pointed out: return this.foos.GetEnumerator();&nbsp; &nbsp; }}

慕尼黑8549860

请注意,另一种已IEnumerable<T>实现的System.Collections方法是MyObjects从类派生您的类System.Collections作为基类(documentation):System.Collections:提供通用集合的基类。我们以后可以使我们自己实行重写虚拟System.Collections方法,以提供定制的行为(仅适用于ClearItems,InsertItem,RemoveItem,和SetItem沿Equals,GetHashCode以及ToString从Object)。不同于,List<T>后者的设计不容易扩展。例:public class FooCollection : System.Collections<Foo>{&nbsp; &nbsp; //...&nbsp; &nbsp; protected override void InsertItem(int index, Foo newItem)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; base.InsertItem(index, newItem);&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; Console.Write("An item was successfully inserted to MyCollection!");&nbsp; &nbsp; }}public static void Main(){&nbsp; &nbsp; FooCollection fooCollection = new FooCollection();&nbsp; &nbsp; fooCollection.Add(new Foo()); //OUTPUT: An item was successfully inserted to FooCollection!}请注意,collection仅在需要自定义收集行为的情况下才建议使用这种驱动,这种情况很少发生。见用法。
随时随地看视频慕课网APP
我要回答