【问题标题】:ArgumentOutOfRangeException when sorting a DataGridView using a custom IComparer使用自定义 IComparer 对 DataGridView 进行排序时出现 ArgumentOutOfRangeException
【发布时间】:2012-12-22 14:14:49
【问题描述】:

设置

我有一段代码使用自定义 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 消息“索引超出范围。参数:索引”。

更多事实

进一步调查发现:

  • 我正在排序的 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...

【问题讨论】:

  • 当两者的 ReadOnly 为 false 时,您将返回 -1。

标签: c# sorting datagridview indexoutofboundsexception


【解决方案1】:

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

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

 if((row1.ReadOnly && row2.ReadOnly) || !(row1.ReadOnly || row2.ReadOnly))

【讨论】:

    【解决方案2】:

    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) 会返回的结果,这就是为什么您的“解决方法”(我认为这是一个更好的解决方案)有效的原因。

    【讨论】:

    • 谢谢,我发现了不对称,但没有考虑到它可能是索引超出范围异常的原因。在我的调查期间,我确实重写了该方法以仅返回 -1,以确保这是问题所在。你的解释很有道理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2021-09-28
    • 2020-07-31
    • 2015-10-12
    • 2020-03-24
    • 2012-12-29
    相关资源
    最近更新 更多