【问题标题】:Does OrderBy calls guarantee to call the keySelector only once per element?OrderBy 调用是否保证每个元素只调用一次 keySelector?
【发布时间】:2020-02-06 09:42:21
【问题描述】:

his (accepted) response关于同步排序,mm8提供了这段代码:

int index = 0;
list1 = list1.OrderBy(d => list2[index++]).ToList();

代码很大程度上依赖于OrderBy 将调用提供的keySelector

  • 以原始序列顺序的参数
  • 每个元素仅一次

即使current implementationOrderBy 确实是这样工作的,是否有任何保证?

我在the OrderBy documentation 中没有找到任何线索。 LINQ 指南中都没有。

编辑:显然,改变行为对于依赖它的代码(如 mm8 代码)来说是一个重大改变。我的问题更多的是:当提供OrderBy 时,这种行为是否保证是不可变的,或者它现在是既成事实?。

【问题讨论】:

  • 不确定您的问题是什么? is there any guarantee about it?
  • 就个人而言,我对每个元素都会调用一次选择器这一事实感到满意:有很多代码会执行诸如 .OrderBy(x => new Guid()) 之类的操作,如果不保留它会中断,并且.NET 讨厌破坏向后兼容性。我对 in order 调用键选择器不太有信心,但我看不出这必然会改变的原因
  • is there any guarantee about it?。是的,这是我的问题。 OrderBy 是否会永远调用keySelector,并以原始序列顺序调用keySelector,并且每个元素仅调用一次。显然,改变行为对于依赖它的代码来说是一个重大改变(已经提供了示例),这是一个 fait accompli OrderBy 的工作方式。我的问题更多的是:当提供 OrderBy 时,这种行为是否保证是不可变的。
  • 要考虑的另一件事是 OrderBy 在 IEnumerable 上工作,因此它会在每次迭代中为每个项目调用一次键选择器。它在您的示例中调用它一次的“保证”是由于您在之后立即调用 ToList 的事实。虽然它不能完全回答您的问题,但它可能会阐明为什么没有记录和保证该行为......因为无法保证您将如何处理 OrderBy 函数生成的 IEnumerable .. 如果您迭代更多而不是一次你的关键功能将被每个项目多次调用
  • 你问错了社区。我们不能保证任何事情。

标签: c# linq


【解决方案1】:

根据source code 调用一次。但它可以在未来改变 - 不保证:

internal override void ComputeKeys(TElement[] elements, int count) 
{
    keys = new TKey[count];
    for (int i = 0; i < count; i++) keys[i] = keySelector(elements[i]);
    if (next != null) next.ComputeKeys(elements, count);
}

【讨论】:

    【解决方案2】:

    鉴于链接答案中的输入,可以构建一个新示例。

    var list1 = new List<string> { "A", "B", "C" };
    var list2 = new List<int> { 90, 50, 40 };
    

    跑步

    int index = 0;
    list1 = list1.OrderBy(d => list2[index++]).ToList();
    

    每个元素调用一次,输出将如下所示:

    list1 = {"C","B","A"}

    list2 = {90,50,40}

    关于这种行为不会改变的任何保证?

    不,不能保证。过去阅读Jon Skeets Article on C# history of things that have broken / changed behaviour between versions

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多