6

重複の可能性:
LinkedList クラスの C# IEnumerable<T> の実装

IEnumerable数時間ウェブを検索した後でも、 /IEnumeratorの仕組みと実装方法をまだ理解できません。

私はゼロから単純なものを構築しましたが、今はそれを実装して foreach できるようにしLinkedListたいと考えています。IEnumerableそれ、どうやったら出来るの?

class Program
{
    LL myList = new LL();

    static void Main()
    {
        var gogo = new Program();
    }
    public Program()
    {

        myList.Add("test");
        myList.Add("test1");

        foreach (var item in myList) //This doesn't work because I havn't implemented Ienumerable
            Console.WriteLine(item);

        Console.Read();
    }
}


class LL
{

    private LLNode first;

    public void Add(string s)
    {
        if (this.first == null)
            this.first = new LLNode() { Value = s };
        else
        {
            var node = this.first;
            while (node.Next != null)
                node = node.Next;

            node.Next = new LLNode() { Value = s };
        }
    }


class LLNode
{
    public string Value { get; set; }
    public LLNode Next { get; set; }
}
4

2 に答える 2

6

それは本当に難しいことではありません。IEnumerableを実装するには、GetEnumeratorメソッドを実装するだけです。

そのためには、 IEnumeratorを実装する別のクラスを作成する必要があります。IEnumerator の実装は非常に簡単です。通常、(GetEnumerator で) 列挙子を作成するときにコレクションへの参照を渡し、列挙子はどの項目が現在の項目であるかを追跡します。次に、を次の項目MoveNextに変更するだけでCurrent(リストの最後にある場合は false を返します) 、最初のノードのに戻るようにReset設定します。Current

したがって、非常に広く、テストされていないコード用語では、次のようなものが必要です。

public class MyLinkedListEnumerator : IEnumerator
{
    private LL myList;
    private LLNode current;

    public object Current
    {
       get { return current; }
    }

    public MyLinkedListEnumerator(LL myList) 
    {
        this.myList = myList;
    }

    public bool MoveNext()
    {
        if (current == null) {
            current = myList.first;
        }
        else {
            current = current.Next;
        }
        return current != null;
    }

    public void Reset() 
    {
        current = null;
    }
}
于 2013-01-16T14:30:47.160 に答える
4

あなたがする必要があるのは:

(1) クラスに IEnumerable<T> を実装するようにします。ここで、T は列挙項目の型です。(あなたの場合、LLNodeのように見えます)。

(2) public IEnumerator<T> GetEnumerator を記述します。「yield」キーワードを使用して実装します。

(3) IEnumerator IEnumerable.GetEnumerator() メソッドを追加し、GetEnumerator() を返すだけです。

次のコードは、これを明確にする必要があります。<int> がある場合は、それが正しい型であると仮定して、<LLNode> を配置する必要があります。

using System;
using System.Collections;
using System.Collections.Generic;

namespace Demo
{
    internal class Program
    {
        private static void Main()
        {
            var test = new MyDemo();

            foreach (int item in test)
            {
                Console.WriteLine(item);
            }
        }
    }

    public class MyDemo: IEnumerable<int>
    {
        public IEnumerator<int> GetEnumerator()
        {
            // Your implementation of this method will iterate over your nodes
            // and use "yield return" to return each one in turn.

            for (int i = 10; i <= 20; ++i)
            {
                yield return i;
            }
        }

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

私はあなたのコードを適切に修正したでしょうが、あなたが投稿したコードはコンパイルされません。

[編集]

コードを更新したので、値を列挙したいことがわかりました。完成したコードは次のとおりです。

using System;
using System.Collections;
using System.Collections.Generic;

namespace Demo
{
    internal class Program
    {
        private LL myList = new LL();

        private static void Main()
        {
            var gogo = new Program();
        }

        public Program()
        {
            myList.Add("test");
            myList.Add("test1");

            foreach (var item in myList) // This now works.
                Console.WriteLine(item);

            Console.Read();
        }
    }


    internal class LL: IEnumerable<string>
    {
        private LLNode first;

        public void Add(string s)
        {
            if (this.first == null)
                this.first = new LLNode
                {
                    Value = s
                };
            else
            {
                var node = this.first;
                while (node.Next != null)
                    node = node.Next;

                node.Next = new LLNode
                {
                    Value = s
                };
            }
        }

        public IEnumerator<string> GetEnumerator()
        {
            for (var node = first; node != null; node = node.Next)
            {
                yield return node.Value;
            }
        }

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

        private class LLNode
        {
            public string Value { get; set; }
            public LLNode Next { get; set; }
        }
    }
}
于 2013-01-16T14:39:10.900 に答える