【问题标题】:IComparer issueIComparer 问题
【发布时间】:2013-05-08 07:46:41
【问题描述】:

我有一个奇怪的问题,我不知道原因。我会尽量清楚地描述我的问题。

我有一个 RTree 类,在这个类中,我想比较两个矩形(这里我称为信封,它包含 minX、minY、maxX、maxY),所以我们有一个比较器类如下:

private class AnonymousXComparerImpl : IComparer
{
    public AnonymousXComparerImpl()
    { }

    public int Compare(object o1, object o2) 
    {
        IEnvelope ea = (IEnvelope)((IBoundable)o1).Bounds;
        IEnvelope eb = (IEnvelope)((IBoundable)o2).Bounds;
        double a = (ea.MinX + ea.MaxX) / 2d;
        double b = (eb.MinX + eb.MaxX) / 2d;
        return a > b ? 1 : a < b ? -1 : 0;
    }
}

使用这个比较器,我们可以维护一个信封的ArrayList并轻松对其进行排序,信封是随机添加的。当我们调用下面的代码,我们遇到了

无法排序,因为 IComparer.Compare() 方法返回 结果不一致。要么一个值不等于它自己, 或一个值与另一个值重复比较会产生不同的 结果。

sortedChildBoundables.Sort(new AnonymousXComparerImpl());

这是奇怪的部分。此错误仅发生在未安装 VisualStudio 的 .net 4.0 中。如果机器安装了VS或者.net 4.5,这个问题就不能再出现了。

在这种情况下,我无法弄清楚为什么会发生这种情况。如果您对调试此类问题有任何经验,那就太好了,我很感激。

谢谢, 霍华德

【问题讨论】:

  • 我在这里唯一能想到的是浮点问题,这意味着相同项目的相等性并不完全匹配,不知道为什么它特定于 v4。您是否尝试过强制舍入?
  • 尝试使用 decimal 数据类型而不是双精度
  • 没有其他线程涉及吗?另外,这个线程可能很有趣:stackoverflow.com/questions/6683059/…
  • MinX、MaxX 值可以是 NaN 吗?
  • 您是否尝试过只使用return a.CompareTo(b); 来代替?您的问题可能是 NaN != NaN。

标签: c# .net icomparer r-tree


【解决方案1】:

如果例如ea.MinXNaNaNaNa &gt; ba &lt; b 都是 false。这意味着,有些对象比较等于所有其他对象。

您首先必须决定如何对包含NaN 的对象进行排序。

一个简单的解决方法可能是插入

if (double.IsNaN(a)) a = 0.0;
if (double.IsNaN(b)) b = 0.0;

正如 cmets 中的 @Seph 和 @Jeppe 所指出的,double.CompareTo 做了正确的事情,所以最后一行可以替换为 return a.CompareTo(b);

【讨论】:

  • +1 这听起来很合理——尽管我不确定为什么 .Net 版本之间的结果会有所不同。但是,如果数据中可以存在NaN(并且OP说可以),那么它肯定会导致观察到的那种问题。
  • 说的有道理,请允许我暂时保留这个帖子,稍后标记为答案。非常感谢。
  • @MatthewWatson - 也许新版本中的Sort 函数不会进行不必要的比较,因此无法检测到不一致。
  • 只替换原始代码(问题)中的最后一行更简单:return a.CompareTo(b);。方法double.CompareTo(double) 处理NaN 和无穷大。它不会投射到0.0,但是。NaN 将位于任何负数之前。 补充:刚刚看到 Seph 很久以前在对该问题的评论中提出了这个建议。
【解决方案2】:

一个可能的原因是您的信息在比较过程中实际上发生了变化。

如果您在后台线程中进行排序,如果在两次请求时比较获得相同项目的不同值,您肯定会收到此错误。

例如,如果您的主线程在比较运行时更新了其中一个值(可能通过数据绑定)。

确保缓存比较的值,以便始终返回一致的结果。或者接受错误可能不时发生并重新排序。

这也将解释您对机器/操作系统依赖的感觉。多线程问题会因软件和硬件的不同而不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2010-10-30
    • 2012-01-11
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    相关资源
    最近更新 更多