我最近意识到,您不应该对 IEnumerable 的实现做出任何假设(例如,您不能假设当您在 foreach 循环期间对来自 IEnumerable 的对象之一进行更改时,之后循环(甚至在每次迭代之后)可以在 IEnumerable 中找到更改的对象,
因此在重新检查我对 IEnumerable 的假设之后,我得出的结论是,实际上您唯一可以确定的是。它允许您遍历集合的所有元素,其中集合(不是 ICollection 本身)可以是任何东西。
我认为我不能做出的另一个假设是,理论上您可以指定底层集合的顺序。我想说的是,每次循环时都以不同的顺序获取项目。
现在回到我原来的问题,考虑到上述内容,First()
和Last() 每次都可以返回不同的项目(理论上看看 IEnumerable 是什么)?
额外信息:
当然,通常这没问题,因为 IEnumerable 是通过有序的东西实现的。但是,如果 IEnumerable 调用 Web 服务来获取其元素会怎样?
背景信息:
我正在考虑这个,因为我想为 foreach 循环中的第一个和最后一个元素做一些特定的事情。所以我检查了 if(currentElement == Enumerable.Last())
I recently came to realize that you shouldn't make any assumptions on the implementation of an IEnumerable (for example that you can't assume that when you make changes to one of the objects that came from the IEnumerable during a foreach loop, that after the loop (or even after each iteration) the changed object can be found in the IEnumerable.
So after re-examining my assumptions about IEnumerable, I came to the conclusion that in fact the only thing you can know for sure is that it allows you to traverse all the elements of a collection, where a collection (not ICollection per se) can be anything.
Another assumption that I think that I cannot make is that the order of the underlying collection is something specific. Theoretically you could get the items in a different order everytime you loop over them I'd say.
Now to return to my original question, taking the above into account, First()
and Last()
could return different items every time (theoretically looking at what an IEnumerable is)?
Exra info:
Of course usually this will be fine because the IEnumerable is implemented by something that is ordered. But what if the IEnumerable makes calls to a webservice to get its elements.
Background info:
I was thinking about this because I wanted to do something specific for the first and last element in a foreach loop. So I checked if(currentElement == Enumerable.Last())
发布评论
评论(6)
First()
获取一个枚举器并返回它找到的第一个值。Last()
最常迭代整个集合并在到达枚举末尾之前返回元素一。是的,这就是你所知道的一切。具体来说,集合可以是无限的,然后Last()
将永远不会返回。Jon Skeet 有一系列关于 LINQ 运算符的非常有用的文章 - 请参阅 Edulinq。他描述了每个 LINQ 运算符,并详细讨论了所有想法和假设。它提供了关于所有这些事情如何真正运作的很好的见解。
First()
gets an enumerator and return first value that it founds.Last()
most often iterates through the whole collection and returns element one before reaching the end of enumeration. And right, that's all you know for sure. Specifically, collection can be infinite and thenLast()
will never return.There is very helpful series of articles about LINQ operators by Jon Skeet - see Edulinq. He describes every single LINQ operator and discuss all the ideas and assumptions in details. It gives very good insight in how all those things really work.
Last()
确实是最后一个,但调用它会枚举您的 Enumerable。它并非没有成本或副作用。这还给出了
Last()
的定义:迭代当前产生的最后一个元素。更改列表,您可能会得到另一个 Last()。Last()
is really the last, but calling it enumerates your Enumerable. It is not free of cost or side-effects.And that also gives you the definition of
Last()
: the last element that an iteration currently yields. Change the list and you may have another Last().我想在多线程环境中,
.First
和.Last
可能被证明是不确定的,特别是如果您对并发性不小心的话。I'd imagine that in a multithreaded environment,
.First
and.Last
could prove to be non-deterministic, especially if you're not careful with your concurrency.正如其他人提到的,如果您不知道底层可枚举是什么,您可能不应该假设 First() 或 Last() 的行为符合您的预期。但是,如果您已经要循环 IEnumerable 并希望获得可枚举当前状态的“快照”,那么您将能够保证 First() 和 Last() 的行为符合预期。我会将 IEnumerable 转换为这样的列表(或数组),然后您就不会有任何问题:
As others mentioned, if you don't know what the underlying enumerable is, you probably shouldn't assume that First() or Last() behave as you would expect. However if you're already going to be looping over the IEnumerable and want to get a 'snapshot' of the current state of the enumerable, then you'd be able to guarantee First() and Last() behave as expected. I would convert the IEnumerable to a list (or array) like this and then you shouldn't have any problems:
您可以使用 Enumerable.OrderBy Method 来确保枚举是有序的根据理想的标准并获得您真正想要的第一个或最后一个项目。
You can use Enumerable.OrderBy Method to make sure that the enumerable is ordered by the desirable criteria and to get the first or last items you realy want.
Enumerable.first() 和 Enumerable.last() 实际上是真正的第一个和最后一个元素。
在这种情况下,您必须指定您认为应该是第一个和最后一个元素。它很大程度上取决于例如您如何对 Enumerable 中的元素进行排序以及在此过程中集合是否发生更改/修改。如果您想更加确定每次请求 .first() 和 .last() 时都能检索相同的项目,您应该实现更多逻辑,例如排序。
The Enumerable.first() and Enumerable.last() are in fact the real first and last elements.
In this case you have to specify what you think should be the first and last element. It strongly depends on for example how you sort your elements inside the Enumerable and if the collection is changed / modified during the proces. If you want to be more sure on retrieving the same items everytime you request .first() and .last() you should implement some more logic like sorting.