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