我使用以下代码使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
有帮助吗?

解决方案

Ienumerator和Ienumerable有什么区别?

杰森的答案很好,但我想我只是补充我对此的看法。想象您有一个序列:

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

现在想象一下,您指向该顺序的某个位置:

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

“箭头”是可以做两件事的对象。首先,它可以为您指向的东西。其次,它可以使下一件事指出。

ienumerator是箭头。它具有当前的属性,可为您指向。它具有一种方法,即movenext(),它使自己指向下一件事。

您如何首先获得箭头?您需要一个箭工厂。您向工厂索要箭头,它为您提供了一个指向序列中的第一个元素的箭头。

Ienumerable是一家箭工厂。它具有一种方法,即getEnumerator,它为您提供了序列的第一个元素的箭头。

该方案的一个不错的属性是,您可以在同一序列中具有多个指向不同位置的箭头。

实施通用界面而不是仅仅是iEnumerable有什么好处?

假设序列是整数的。如果您实施 IEnumerable 然后你说

foreach(int x in mysequence)

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

假设序列是字符串。如果您实施 IEnumerable<string> 然后你可以说:

string first = mysequence.First();

如果您不这样做,那么您必须说

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

这是不必要且容易出错的。您可以简单地说明类型是字符串,而不是通过铸件指导编译器 保证 该类型是通过使用类型系统的字符串。

其他提示

1)什么是 IEnumerator 为了?有什么区别 IEnumeratorIEnumerable?

IEnumerator 是代表您列举序列的方法的接口。和...之间的不同 IEnumeratorIEnumerable 是前者代表让您列举序列的对象的合同,后者表示可以列举的序列的对象的合同。

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


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

2)这是什么原因?它只是在上面调用方法。

前者代表该方法的实现 GetEnumerator 在合同上 IEnumerable<string>. 。后者代表该方法的明确实现 GetEnumerator 在合同上 IEnumerable. 。问题是两份合同都有一种名称的方法 GetEnumerator 但是使用不同的返回类型,因此方法不能同时满足这两个合同(任何实施的类别 IEnumerable<T> 也必须实施 IEnumerable 作为 IEnumerable<T> : IEnumerable)。后者调用 IEnumerable<string>.GetEnumerator 因为那是一个明智的实现,返回 IEnumerator 作为 IEnumerator<string> : IEnumerator.

3)最后,我实现通用界面有什么好处 IEnumerable<string> 而不是只是 IEnumerable?

强大的打字。你知道序列中的元素 IEnumerable<string> 都是所有实例 String 而你不知道 IEnumerable 并可能最终试图将后者的元素铸造为 String 当不可能的时候。

这是声明 IEnumerable<T>:

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

你别无选择,你 也实现了非传元的ienumerable接口。如果您省略了ienumerable.getEnumerator()实现,则将获得编译错误。这是从.NET 1.x天剩下的,那里的仿制药还没有可用,并且需要.NET 2.0的过渡期,它需要支持与.NET 1.X组件互动。我们坚持下去。

1)什么是Ienumerator?

Ienumerator是MoveNext()和当前成员的真正工作部分。

Ienumerator和Ienumerainer有什么区别

iEnumerable是一个集合的接口,以表明其具有getEnumerator()。

2)[非生成getEnumerator]这是什么用?它只是调用上面的方法

非传播方法只是为了向后兼容。请注意,通过使用显式实现,它会尽可能“看不见”。实施它是因为您必须然后忘记它。

3)最后,通过实施遗传界面而不仅仅是iEnumerable,我从中获得了什么好处

使用时 foreach Adavantage很小,因为foreach将键入循环变量。它会让您使用 var 在foreach中:

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

但是有 IEnumerable<string> 您还具有针对其他区域的类型安全接口,最著名的是Linq:

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

GetEnumerator 自从仿制药被引入该语言之前就已经存在,以免打破预先存在的代码,默认方法将通往通用实现。

有了通用的枚举,您的班级消费者在迭代时不需要将每个项目施放到串联。

关于第三个问题(为什么要使用仿制药?),这里有一些答案:

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

简而言之,每次都可以使用通用收藏。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top