订购IENumerable的次数是多少次?

时间:2017-07-17 10:25:01

标签: c# ienumerable

我知道当我迭代一个IEnumerable时,我会迭代源集合,所以如果我在IEnumerable的下一次迭代中修改了源集合,它就会计算出modificaction。

所以我想知道当我有一个有序的IEnumerable时它会如何影响它。

例如,如果我有这个:

List<MyType> myNoOrderedList //add my items

IEnumerable<MyType> myOrderedIEnumerable = myNoOrderedList
  .OrderBy(x => x.Property);

foreach(MyType in myOrderedIEnumerable)
{
    //Do something
}

假设我在列表中有3个元素,在IEnumerable的每次迭代中,列表是有序的,还是只列出一次列表?

如果在&#34;做某事&#34;会发生什么?我添加或删除项目? IEnumerable有初始订购的商品,还是必须再次订购以便对帐户进行修改?

3 个答案:

答案 0 :(得分:5)

数目:

  1. 最多一次(物化,如果有的话)
  2. 由于您已具体化myOrderedIEnumerable将无法看到对myNoOrderedList的任何修改:
  3. 简化示例:

     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 
    

    编辑:请注意,materization是一个棘手的事情:可能会被称为:

    1. 立即声明,例如在.ToList().Any().FirstOrDefault()
    2. 之后
    3. 在第一项上,例如.OrderBy(您的情况)
    4. 从不.Where().SkipWhile() - 请参阅Magnus的评论
    5. Linq 是懒惰的,并尽可能地实现。

答案 1 :(得分:2)

  

假设我在列表中有3个元素,在IEnumerable的每次迭代中,列表是有序的,还是只列出一次列表?

根据您当前的代码,只有一次。
每次获得一名普查员时,都会对该名单进行排序 您的foreach语句将编译为try..finally,只有一个枚举器将用于迭代收集。

  

如果在&#34;做某事&#34;会发生什么?我添加或删除项目? IEnumerable有初始订购的商品,还是必须再次订购以便对帐户进行修改?

如果您在从myNoOrderedList获取枚举数之前在IOrderedEnumerable添加或删除项目,则会将其包含在已排序的结果中。
如果您在开始枚举已排序的集合后执行此操作,则不会以任何方式影响您的活动枚举,因为已排序的项目已缓冲并从缓冲区返回。

但是,请注意,如果您可以添加或删除项目来枚举集合(在您的情况下为miOrderedIEnumerable),那么您会得到 InvalidOperationException #34;收藏被修改;枚举操作可能无法执行&#34;。

答案 2 :(得分:0)

每次需要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