它被订购了多少次 IENumerable?
How many times it is ordered a IENumerable?
我知道当我迭代 IEnumerable 时,我会迭代源集合,因此如果我在 IEnumerable 的下一次迭代中修改了源集合,它会计算修改。
所以我想知道当我有一个有序的 IEnumerable 时它会如何影响它。
例如,如果我有这个:
List<MyType> myNoOrderedList //add my items
IEnumerable<MyType> myOrderedIEnumerable = myNoOrderedList
.OrderBy(x => x.Property);
foreach(MyType in myOrderedIEnumerable)
{
//Do something
}
假设我在列表中有 3 个元素,在 IEnumerable 的每次迭代中,列表是有序的还是只对列表进行一次排序?
如果我在 "Do something" 中添加或删除项目会怎样? IEnumerable 有初始订购的项目或必须重新订购以考虑列表的修改?
Supose that I have 3 elements in the list, in each iteration on IEnumerable, the list is ordered or only the list is ordered once?
根据你现在的代码,只有一次。
每次获得枚举器时都会对列表进行排序。
您的 foreach
语句将被编译成 try..finally
,只有一个枚举器将用于遍历集合。
What happen if in "Do something" I add or remove an item? The IEnumerable has initial ordered items or has to order again to has account the modification of the list?
如果您在从 IOrderedEnumerable
获取枚举器之前从 myNoOrderedList
添加或删除项目,则它将包含在排序结果中。
如果您在开始枚举已排序的集合之后执行此操作,那么它不会以任何方式影响您的活动枚举,因为已排序的项目被缓冲并从缓冲区返回。
但是,请记住,如果您可以向枚举集合中添加或删除项目(在您的情况下为 miOrderedIEnumerable
),那么您将得到 InvalidOperationException
说 "Collection was modified; enumeration operation may not execute"。
答案:
- 最多一次(在 实现 如果有的话)
- 由于您已经具体化
myOrderedIEnumerable
将不会看到初始 myNoOrderedList
的任何修改:
简化示例:
List<string> initial = new List<String>() {
"a", "z", "e", "d";
};
// Nothing will be done at this point (no ordering)
var ordered = initial.
.OrderBy(x => x.Property);
// ordered has not materialized here, so it'll feel Addition
initial.Add("y"); // <- will be added into ordered
// Here on the first loop ordered will be materialized and since
// initial and ordered are different collection now, we can modify
// initial without changing ordered
foreach (var item in ordered) {
if (item == "a") {
initial.Add("b");
initial.Remove("z");
}
Console.WriteLine(item);
}
结果:
a
d
e
y <- before materialization
z
编辑:请注意,物质化是一件棘手的事情:它可能被称为:
- 立即,在声明中,例如在
.ToList()
、.Any()
、.FirstOrDefault()
之后
- 在第一项上,例如
.OrderBy
(你的情况)
- 从不
.Where()
、.SkipWhile()
- 查看 Magnus 的评论
Linq 是懒惰的并且尽可能晚地执行实体化。
每次需要OrderBy
的结果,一个buffered copy of the source is sorted。例如:
int[] array = { 2, 1, 3 };
var ordered = array.OrderBy(x => x);
foreach (int i in ordered)
{
array[1] = 0;
Debug.Write(i); // 123
}
foreach (int i in ordered)
Debug.Write(i); // 023
我知道当我迭代 IEnumerable 时,我会迭代源集合,因此如果我在 IEnumerable 的下一次迭代中修改了源集合,它会计算修改。
所以我想知道当我有一个有序的 IEnumerable 时它会如何影响它。
例如,如果我有这个:
List<MyType> myNoOrderedList //add my items
IEnumerable<MyType> myOrderedIEnumerable = myNoOrderedList
.OrderBy(x => x.Property);
foreach(MyType in myOrderedIEnumerable)
{
//Do something
}
假设我在列表中有 3 个元素,在 IEnumerable 的每次迭代中,列表是有序的还是只对列表进行一次排序?
如果我在 "Do something" 中添加或删除项目会怎样? IEnumerable 有初始订购的项目或必须重新订购以考虑列表的修改?
Supose that I have 3 elements in the list, in each iteration on IEnumerable, the list is ordered or only the list is ordered once?
根据你现在的代码,只有一次。
每次获得枚举器时都会对列表进行排序。
您的 foreach
语句将被编译成 try..finally
,只有一个枚举器将用于遍历集合。
What happen if in "Do something" I add or remove an item? The IEnumerable has initial ordered items or has to order again to has account the modification of the list?
如果您在从 IOrderedEnumerable
获取枚举器之前从 myNoOrderedList
添加或删除项目,则它将包含在排序结果中。
如果您在开始枚举已排序的集合之后执行此操作,那么它不会以任何方式影响您的活动枚举,因为已排序的项目被缓冲并从缓冲区返回。
但是,请记住,如果您可以向枚举集合中添加或删除项目(在您的情况下为 miOrderedIEnumerable
),那么您将得到 InvalidOperationException
说 "Collection was modified; enumeration operation may not execute"。
答案:
- 最多一次(在 实现 如果有的话)
- 由于您已经具体化
myOrderedIEnumerable
将不会看到初始myNoOrderedList
的任何修改:
简化示例:
List<string> initial = new List<String>() {
"a", "z", "e", "d";
};
// Nothing will be done at this point (no ordering)
var ordered = initial.
.OrderBy(x => x.Property);
// ordered has not materialized here, so it'll feel Addition
initial.Add("y"); // <- will be added into ordered
// Here on the first loop ordered will be materialized and since
// initial and ordered are different collection now, we can modify
// initial without changing ordered
foreach (var item in ordered) {
if (item == "a") {
initial.Add("b");
initial.Remove("z");
}
Console.WriteLine(item);
}
结果:
a
d
e
y <- before materialization
z
编辑:请注意,物质化是一件棘手的事情:它可能被称为:
- 立即,在声明中,例如在
.ToList()
、.Any()
、.FirstOrDefault()
之后
- 在第一项上,例如
.OrderBy
(你的情况) - 从不
.Where()
、.SkipWhile()
- 查看 Magnus 的评论
Linq 是懒惰的并且尽可能晚地执行实体化。
每次需要OrderBy
的结果,一个buffered copy of the source is sorted。例如:
int[] array = { 2, 1, 3 };
var ordered = array.OrderBy(x => x);
foreach (int i in ordered)
{
array[1] = 0;
Debug.Write(i); // 123
}
foreach (int i in ordered)
Debug.Write(i); // 023