2011-03-28 31 views
4

我有以下問題,我不知道它來自哪裏。我非常感謝幫助。list.Sort ArgumentException錯誤:IComparer不會返回0(空)

代碼:

List<Point> lst = new List<Point>(); 
lst.Add(new Point(0, -2)); 
lst.Add(new Point(-1, -2)); 

lst.Sort(delegate (Point x,Point y) 
{ 
    if (x.X == 0) 
     return -1; 
    else if (y.X == 0) 
     return 1; 
    else 
    { 
     double retVal1 = x.Y * 1.0/-x.X; 
     double retVal2 = y.Y * 1.0/-y.X; 
     int retVal = -Math.Sign(retVal1 - retVal2); 
     return retVal; 
    } 
}); 

如果執行,我收到一個ArgumentException說的IComparer不不返回0(零)。但是,它實際上不能返回除-1,0和1之外的任何其他內容,或者?

非常感謝您的幫助!

啊,順便說一句我使用.NET 3.5

+0

它_doesn't_ return 0你認爲它在哪裏?即使「else」塊中的計算_did_等於零,也不知道。 – 2011-03-28 12:44:58

回答

8

實際上,錯誤消息說:當Array.Sort調用x時,IComparer(或它依賴的IComparable方法)沒有返回零。的CompareTo(X)。 x:''x's type:'Point'IComparer:'System.Array + FunctorComparer`1 [System.Drawing.Point]'

您必須返回0,如果對象是相同的:身份需要平等(的東西總是等於本身)和平等需要等價

lst.Sort(delegate(Point x, Point y) { 
     if (x.X == y.X && x.Y == y.Y) { // you are missing this 
      return 0; 
     } 
     if (x.X == 0) 
      return -1; 
     else if (y.X == 0) 
      return 1; 
     else { 
      double retVal1 = x.Y * 1.0/-x.X; 
      double retVal2 = y.Y * 1.0/-y.X; 
      int retVal = -Math.Sign(retVal1 - retVal2); 
      return retVal; 
     } 
    }); 
+1

這仍然違反了下一次測試中的一致排序,就好像點a是{0,1},點b是{0,2},然後調用(a,b)返回-1意味着a 2011-03-28 13:07:55

+0

@Jon Hanna:你是對的,我只是檢查了這個例子發生的錯誤,並假設其餘的都是正確的。 – 2011-03-28 14:28:07

2

你還沒有完全閱讀異常信息。它最有可能說它不會爲同一個對象實例返回0。

您的代碼有誤,如果Point的相同實例或相同的值被傳入,則需要返回0。否則,他永遠不會知道他何時完成排序,並最終陷入無盡的循環......我們都知道這是一個絕對的負面表現。

+0

啊,好的,比較器必須爲0才能獲得相同的值。不知道,謝謝你的回答! (其實這很合乎邏輯,但它從來沒有發生過) – 2011-03-28 12:47:28

0

至於說,一個比較器必須爲相同的值返回0 (你可能等同地命令兩個不同的東西,但你必須等於命令兩個等於的東西)。

還有一個問題是,如果.X爲0的檢查可能導致相同的項返回不一致的排序,如果它們都具有.X等於0的話。比較方法必須始終保持一致其中:

如果x < y則y> x。

如果x < y和y < z然後x < z。

你的算法將所述第一規則是這樣的:

說點a是{0,3}和點b是{0,2}

與(A,B),然後返回調用-1意思是< b,但用(b,a)調用返回-1意味着b < a。

更換整個事情有:

lst.Sort(delegate (Point x,Point y) 
{ 
    return (x.Y * 1.0/-x.X).CompareTo(y.Y * 1.0/-y.X); 
}); 

(請注意,這隱含了相同的分數返回0 - 我們可以添加一個明確的檢查,如果這是一個重計算作爲優化,但沒有必要。

另外,是Point這裏System.Drawing.Point?如果是這樣,那麼這段代碼現在可以正常工作,但是如果它是其他內容,那麼值得注意的是,如果Point是一個結構,那麼代碼就沒問題,但如果Point是一個類,應該包含一個空檢查。