2011-03-28 14 views
4

私は次の問題があり、どこから来るのか分かりません。私は非常に助けていただければ幸いです。list.Sort ArgumentExceptionエラー:IComparerは0(null)を返しません

コード:

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; 
    } 
}); 

実行された場合、私がしたIComparerが0(null)を返しませていないことを言ってArgumentExceptionがを受け取ります。しかし、実際に-1、0、1以外の何も返しませんか?

ありがとうございました!

あ、ところで私は、.NET 3.5

+0

0を返しません。どこに表示されますか? elseブロック_did_の計算がゼロに等しい場合でも、それは分かっていません。 –

答えて

8

実際には、エラーメッセージ:IComparer(またはそれが依存するIComparableメソッド)は、Array.Sortがxを呼び出すとゼロを返しませんでした。 CompareTo(x)。 x: '' xの種類: 'ポイント' 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}のように次のテストで一貫した順序に違反します。 -1はa

+0

@ジョン・ハンナ:あなたが正しいです、私は例で起こったエラーをチェックし、残りは正しいと仮定しました。 –

2

あなたは完全に例外メッセージを読んでいない使用しています。これは、オブジェクトの同じインスタンスに対して0を返さない可能性が最も高いと言えます。

コードが間違っています。Pointの同じインスタンスまたは同じ値が渡された場合は、0を返す必要があります。そうでなければ、彼はソートを終えていつ終わりを迎えるのかを決して知らないでしょう...そして、これは絶対的なマイナスのパフォーマンスのヒットであることはわかっています。

+0

ああ、同じ値のため、Comparerが0である必要があります。それを知らなかった、答えのおかげで! (実際にはかなり論理的ですが、私には起こりませんでした) –

0

としては、アイデンティティが平等を伴う(何かが常に自分自身に等しい)と平等の等価性を伴うと比較子が同じ値の場合は0を返す必要があります、と述べました(かもしれません等しく2つの異なるものを注文しますが、オーダー2つの同等物に等しくする必要があります)。

.Xが0であることを確認すると、両方のXが0に等しい場合、同じ項目の順序が矛盾する可能性があります。比較方法が常に一貫していなければならないという重要なルールです

x <の場合、y> xです。

x < yおよびy < z次にx < z。

あなたのアルゴリズムは、このようにある第1のルール破壊:

言う点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を返すことに注意してください - これは最適化などの重い計算だったが、それは必要がなければ、我々は、明示的なチェックを追加することができます。

また、PointSystem.Drawing.Pointですか?もしそうなら、今度はこのコードはうまくいきますが、もしそれ以外のものがあれば、Pointが構造体であればコードは正常ですが、Pointがクラスであればヌルチェックが含まれているはずです。

関連する問題