我知道IEnumerable<T>
在被调用之前不会迭代。
假设我有这样的代码:
foreach(int iteratorInt in myIEnumerable.OrderBy(x => x))
{
if(iteratorInt == myIEnumerable.First())
{
// do something
}
}
在if
中,我检查的是第一个元素,那么myIEnumerable
是否必须在每次迭代时排序,以确定哪个是第一个元素,或者它只排序一次?
4条答案
按热度按时间jhdbpxl91#
当使用LINQ扩展时,查询将仅在请求时执行,否则称为延迟执行。当多次请求相同的查询时,每次都会重新计算底层查询,除非初始查询已经用
.ToArrary()
或.ToList()
之类的东西物化。这个问题并不完全清楚,所以我将提供一些示例来演示各种行为。
例1:
验证码:
例2:
验证码:
实施例3:
验证码:
所有查询都使用相同的方法来获取可枚举对象:
结果将结束为:
kyxcudwk2#
您的Enumerable将只被排序一次,如下所示:
myIEnumerable.OrderBy(x => x)
在这一行
if(iteratorInt == myIEnumerable.First())
,它将不会被再次订购。也许你误解了
IEnumerable.First
方法,IEnumerable.First
和IEnumerable.OrderBy
方法之间没有关系。您可以在这里看到一个定制的
OrderBy
方法:输出:
发生了什么事?
首先调用
MyCustomOrderBy
方法,他需要遍历整个集合来对元素进行排序。然后开始foreach,并对每个项目执行
myIEnumerable.First()
:最后,你得到了你想要的:
zed5wv103#
对于此代码:
OrderBy
只执行一次cigdeys34#
OrderBy
只计算一次,但是,每次迭代都会创建一个基于原始无序myIEnumerable
的新IEnumerator<T>
,并且它可能不会在第一次迭代中匹配iteratorInt
,除非第一个元素恰好是排序到第一个位置的元素。如果你想让
iteratorInt
的第一次迭代的值匹配enumerable的First()
结果,你需要在循环之前创建一个有序enumerable的临时副本,像这样:虽然这是一个相当无意义的模式(类似于“Loop-switch”反模式),但它可以简化为: