无法理解 IEnumerator

发布于 2024-12-13 16:56:34 字数 935 浏览 1 评论 0原文

我目前正在学习 C#,以便有效地使用 Razor 和 Umbraco,我有一点 PHP 背景和 JavaScript 的合理知识。

我遇到了 IEnumerator 界面,但很难理解它。我在下面设置了一个代码片段来演示使用 foreach 循环遍历数组:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace cardEnum
{
    class suitsEnumerator
    {
        private static string[] suits = { "Hearts", "Spades", "Diamonds", "Clubs" };
        public void showAll()
        {
            foreach(string x in suits){
                System.Console.WriteLine(x);
            }
        }
    }
    class run
    {
        static void Main()
        {
            Console.WriteLine("The suits are:");
            var suits = new suitsEnumerator();
            suits.showAll();
            Console.ReadKey();
        }
    }
}

有人可以解释为什么我什至需要使用 IEnumerator ,否则我可以很容易地循环遍历数组。我知道这是一个非常简单的问题,我只是想不出使用 IEnumerable 的理由。

任何帮助将不胜感激,谢谢!

I'm currently learing C# for the purpose of effectivly usingRazor and Umbraco, I have a little bit of background in PHP and a reasonable knowledge in JavaScript.

I came across the IEnumerator interface and have had difficulty getting my head around it. I've setup a code snippet below to demonstrate looping through an array with foreach:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace cardEnum
{
    class suitsEnumerator
    {
        private static string[] suits = { "Hearts", "Spades", "Diamonds", "Clubs" };
        public void showAll()
        {
            foreach(string x in suits){
                System.Console.WriteLine(x);
            }
        }
    }
    class run
    {
        static void Main()
        {
            Console.WriteLine("The suits are:");
            var suits = new suitsEnumerator();
            suits.showAll();
            Console.ReadKey();
        }
    }
}

Can someone explain why I would even need to use IEnumerator when I can quite easily loop through the array otherwise. I KNOW this is such a simple question, I just cant think of an reason to use IEnumerable.

Any help at all would be greatly appreciated, thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

清引 2024-12-20 16:56:34

这就是在您的示例中实现枚举器模式的方式。我希望这能澄清一些事情,特别是 IEnumerableIEnumerator 之间的关系:

namespace cardEnum {
    // simple manual enumerator
    class SuitsEnumerator : IEnumerator {
        private int pos = -1;
        private static string[] suits = { "Hearts", "Spades", "Diamonds", "Clubs" };

        public object Current {
            get { return suits[pos]; }
        }

        public bool MoveNext() {
            pos++;
            return (pos < suits.Length);
        }

        public void Reset() {
            pos = -1;
        }
    }

    class Suits : IEnumerable {
        public IEnumerator GetEnumerator() {
            return new SuitsEnumerator();
        }
    }

    class run {
        static void Main() {
            Console.WriteLine("The suits are:");
            var suits = new Suits();
            foreach (var suit in suits) {
                Console.WriteLine(suit);
            }
            Console.ReadKey();
        }
    }
}

当然,这是一个为了帮助理解而设计的示例。由于 string[] 已经实现了 IEnumerable,因此没有理由重新发明轮子。


由于 C# 支持 yields 关键字,因此创建 Enumerator 最近变得更加容易:

namespace cardEnum {
    // no explicit SuitsEnumerator required
    class Suits : IEnumerable {
        public IEnumerator GetEnumerator() {
            yield return "Hearts";
            yield return "Spades";
            yield return "Diamonds";
            yield return "Clubs";
        }
    }

    class run {
        static void Main() {
            Console.WriteLine("The suits are:");
            var suits = new Suits();
            foreach (var suit in suits) {
                Console.WriteLine(suit);
            }
            Console.ReadKey();
        }
    }
}

This is how the enumerator pattern could be implemented in your example. I hope this clarifies a few things, in particular, the relationship between IEnumerable and IEnumerator:

namespace cardEnum {
    // simple manual enumerator
    class SuitsEnumerator : IEnumerator {
        private int pos = -1;
        private static string[] suits = { "Hearts", "Spades", "Diamonds", "Clubs" };

        public object Current {
            get { return suits[pos]; }
        }

        public bool MoveNext() {
            pos++;
            return (pos < suits.Length);
        }

        public void Reset() {
            pos = -1;
        }
    }

    class Suits : IEnumerable {
        public IEnumerator GetEnumerator() {
            return new SuitsEnumerator();
        }
    }

    class run {
        static void Main() {
            Console.WriteLine("The suits are:");
            var suits = new Suits();
            foreach (var suit in suits) {
                Console.WriteLine(suit);
            }
            Console.ReadKey();
        }
    }
}

Of course, this is a contrived example to aid understanding. Since string[] already implements IEnumerable, there's no reason to reinvent the wheel.


Since C# supports the yields keyword, creating an Enumerator got a little easier recently:

namespace cardEnum {
    // no explicit SuitsEnumerator required
    class Suits : IEnumerable {
        public IEnumerator GetEnumerator() {
            yield return "Hearts";
            yield return "Spades";
            yield return "Diamonds";
            yield return "Clubs";
        }
    }

    class run {
        static void Main() {
            Console.WriteLine("The suits are:");
            var suits = new Suits();
            foreach (var suit in suits) {
                Console.WriteLine(suit);
            }
            Console.ReadKey();
        }
    }
}
梦断已成空 2024-12-20 16:56:34

首先,如果您要创建自己的枚举器,则应该使该类实现 IEnumerator 接口(或其通用等效接口)。

public class FooEnumerator : IEnumerator
{
    #region IEnumerator Members

    public object Current
    {
        get { throw new NotImplementedException(); }
    }

    public bool MoveNext()
    {
        throw new NotImplementedException();
    }

    public void Reset()
    {
        throw new NotImplementedException();
    }

    #endregion
}

通常,枚举器用于在集合中一次移动一项。这是一个简单的界面,用于支持移动项目,但不代表项目本身。它只有当前项目和移动到下一个项目的概念。

另一方面,IEnumerable 旨在表示项目的集合。根据其定义,IEnumerable 返回一个枚举器,其目的是枚举 IEnumerable 集合中的每个项目。它们不是相互排斥的类,而是依赖类。

您通常不会像示例中那样创建一个枚举器来遍历您的值。您将创建一个集合并使用枚举器对其进行导航(或者在更高级别迭代在幕后使用枚举器的集合)。

First of all, if you are going to create your own enumerator, you should make the class implement the IEnumerator interface (or its generic equivalent).

public class FooEnumerator : IEnumerator
{
    #region IEnumerator Members

    public object Current
    {
        get { throw new NotImplementedException(); }
    }

    public bool MoveNext()
    {
        throw new NotImplementedException();
    }

    public void Reset()
    {
        throw new NotImplementedException();
    }

    #endregion
}

Typically enumerators are used to move, one item at a time, through a collection. It's a simple interface for supporting the moving items, but not representing the items themselves. It only has the concept of the current item and moving to the next.

IEnumerable, on the other hand, is intended to represent the collection of items. IEnumerable, by its definition, returns an enumerator whose purpose is to enumerate through each item in the IEnumerable collection. They are not mutually exclusive classes, the are dependent classes.

You wouldn't normally create an enumerator to go through your values like in your example. You would create a collection and use an enumerator to navigate it (or at a higher level iterate the collection which uses an enumerator behind the scenes).

失与倦" 2024-12-20 16:56:34

您可能(而且经常)必须执行一些比仅仅打印对象的值更复杂的操作。

您的类可能必须一一返回(产生)对象以进行某些外部处理(通过某些其他类、方法等)。

那么暴露一个 IEnumerator 比返回整个集合更好,因为枚举意味着您一次只传递一个对象!不是一次(可能)一百万个元素的数组。

You may (and often will) have to to perform some more complex operations than just printing out the values of your objects.

Your class could have to return (yield) objects one by one for some external processing (by some other class, method etc.).

Then exposing an IEnumerator is better than returning an entire collection, because enumerating means you're only passing one object at the time! Not an array of (possibly) one milion elements at once.

酷炫老祖宗 2024-12-20 16:56:34

C# 编译器对此进行了转换:

foreach(string x in suits)

使用 IEnumerator(或 IEnumerator)。

IEnumerable 和 < code>IEnumerable接口定义一个 GetEnumerator 方法,该方法返回一个 IEnumerator(或分别是 IEnumerator),这就是您使用 foreach 进行的迭代所使用的内容。

例外是使用数组完成的迭代,编译器以不同的方式对待它(感谢@Jon Skeet)。

The C# compiler transforms this:

foreach(string x in suits)

To use IEnumerator (or IEnumerator<T>).

The IEnumerable and IEnumerable<T> interfaces define a GetEnumerator method that returns an IEnumerator (or IEnumerator<T>, respectively) which is what is being used for the iteration you are doing with foreach.

The exception is iteration done with arrays, which the compiler treats differently (thanks @Jon Skeet).

疯了 2024-12-20 16:56:34

这很好,因为你的代码依赖于接口(IEnumerable

今天,如果你决定使用 for 循环,你的代码中的套装类型是数组,

private static string[] suits = { "Hearts", "Spades", "Diamonds", "Clubs" };

你的代码看起来或多或少像下面

for (int index = 0; index < suits.Length; suits++)
{
    // code here
}

这样明年你可能有一个理由将其类型从 Array 更改为 List。如果您使用 for ,则需要更新代码块,因为 Array 具有 Length 属性,而 List 具有 Count 属性。

It's good because your code is depend on interface (IEnumerable)

Today type of suits in your code is Array

private static string[] suits = { "Hearts", "Spades", "Diamonds", "Clubs" };

if you decide to use for loop you code look more or less like below

for (int index = 0; index < suits.Length; suits++)
{
    // code here
}

Next year you may have a reason to change its type from Array to List<T>. If you use for you need to update block of code since Array has Length while List has Count property.

Saygoodbye 2024-12-20 16:56:34

如果您查看 System.Array,您会发现 Array 实现了 IEnumerable。
并且每个都不需要 IEnumerable 对象。它只需要一个名为 GetEnumerator 的方法。

If you look at System.Array you'll see that Array implements IEnumerable.
And for each doesn't need an IEnumerable object. It only needs a method called GetEnumerator.

梦幻之岛 2024-12-20 16:56:34

假设您要创建一个自定义套装集合...学习如何实现 IEnumerable 将使您深入了解它为何如此有用。没有它,LINQ 就不可能存在。

Suppose you were to create a custom collection of suits ...learning how to implement the IEnumerable<T> will give you a bit of insight on why it is so useful. Without it, LINQ could not exist as we know it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文