【问题标题】:Where is the inconsistency in this Icomparer that is causing a null reference?此 Icomparer 中导致空引用的不一致在哪里?
【发布时间】:2012-11-15 22:31:52
【问题描述】:

我在自定义 IComparer 实现中收到一个空对象,尽管它所应用的集合中没有空条目。我的理解是这可能是由 IComparer 实现中的不一致引起的。我无法在以下代码中发现这可能发生的位置。

作为参考,意图是这些首先按“正确”属性排序,然后如果它们相同,则根据“tiebreakerDelta”属性排序,该属性最接近于零排序而不会超过。

        public int Compare(IFoolsSortable a, IFoolsSortable b)
    {
        int value1 = a.correct;
        int value2 = b.correct;

        // compare the total correct first
        if (value1 < value2) return 1;
        if (value1 > value2) return -1;

        // total correct is the same, sort on deltas (closest without going over)
        value1 = a.tiebreakerDelta;
        value2 = b.tiebreakerDelta;

        // returning -1 says "put value1 higher in the list than value2" 
        // (higher means closer to the 0 element of the sorted array) 
        if (value1 == 0) return -1; // a zero is higher than anything! 
        if (value2 == 0) return 1; // ditto, for the other arg, if val1 isn't zero 
        if (value1 == value2) return 0; // after that, if they are the same, say so 
        // if both are negative, then the larger one goes higher 
        if (value1 < 0 && value2 < 0) return (value1 > value2) ? -1 : 1;
        // if only one is negative, it goes higher 
        if (value1 < 0) return -1;
        if (value2 < 0) return 1;
        // finally, if both are postitive, lower one goes higher 
        return (value1 > value2) ? 1 : -1;
    }

感谢您提供的任何帮助!

编辑:我确定这不是一个真正的空引用,它是由一些不一致引起的。此外,有时会显示此错误文本以确认 -

Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. x: '',  x's type: 'ResultsLineViewModel',

不幸的是,断点对我没有帮助。

编辑:这是一个简短的示例,其中 ResultsLineViewModel 实现了 IFoolsSortable 接口:

List<ResultsLineViewModel> ls = new List<ResultsLineViewModel>();
        ResultsLineViewModel line1 = new ResultsLineViewModel();
        line1.correct = 10;
        line1.tiebreakerDelta = 0;
        ls.Add(line1);

        ResultsLineViewModel line2 = new ResultsLineViewModel();
        line2.correct = 10;
        line2.tiebreakerDelta = 2;
        ls.Add(line2);

        ResultsLineViewModel line3 = new ResultsLineViewModel();
        line3.correct = 10;
        line3.tiebreakerDelta = -3;
        ls.Add(line3);

        ResultsLineViewModel line4 = new ResultsLineViewModel();
        line4.correct = 9;
        line4.tiebreakerDelta = 0;
        ls.Add(line4);

        ls.Sort(new FoolsSort());

正确的排序是:Line1, line3, line2, line4

【问题讨论】:

  • 你的空引用异常是否有与之关联的行号?
  • 如果a.tiebreakerDeltab.tiebreakerDelta 都是0,那么你将返回-1 而不是0(if (value1 == value2) return 0; 行永远不会被执行)。不知道这是否是您的 null 问题的原因,但这似乎是不一致的。
  • 不确定您在寻找什么样的帮助...只需在方法的开头放置带条件的断点 (a==null || b==null) 看看为什么会调用它与空...
  • 如果您能展示一个简短但完整的失败示例,这将非常有帮助。
  • 底部关于 Delta 的整个部分可以审查得更简单。而且我觉得那里可能会出现一些错误,因为您以特定顺序一个接一个地测试一个值。如果你想测试哪一个更接近 0,你可以Math.Abs() 他们两个,然后测试哪个更大。但是,知道 null 出现在哪里会很有帮助。

标签: c# .net compare icomparable icomparer


【解决方案1】:

如果a 大于b,则Compare(a,b) 应返回1,Compare(b,a) 应返回-1。如果您有a.correct = b.correct,并且有a.tiebreakerDelta = 0b.tiebreakerDelta = 0,那么这将与Compare 方法不一致,因为您希望保留操作的顺序。

据我所知,你应该先这样做

if (value1 == value2) return 0; // after that, if they are the same, say so

然后是这个:

if (value1 == 0) return -1; // a zero is higher than anything! 
if (value2 == 0) return 1; // ditto, for the other arg, if val1 isn't zero 

还要注意你的逻辑是相反的,如果第一个大于第二个,你应该返回 1,而不是 -1。检查例如这个link

【讨论】:

  • 尼克 - 非常感谢,按照您指定的重新处理订单似乎已经解决了问题!如果您不介意,您能否详细说明第一段 - 我想真正了解为什么这与原始错误相比有效。
  • 嗯,如您所见,第一个代码的问题是,当您有两个具有相同正确属性的项目并且两个 tiebreakerDelta 属性均为 0 时,调用 Compare(val1,val2) 将返回 (根据你的代码)-1,如果你用那些相同的实例来调用比较,比如比较(val2,val1)你会再次得到-1,这不是它应该如何工作的。想象一下,您正在调用 Compare(1,2) 并返回 -1,而当您调用 Compare(2,1) 时,它再次返回 -1。然后没有什么可比较的,它们的顺序比它们的价值更重要,你根本不应该排序。
  • 现在对我来说完全有意义,再次感谢 - 一旦你解释了这对我来说似乎很明显。干杯。
  • 除此之外,似乎 sort 正在将一个项目与其自身进行比较,如 Compare(a,a) 并且应该返回 0 而不是 -1。这就是为什么你得到你的例外。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
相关资源
最近更新 更多