Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#是否会从不同类型的枚举数(如C+)之间的区别中获益+;迭代器?_C#_C++_Ienumerable_Iterator - Fatal编程技术网

C#是否会从不同类型的枚举数(如C+)之间的区别中获益+;迭代器?

C#是否会从不同类型的枚举数(如C+)之间的区别中获益+;迭代器?,c#,c++,ienumerable,iterator,C#,C++,Ienumerable,Iterator,我一直在考虑IEnumerator.Reset()方法。我在MSDN文档中读到它仅用于COM互操作。作为一个C++程序员,它看起来像是一个 IEnumerator ,支持重置< /C> >,我称之为A,而 IEnumerator 不支持 RESET>代码>,实际上是一个.< /p> 所以我的问题的第一部分是,这种理解正确吗 我问题的第二部分是,如果在输入迭代器和前向迭代器(或者如果您愿意的话是“枚举器”)之间进行区分,那么在C#中会有什么好处?这会不会有助于消除程序员之间的一些困惑,就像在本文中

我一直在考虑
IEnumerator.Reset()
方法。我在MSDN文档中读到它仅用于COM互操作。作为一个C++程序员,它看起来像是一个<代码> IEnumerator <代码>,支持<代码>重置< /C> >,我称之为A,而<代码> IEnumerator <代码>不支持<代码> RESET>代码>,实际上是一个.< /p> 所以我的问题的第一部分是,这种理解正确吗

我问题的第二部分是,如果在输入迭代器和前向迭代器(或者如果您愿意的话是“枚举器”)之间进行区分,那么在C#中会有什么好处?这会不会有助于消除程序员之间的一些困惑,就像在本文中发现的那样

编辑:关于前向迭代器和输入迭代器的说明。输入迭代器仅保证只能枚举集合(或从生成器函数或输入流)的成员一次。这正是IEnumerator在C#中的工作方式。是否可以再次枚举取决于是否支持
Reset
。前向迭代器没有此限制。您可以根据需要经常枚举成员

一些C#程序员不明白为什么在多路径算法中不能可靠地使用
IEnumerator
。考虑以下情况:

void PrintContents(IEnumerator<int> xs)
{
  while (iter.MoveNext())
    Console.WriteLine(iter.Current); 
  iter.Reset();
  while (iter.MoveNext())
    Console.WriteLine(iter.Current); 
}
但是,请看以下几点:

IEnumerable<int> GenerateInts() {   
  System.Random rnd = new System.Random();
  for (int i=0; i < 10; ++i)
    yield return Rnd.Next();
}

PrintContents(GenerateInts());
IEnumerable GenerateInts(){
System.Random rnd=新的System.Random();
对于(int i=0;i<10;++i)
收益率返回Rnd.Next();
}
打印内容(GenerateInts());

如果
IEnumerator
支持
Reset
,换句话说,它支持多通道算法,那么每次迭代集合时都会有所不同。这将是不可取的,因为这将是令人惊讶的行为。这个例子有点假,但它确实发生在现实世界中(例如,从文件流读取)

重置是一个大错误。我在
Reset
上称之为骗局。在我看来,反映.NET类型系统中“正向迭代器”和“输入迭代器”之间区别的正确方法是区分
IEnumerable
IEnumerator


另请看,微软的埃里克·利珀特(Eric Lippert)(毫无疑问,我的观点是,他是一个拥有比我所宣称的更多资历的人,这是一个设计错误)在评论中也提出了类似的观点。另请参见。

我不这么认为。我将调用
IEnumerable
前向迭代器和输入迭代器。它不允许您后退或修改基础集合。由于添加了
foreach
关键字,迭代器在大多数情况下几乎不被认为是一种工具

意见: 输入迭代器(获取每个迭代器)与输出迭代器(对每个迭代器执行某些操作)之间的差异太小,无法证明向框架中添加迭代器是正确的。此外,为了执行输出迭代器,需要将委托传递给迭代器。对于C#程序员来说,输入迭代器似乎更自然


如果程序员想要随机访问,还有
IList

有趣的问题。我认为C#当然会受益。然而,这并不容易添加

< > C++中存在区别,因为它的类型系统更加灵活。在C#中,没有一种健壮的通用方法来克隆对象,这是表示前向迭代器(支持多过程迭代)所必需的。当然,为了让它真正有用,您还需要支持双向和随机访问迭代器/枚举器。为了让它们都能顺利工作,你需要一些鸭子打字的形式,比如C++模板。 最终,这两个概念的范围是不同的

在C++中,迭代器应该代表一系列值所需的所有知识。给定一对迭代器,我不需要原始容器。我可以排序,我可以搜索,我可以随心所欲地操作和复制元素。原始容器不在图片中

在C#中,枚举数并不意味着做那么多。最终,它们只是为了让您以线性方式运行序列而设计的

至于
Reset()
,人们普遍认为首先添加它是错误的。如果它工作正常,并且实现正确,那么是的,您可以说您的枚举器类似于前向迭代器,但一般来说,最好将其视为错误而忽略。然后所有枚举数都与输入迭代器相似

不幸的是。

从C#的角度来看:

您几乎从不直接使用
IEnumerator
。通常执行
foreach
语句,该语句需要
IEnumerable

IEnumerable _myCollection;
...
foreach (var item in _myCollection) { /* Do something */ }
您也不能传递
IEnumerator
。如果要传递需要迭代的集合,则传递
IEnumerable
。由于
IEnumerable
只有一个函数,返回一个
IEnumerator
,因此可以使用它多次迭代集合(多次传递)


没有必要在
IEnumerator
上使用
Reset()
函数,因为如果您想重新开始,只需扔掉旧的(垃圾回收的)并获得新的

如果有一种方法可以询问
IEnumerator
它可以支持哪些功能以及它可以做出哪些承诺,那么.NET框架将受益匪浅。这些特性在
IEnumerable
中也会很有帮助,但是如果能够询问枚举器的问题,那么可以从诸如
ReadOnlyCollection
之类的包装器接收枚举器的代码就可以以改进的方式使用基础集合,而不必涉及包装器

给定集合的任何枚举数
IEnumerable _myCollection;
...
foreach (var item in _myCollection) { /* Do something */ }