关于 IEnumerable 和 IEnumerator 的问题

发布于 2024-10-09 15:19:06 字数 741 浏览 3 评论 0原文

我使用以下代码使 myClass 能够使用 foreach。但我对编程相当陌生,并且在理解以下代码时遇到一些困难。我在评论中描述了我的问题。如果您提供一些信息,我将不胜感激。

    public class MyClass : IEnumerable<string> 
    {  
    //1) What is IEnumerator for?
        // Whats the difference between IEnumerator and IEnumerable
    public IEnumerator<string> GetEnumerator()     
    {
             yield return "first";         
             yield return "second";     
    }      
    //2) What is it for?  It just calls above method 
   IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator(); 
         } 
    }
   //3) Lastly what benefits I have from implementing genetic interface 
   //IEnumerable<string> instead of just IEnumerable

I use the following code to enable myClass to use foreach. But I am rather new to programming and have some difficulty in understanding the following code. I described my problems in the comments. I would be grateful for providing some information.

    public class MyClass : IEnumerable<string> 
    {  
    //1) What is IEnumerator for?
        // Whats the difference between IEnumerator and IEnumerable
    public IEnumerator<string> GetEnumerator()     
    {
             yield return "first";         
             yield return "second";     
    }      
    //2) What is it for?  It just calls above method 
   IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator(); 
         } 
    }
   //3) Lastly what benefits I have from implementing genetic interface 
   //IEnumerable<string> instead of just IEnumerable

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

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

发布评论

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

评论(7

夜声 2024-10-16 15:19:07

IEnumerator 和 IEnumerable 有什么区别?

杰森的回答很好,但我想我应该补充一下我对此的看法。想象你有一个序列:

1, 1, 2, 3, 5, 8, 13, ...

现在想象你有一个箭头指向该序列的某个位置:

1, 1, 2, 3, 5, 8, 13, ...
         ^

“箭头”是一个可以做两件事的对象。首先,它可以给你它所指向的东西。其次,它可以使自己指向下一件事。

IEnumerator 是一个箭头。它有一个属性 Current,可以为您提供它所指向的东西。它有一个方法,MoveNext(),它使自己指向下一个事物。

首先你如何获得箭头?你需要一个箭厂。你向工厂请求一个箭头,它给你一个指向序列中第一个元素的箭头。

IEnumerable 是一个箭头工厂。它有一个方法 GetEnumerator,可以为您提供指向序列第一个元素的箭头。

该方案的一个很好的特性是您可以在同一序列中使用多个箭头指向不同的位置。

实现通用接口 IEnumerable 而不仅仅是 IEnumerable 有什么好处?

假设序列是整数。如果您实现 IEnumerable ,那么当您说

foreach(int x in mysequence)

实际执行的操作是将序列中的 int 转换为对象,将整数装箱,然后立即将对象拆箱回整数,从而添加完全不必要的内存分配到每一个操作。如果编译器知道该序列是整数,那么它可以跳过不必要的装箱操作。

假设序列是字符串。如果您实现了 IEnumerable 那么您可以说:

string first = mysequence.First();

如果您没有实现,那么您必须说出

string first = (string)mysequence.First();

哪个是不必要的且容易出错。您可以使用类型系统简单地保证类型为字符串,而不是通过强制转换来指示编译器类型为字符串。

What is the difference between IEnumerator and IEnumerable?

Jason's answer is good but I thought I'd just add how I think about this. Imagine you have a sequence:

1, 1, 2, 3, 5, 8, 13, ...

Now imagine you have an arrow pointing at some position of that sequence:

1, 1, 2, 3, 5, 8, 13, ...
         ^

An "arrow" is an object that can do two things. First, it can give you the thing it is pointing at. Second, it can make itself point at the next thing.

IEnumerator is an arrow. It has a property, Current, that gives you the thing it is pointing at. It has a method, MoveNext() that makes itself point at the next thing.

How do you get an arrow in the first place? You need an arrow factory. You ask the factory for an arrow, and it gives you an arrow that points to the first element in the sequence.

IEnumerable is an arrow factory. It has a method, GetEnumerator, that gives you an arrow to the first element of the sequence.

A nice property of this scheme is that you can have multiple arrows pointing to different places in the same sequence.

what are the benefits of implementing generic interface IEnumerable instead of just IEnumerable?

Suppose the sequence is of integers. If you implement IEnumerable then when you say

foreach(int x in mysequence)

what that will actually do is convert the int in the sequence to object, boxing the integer, and then immediately unbox the object back to integer, adding a completely unnecessary memory allocation to every single operation. If the compiler knows that the sequence is of integers then it can skip the unnecessary boxing operation.

Suppose the sequence is of strings. If you implement IEnumerable<string> then you can say:

string first = mysequence.First();

If you don't, then you have to say

string first = (string)mysequence.First();

which is unnecessary and error-prone. Rather than instruct the compiler via a cast that the type is string, you can simply guarantee that the type is string by using the type system.

ˇ宁静的妩媚 2024-10-16 15:19:07

1) IEnumerator 的用途是什么? IEnumeratorIEnumerable 之间有什么区别?

IEnumerator 是一个接口,它表示可让您枚举序列的方法。 IEnumeratorIEnumerable 之间的区别在于,前者表示可枚举序列的对象的约定,而后者表示可枚举序列的对象的约定。被一一列举。

public IEnumerator<string> GetEnumerator() {
         yield return "first";         
         yield return "second";     
}      


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

2)它的用途是什么?它只是调用上面的方法。

前者表示合约 IEnumerable 上方法 GetEnumerator 的实现。后者表示合约 IEnumerable 上方法 GetEnumerator 的显式实现。问题在于,两个合约都有一个名为 GetEnumerator 的方法,但返回类型不同,因此一个方法无法同时满足两个合约(任何实现 IEnumerable 的类都必须还将 IEnumerable 实现为 IEnumerable: IEnumerable)。后者调用 IEnumerable.GetEnumerator 的实现,因为这是一个明智的实现,它将 IEnumerator 返回为 IEnumerator。 :IEnumerator

3) 最后,实现通用接口 IEnumerable 而不仅仅是 IEnumerable 有什么好处?

强打字。您知道序列 IEnumerable 中的元素都是 String 的实例,但您不知道对于 IEnumerable 并且可能会结束up 尝试将后者的元素强制转换为 String 的实例,但事实并非如此。

1) What is IEnumerator for? Whats the difference between IEnumerator and IEnumerable?

IEnumerator is an interface that represents methods that let you enumerate a sequence. The difference between IEnumerator and IEnumerable is that the former represents the contract for objects that let you enumerate a sequence, and the latter represents the contract for objects that are a sequence that can be enumerated over.

public IEnumerator<string> GetEnumerator() {
         yield return "first";         
         yield return "second";     
}      


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

2) What is it for? It just calls above method.

The former represents an implementation of the method GetEnumerator on the contract IEnumerable<string>. The latter represents an explicit implementation of the method GetEnumerator on the contract IEnumerable. The issue is that both contracts have a method named GetEnumerator but with different return types so that a method can't simultaneously satisfy both contracts (any class implementing IEnumerable<T> must also implement IEnumerable as IEnumerable<T> : IEnumerable). The latter invokes the implementation of IEnumerable<string>.GetEnumerator as that is a sensible implementation that returns an IEnumerator as IEnumerator<string> : IEnumerator.

3) Lastly what benefits I have from implementing generic interface IEnumerable<string> instead of just IEnumerable?

Strong typing. You know that the elements in a sequence IEnumerable<string> are all instances of String whereas you don't know that for IEnumerable and could end up trying to cast an element of the latter to an instance of String when it can not be.

囍笑 2024-10-16 15:19:07

这是 IEnumerable 的声明:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

您别无选择,您必须也实现非泛型 IEnumerable 接口。如果省略 IEnumerable.GetEnumerator() 实现,则会出现编译错误。这是 .NET 1.x 时代(泛型尚不可用)和 .NET 2.0 过渡期(需要支持与 .NET 1.x 程序集的互操作)留下的包袱。我们被困住了。

This is the declaration for IEnumerable<T>:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

You have no choice, you have to implement the non-generic IEnumerable interface as well. You'll get a compile error if you omit the IEnumerable.GetEnumerator() implementation. This is baggage left over from the .NET 1.x days where generics weren't available yet and the transition period for .NET 2.0 where it needed to support interop with .NET 1.x assemblies. We're stuck with it.

执手闯天涯 2024-10-16 15:19:07

1) IEnumerator 的用途是什么?

IEnumerator 是 MoveNext() 和 Current 成员的真正工作部分。

IEnumerator 和 IEnumerable 有什么区别

IEnumerable 是集合的接口,用于指示它具有 GetEnumerator()。

2) [非泛型 GetEnumerator] 它的用途是什么?它只是调用上面的方法

非泛型方法只是为了向后兼容。请注意,通过使用显式实现,它会尽可能地“移出视线”。实施它是因为你必须这样做,然后就忘记它。

3)最后,我从实现遗传接口中得到了什么好处
IEnumerable 而不仅仅是 IEnumerable

当与 foreach 一起使用时,优势很小,因为 foreach 将对循环变量进行类型转换。它允许您在 foreach 中使用 var

foreach (var s in myClassInstance)     // needs `IEnumerable<string>` 
foreach (string s in myClassInstance)  // works with  `IEnumerable` as well 

但是使用 IEnumerable 您还可以为其他区域提供类型安全的接口,尤其是 LINQ:

MyClass mc = new MyClass ();
string s = mc.FirstOrDefault();

1) What is IEnumerator for?

IEnumerator is the real working part with the MoveNext() and Current members.

Whats the difference between IEnumerator and IEnumerable

IEnumerable is the interface for a collection to signal that it has an GetEnumerator().

2) [non-generic GetEnumerator] What is it for? It just calls above method

The non-generic method is just there for backward compatibility. Note that it is moved 'out of sight' as much as possible by use of the explicit implementation. Implement it because you must and then forget about it.

3) Lastly what benefits I have from implementing genetic interface
IEnumerable instead of just IEnumerable

When used with foreach the adavantage is small, as foreach will type-cast the looping variable. It will let you use var in the foreach:

foreach (var s in myClassInstance)     // needs `IEnumerable<string>` 
foreach (string s in myClassInstance)  // works with  `IEnumerable` as well 

But with IEnumerable<string> you also have a type-safe interface to other areas, most notably LINQ:

MyClass mc = new MyClass ();
string s = mc.FirstOrDefault();
梦初启 2024-10-16 15:19:07

GetEnumerator 在泛型被引入该语言之前就已经存在了,为了不破坏预先存在的代码,默认方法会调用泛型实现。

使用通用枚举,类的使用者在迭代时不需要将每个项目转换为字符串。

GetEnumerator has been around since before generics were introduced to the language, so as to not break pre-existing code, the default method calls through to the generic implementation.

With a generic enumeration, the consumer of your class doesn't need to cast each item to string when iterating.

指尖凝香 2024-10-16 15:19:07

关于第三个问题(为什么使用泛型?)这里有一些答案:

我们应该使用通用集合来提高安全性和性能吗?

简而言之,尽可能使用通用集合。

Regarding the 3rd question (why use generics?) here are some answers:

Should we use Generic Collection to improve safety and performance?

In short, use generic collections every time you can.

标点 2024-10-16 15:19:07

要了解其差异,您需要了解其用途。实际上,它们代表了迭代器设计模式,这是面向对象软件开发人员使用的设计模式之一。

迭代器模式提供了一种顺序访问集合元素的方法,而无需知道集合的结构。

在传统的设计模式方法中,迭代器模式具有用于创建 Iterator 对象的 Aggregate 接口和用于遍历 Aggregate 对象的 Iterator 接口。

现在,IEnumerable 充当保证返回迭代器的聚合接口。迭代器(也称为枚举器)负责生成由特定条件定义的序列中的下一个元素。 IEnumerator 是定义此功能的接口。您可以在我的博客文章 C# 迭代器模式中了解有关此模式的更多信息

To understand the difference you need to understand its use. Actually, they represent an Iterator design pattern which is one of the design patterns used by object-oriented software developers.

The Iterator pattern provides a way of accessing elements of a collection sequentially, without knowing how the collection is structured.

In the traditional design pattern approach, the iterator pattern has an Aggregate interface for creating an Iterator object and the Iterator interface for traversing an Aggregate object.

Now, IEnumerable acts as an Aggregate interface that guarantees to return an iterator. Iterators (also known as Enumerators) are responsible for producing the next element in a sequence defined by certain criteria. IEnumerator is an interface that defines this functionality. You can learn more about this pattern in my blog post Iterator Pattern C#

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