IEnumerable<T> 上的延迟 OrderBy

Deferred OrderBy on IEnumerable<T>

我有这个代码,它只是根据每个整数中的数字对整数的 IEnumerable 进行排序。

var ints = new List<int>() { 66, 7, 9, -5, -22, 67, 122, -333, 555, -2 };
var ordered = ints.OrderBy(x =>
{
   x = Math.Abs(x);

   Console.WriteLine($"Getting length of {x}");

   int len = 0;
   while (x >= 1)
   {
      len++;
      x /= 10;
   }
   return len;
});

   Console.WriteLine("After OrderBy");
   Console.WriteLine("Fetching first item in ordered sequence");
   Console.WriteLine($"First item is {ordered.First()}");

   Console.WriteLine(string.Join(" ", ordered));

因此,当程序在 ordered 序列中获取第一项时,IEnumerable 正在排序(我正在接收输出行 Getting lenght of XXX),因为 OrderBy 被推迟了,那很清楚。

但是为什么当程序点击时 Console.WriteLine(string.Join(" ", ordered)); 我又得到了这个输出? IEnumerable 是否再次排序? (不是已经排序了吗?)

当您将值赋给 ordered 时,它们实际上并没有排序。它基本上是订购清单的说明。 IOrderedEnumerable<int>。因此,每次您尝试访问第一个项目或任何其他项目时,它都会将其转换为有序列表,以便为您提供该项目。第一次是你运行.First(),第二次是你运行string.Join.
在这两种情况下,程序都会创建一个有序列表的 2 个不同实例,用完它,然后通过丢失引用来处理它(因为你没有保存它)。

如果你需要Ordered只排序一次,你需要在它上面调用ToList(),在这种情况下你只会看到一次列表结果。既然订了。

var ints = new List<int>() { 66, 7, 9, -5, -22, 67, 122, -333, 555, -2 };
var ordered = ints.OrderBy(x =>
{
    x = Math.Abs(x);

    Console.WriteLine($"Getting length of {x}");

    int len = 0;
    while (x >= 1)
    {
        len++;
        x /= 10;
    }
    return len;
}).ToList();

Console.WriteLine("After OrderBy");
Console.WriteLine("Fetching first item in ordered sequence");
Console.WriteLine($"First item is {ordered.First()}");
Console.WriteLine(string.Join(" ", ordered));