关于Ienumer和Ienumerator的问题
-
13-10-2019 - |
题
我使用以下代码使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
为了?有什么区别IEnumerator
和IEnumerable
?
IEnumerator
是代表您列举序列的方法的接口。和...之间的不同 IEnumerator
和 IEnumerable
是前者代表让您列举序列的对象的合同,后者表示可以列举的序列的对象的合同。
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
自从仿制药被引入该语言之前就已经存在,以免打破预先存在的代码,默认方法将通往通用实现。
有了通用的枚举,您的班级消费者在迭代时不需要将每个项目施放到串联。