Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.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#_Iterator - Fatal编程技术网

C#迭代器设计的基本原理(与C+;+;)相比)

C#迭代器设计的基本原理(与C+;+;)相比),c#,iterator,C#,Iterator,我发现了类似的话题: 这基本上解决了Java迭代器(类似于C#)无法向后运行的问题 所以我想集中在极限——在C++迭代器中不知道它的极限,你自己把给定迭代器与极限进行比较。在C#中,迭代器知道的更多——您可以不与任何外部引用进行比较就知道迭代器是否有效 我更喜欢C++方式,因为一旦有迭代器,就可以设置任何迭代器作为限制。换句话说,如果您希望只获取少数元素而不是整个集合,则无需更改迭代器(在C++中)。对我来说,它更“纯净”(清晰) 当然,在设计C++时,MS当然知道这一点。那么C#way的优势

我发现了类似的话题:

这基本上解决了Java迭代器(类似于C#)无法向后运行的问题

所以我想集中在极限——在C++迭代器中不知道它的极限,你自己把给定迭代器与极限进行比较。在C#中,迭代器知道的更多——您可以不与任何外部引用进行比较就知道迭代器是否有效

我更喜欢C++方式,因为一旦有迭代器,就可以设置任何迭代器作为限制。换句话说,如果您希望只获取少数元素而不是整个集合,则无需更改迭代器(在C++中)。对我来说,它更“纯净”(清晰)

当然,在设计C++时,MS当然知道这一点。那么C#way的优势是什么?哪种方法更强大(这将导致基于迭代器的更优雅的函数)。我错过了什么

如果你对C + v+C++迭代器的思想有强烈的理解,请设计< <强> >,而不是限制它们(边界),请回答。 注意:(以防万一)请严格保持讨论的技术性。没有C++/C#flamewar

编辑 正如Tzaman所说,“将限制单独表示没有任何好处,因为除了一次遍历一个元素之外,没有其他方法可以实现。”然而,构建一个一次执行多个步骤的C#迭代器并不是那么困难,因此问题是——使用显式限制迭代器(如在C++中)是否有好处?如果是——什么

@乔恩, Edit1:假设您有一个函数foo,它在迭代器上执行某些操作(这个示例非常幼稚!)

现在,您想调用除最后10个元素之外的所有元素的函数栏

bar(iter_from,iter_end-10); // C++ style
在C#(如果我没有弄错的话)中,您必须为该迭代器提供额外的方法来更改其限制,如下所示:

bar(iter.ChangeTheLimit(-10));
编辑2:在重读了你的文章之后,我感觉到了关键的不同。在C++中,您对集合的迭代器进行工作,在C++中,您对集合进行工作(迭代器在内部使用)。如果是的话,我仍然对C感到有点不舒服——迭代集合,当您发现有趣的元素时,您希望将所有元素从“这里”传递到末尾。在C++中,它非常简单,没有开销。在C#中,可以传递迭代器或集合(如果后者需要额外计算)。我将等待您的评论:-)

@汉斯, 我不是在比较苹果和桔子。公司。理论是这里的共同点,因此您有排序算法、分区等。您有集合(或序列,如Jon所喜欢)的概念。现在,问题是如何设计元素的访问,以用C语言或C++语言(或任何其他语言)编写优雅的算法。我想理解“我们这样做是因为……”的理由

我知道.NET迭代器和集合是独立的类。我知道访问元素和访问整个集合之间的区别。然而,C++中最常用的方法是使用迭代器——这样,尽管集合完全不同,但您可以使用列表和向量。另一方面,在C#中,你更喜欢写作

sort(IEnumerable<T> coll) 
排序(IEnumerable coll)
代替功能

sort(IEnumerator<T> iter)
排序(IEnumerator iter)
对吗?因此,在这个意义上,我猜你不能把C迭代器作为C++迭代器,因为C ^不以和C++相同的方式表达相同的算法。或者正如Jon所指出的——在C语言中,你宁愿转换集合(跳过,取)而不是更改迭代器。

我觉得C语言的设计更像是一种封装:一个序列运行或执行,与其他任何事情无关。将一个限额与另一个限额进行比较有何意义

如果您只想获取几个元素,那么LINQ提供了许多从一个序列构建另一个序列的方法,例如

foo.Take(10)
foo.Skip(10)
foo.Where(x => x.StartsWith("y"))

我认为将一个序列转换成另一个序列比用限制来指定更清晰,也更可组合。如果要将迭代器传递给另一个函数,但要将其限制为前几个元素,为什么还要传递限制?为什么不通过自我限制的转换序列呢

编辑:为了解决您的问题编辑:在C#(至少使用LINQ)中,您不会修改现有集合。您将从旧序列创建一个新序列。这是懒惰的;它不会创建新副本或类似的内容。对于LINQ to对象,这是使用
IEnumerable
上的扩展方法执行的,因此任何序列都可以获得相同的功能

请注意,这并不局限于传统的集合—它可以是从日志文件中读取的一系列行(同样是惰性的)。您不需要任何关于集合本身的知识,只需要它是一个可以从中绘制项目的序列。
IEnumerable
IEnumerator
之间也有区别,前者表示序列,后者表示序列上的迭代器
IEnumerator
很少在C#中显式使用,也很少被传递

现在,您的“除最后10个元素外的所有元素”的示例是一个棘手的示例,因为对于一般序列,您无法判断从结尾到到达结尾的10个元素。LINQto对象中没有显式地执行此操作。对于实现
ICollection
ICollection
的任何内容,您可以使用

Bar(list.Take(list.Count - 10))
但这不是很普遍。一个更通用的解决方案需要保持10个元素的循环缓冲区,有效地提前读取10个元素。老实说,我很少发现这是一项要求

那么C#way的优势是什么

封装一个。如果您不手动设置迭代序列,则更难搞乱迭代限制

C++示例:

std::vector<int> a;
std::vector<int> b;
std::vector<int>::iterator ba = a.begin();
std::vector<int>::iterator ea = a.end();
std::vector<int>::iterator bb = b.begin();
std::vector<int>::iterator eb = b.end();
// lots of code here
for(auto itr = ba; itr != eb; itr++) // iterator tries to "cross" vectors
                                     // you get undefined behavior, depending 
                                     // on what you do with itr
std::向量a;
std::载体b;
std::vector::迭代器ba=a.begin();
std::vector::迭代器ea=a.end();
标准:v
std::vector<int> a;
std::vector<int> b;
std::vector<int>::iterator ba = a.begin();
std::vector<int>::iterator ea = a.end();
std::vector<int>::iterator bb = b.begin();
std::vector<int>::iterator eb = b.end();
// lots of code here
for(auto itr = ba; itr != eb; itr++) // iterator tries to "cross" vectors
                                     // you get undefined behavior, depending 
                                     // on what you do with itr
for(int i = 0; i< 1000; ++i)
{
    ... // do something

    if (i == 100)
       i = 200; // skip from 100 to 200
}