Where is the inconsistency in this Icomparer that is causing a null reference?

Wil*_*ead 8 .net c# compare icomparable icomparer

I'm receiving a null object in my custom IComparer implementation despite no null entries in the collection it is being applied to. My understanding is this can be caused by inconsistencies in the IComparer implementation. I cannot spot where this could be happening in the following code.

For reference the intent is that these are sorted by the 'correct' property first, then if they are the same, it sorts based on the 'tiebreakerDelta' property, which sorts closest to zero without going over.

        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;
    }
Run Code Online (Sandbox Code Playgroud)

Thanks for any help you might be able to offer!

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

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',
Run Code Online (Sandbox Code Playgroud)

不幸的是,断点并没有帮助我.

编辑:这是一个简短的例子,其中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());
Run Code Online (Sandbox Code Playgroud)

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

Nik*_*vic 18

如果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
Run Code Online (Sandbox Code Playgroud)

然后这个:

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 
Run Code Online (Sandbox Code Playgroud)

另请注意,您的逻辑是相反的,如果第一个比第二个更大,则应返回1,而不是-1.检查此链接

  • 好吧,正如你所看到的,第一个代码的问题是当你有两个具有相同正确属性的项目并且当两个tiebreakerDelta属性都为0时,则调用Compare(val1,val2)将返回(根据你的代码)-1,如果你用比较(val2,val1)这些相同的实例调用Compare,你将再次获得-1,这不是它应该如何工作.想象一下,你正在调用Compare(1,2)并返回-1,当你调用Compare(2,1)时它再次返回-1.然后没有什么可比的,他们的顺序比他们的价值更重要,你根本不应该排序. (3认同)