List.orderBy 陷入无限循环

Dan*_*llo 1 c# infinite-loop visual-studio

我有一个List<Expense> myListwhere 费用包含 2 个字段: decimal Amount和一个Status ItemStatus. 状态是enum {Paid, DueSoon, DueToday, Overdue, Unpaid}.

我试图按升序或降序对列表进行排序,但是Status.Unpaid需要始终以升序或降序出现在最后。

myList.Sort((x, y) => comparer.Compare(x.ItemStatus, y.ItemStatus))与我的比较器一起使用效果很好。

但是,在对列表进行排序后,ItemStatus我还想对列表进行排序Amount。所以我决定使用myList = myList.OrderBy(x => x.ItemStatus, comparer).ThenBy(x => x.Amount).ToList()它导致某个地方的无限循环。

当我.ThenBy()完全删除该方法时,无限循环仍然存在。

我在比较器中添加了一个静态计数器来尝试调试,该OrderBy()方法进入无限循环之前在30 个费用列表中使用了比较器 90 次。

这是我的比较器:

class StatusComparer : IComparer<Status>
{
    public bool IsAscending { get; private set; } = true;

    public StatusComparer(bool isAscending)
    {
        IsAscending = isAscending;
    }

    public int Compare(Status x, Status y)
    {
        if (IsUnpaid(x)) { return IsAscending? 1 : -1; }
        if (IsUnpaid(y)) { return IsAscending ? -1 : 1; }


        return x.CompareTo(y);
    }


    private static bool IsUnpaid(Status status)
    {
        return status.CompareTo(Status.Unpaid) == 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

我做错了什么或者我怎样才能实现我想要做的事情?

提前致谢。

Dmi*_*nko 5

你的实现Compare不正确

public int Compare(Status x, Status y)
{
    if (IsUnpaid(x)) { return IsAscending? 1 : -1; }
    if (IsUnpaid(y)) { return IsAscending ? -1 : 1; }

    return x.CompareTo(y);
}
Run Code Online (Sandbox Code Playgroud)

想象一下,我们有IsAscending == trueIsUnpaid(x) == trueIsUnpaid(y) == true。在这种情况下

x.Compare(y) == 1 // so x > y
y.Compare(x) == 1 // so y > x
Run Code Online (Sandbox Code Playgroud)

这就是为什么很OrderBy可能会进入无限循环的原因({x, y}如果x > y和,收集的正确顺序是什么y > x?)。你,可能,想要

public int Compare(Status x, Status y) {
  if (IsUnpaid(x)) { 
    if (!IsUnpaid(y))
      return IsAscending ? -1 : 1; // x is UnPaid, y is Paid
  }
  else if (IsUnpaid(y)) { 
    return IsAscending ? 1 : -1;   // x is Paid, y is UnPaid
  }

  // x and y either both Paid or unPaid
  // If IsAscending should be taken into account, use it as below:
  // return IsAscending ? x.CompareTo(y) : y.CompareTo(x);
  return x.CompareTo(y);
}
Run Code Online (Sandbox Code Playgroud)