【问题标题】:Implementing IEnumerable to my object [duplicate]对我的对象实施 IEnumerable [重复]
【发布时间】:2012-12-30 21:35:05
【问题描述】:

可能重复:
Implementing C# IEnumerable<T> for a LinkedList class

在网上搜索了几个小时后,我仍然无法理解IEnumerable/IEnumerator 的工作原理以及如何实现它。

我从头开始构建了一个简单的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; }
}

【问题讨论】:

  • Here 不是在自定义类上实现IEnumerable 的好教程。 Here 更好。
  • 请注意,从技术上讲,不不需要实现 IEnumerable 以使用带有 foreach 循环的类...
  • 是的,我知道,但我想学习如何使用它。

标签: c# ienumerable ienumerator


【解决方案1】:

你需要做的是:

(1) 让你的类实现 IEnumerable 其中 T 是枚举项的类型。 (在你的情况下,它看起来像是 LLNode)。

(2) 编写一个公共的 IEnumerator GetEnumerator。使用“yield”关键字实现它。

(3) 添加一个 IEnumerator IEnumerable.GetEnumerator() 方法并返回 GetEnumerator()。

下面的代码应该清楚地说明这一点。我有 的地方,你应该放 ,假设那是正确的类型。

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; }
        }
    }
}

【讨论】:

  • 现在尝试编译它,不要使用 foreach 循环和 WriteLite。
  • 感谢它现在有效。现在我要研究它。
【解决方案2】:

真的没那么难。要实现IEnumerable,您只需要实现GetEnumerator 方法即可。

为此,您需要创建另一个实现IEnumerator 的类。实现 IEnumerator 非常简单。通常,当您创建枚举器(在 GetEnumerator 中)时,您将传递对您的集合的引用,并且枚举器将跟踪哪个项目是当前项目。然后它将提供MoveNext,它只是将Current 更改为下一项(如果它位于列表的末尾,则返回false)和Reset,它只是将Current 设置回之前 em> 第一个节点。

因此,在非常广泛的、未经测试的代码术语中,您需要以下内容:

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;
    }
}

【讨论】:

  • 只是指出,如果您使用 yield 语句等自己创建 GetEnumerator() 方法,C# 可以帮助您解决这个问题。
  • 我得到:错误 1 ​​可访问性不一致:参数类型 'xx.LL' 比方法 'xx.MyLinkedListEnumerator.MyLinkedListEnumerator(xx.LL)' C:\\xx\Program.cs 更难访问错误
  • @Ben:这可能是因为你的LL 类是私有的。将其标记为公开。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
相关资源
最近更新 更多