使用自定义IComparer对DataGridView排序时出现ArgumentOutOfRangeException

本文关键字:ArgumentOutOfRangeException 排序 DataGridView 自定义 IComparer | 更新日期: 2023-09-27 17:50:58

设置

我有一段代码正在使用自定义IComparer:对DataGridView进行排序

public class CustomComparer: IComparer
{
    public int Compare(object x, object y)
    {
        DataGridViewRow row1 = (DataGridViewRow)x;
        DataGridViewRow row2 = (DataGridViewRow)y;
        if (row1.ReadOnly && row2.ReadOnly)
        {
            return 0;
        }
        else if (row1.ReadOnly && !row2.ReadOnly)
        {
            return 1;
        }
        else
        {
            return -1;
        }
}

问题

奇怪的是,当我执行以下行时(在填充行之后(:

grid.Sort(new CustomComparer());

我得到一个ArgumentOutOfRangeException,消息为"索引超出范围。参数:Index"。

更多事实

进一步调查显示:

  • 我正在排序的DataGridView上没有BindingSource-行是手动添加的
  • 错误的堆栈跟踪只有一级深度-它发生在mscorlib中的InternalDictionary上
  • 奇怪的事实#1-只有在任何时候,我的自定义比较器对其任何比较都返回-1时,才会发生这种情况
  • 如果我将Sort方法更改为不再使用CustomComparer,则不会引发异常

变通办法

最后一个事实导致我重写了Compare((方法,以遵从.NET的CompareTo方法:

DataGridViewRow row1 = (DataGridViewRow)x;
DataGridViewRow row2 = (DataGridViewRow)y;
return row1.ReadOnly.CompareTo(row2.ReadOnly);

它神秘地工作了。不再引发异常。

因此,尽管我有一个变通办法,但我想知道是否有人知道为什么这可能是一个解决方案,以及问题最初可能是什么。我看过CompareTo的实现,它返回-1…

使用自定义IComparer对DataGridView排序时出现ArgumentOutOfRangeException

juharr是对的,但下面是他是对的原因:

Compare的实现不是对称的,这意味着如果row1.ReadOnly == falserow2.ReadOnly == false,则返回-1,意味着"row1小于row2"。如果使用相同的值进行比较,则row2将小于row1。这可能会混淆要求Compare对称的排序算法。

正确的比较应该是:

    if (row1.ReadOnly == row2.ReadOnly)  // change && to ==
    {
        return 0;
    }
    else if (row1.ReadOnly && !row2.ReadOnly)
    {
        return 1;
    }
    else
    {
        return -1;
    }

这很可能是bool.CompareTo(bool)会返回的结果,这就是为什么您的"变通方法"(在我看来,这是一个更好的解决方案(有效。

问题是,当两者都有ReadOnlyfalse时,您将返回-1。在这种情况下,您应该返回0

只需将您的第一个if语句更改为

 if((row1.ReadOnly && row2.ReadOnly) || !(row1.ReadOnly || row2.ReadOnly))
相关文章:
  • 没有找到相关文章