2011-03-28 3 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 이외의 다른 것을 반환 할 수 없습니까?

도움 주셔서 감사합니다.

아, BTW 난 .NET 3.5

+0

0을 반환하지 않습니다. 어디에서 볼 수 있습니까? else 블럭 _did_에서의 계산이 0과 같다고하더라도, 그것은 알려지지 않았다. –

답변

8

실제로 오류 메시지가 표시됩니다. IComparer (또는 IComparable 메서드가 의존하는)는 Array.Sort가 x를 호출 할 때 0을 반환하지 않았습니다. CompareTo (x). x : ''x의 형식 : '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

Point a가 {0, 1}이고 b가 {0, 2} 인 것처럼 다음 테스트에서 일관된 순서를 위반합니다. (a, b) -1을 반환하면 a

+0

@ 존 한나 : 당신 말이 맞아요, 방금 예를 들어 발생하는 오류를 확인하고 나머지는 올바른 것으로 가정합니다. –

2

당신은 완전히 예외 메시지를 읽지 않은 사용하고 있습니다. 객체의 동일한 인스턴스에 대해 0을 반환하지 않을 가능성이 가장 높습니다.

코드가 잘못되었습니다. 동일한 인스턴스 인 Point 또는 동일한 값이 전달되면 0을 반환해야합니다. 그렇지 않으면 그는 그가 정렬을 끝내고 무한 루프로 끝날 때를 결코 알지 못할 것입니다 ... 그리고 우리 모두는 이것이 절대적인 부정적인 성과라는 것을 알고 있습니다.

+0

아, 좋아요, Comparer은 같은 값으로 0이되어야합니다. 그걸 알지 못 했어, 대답 해줘서 고마워! (사실은 꽤 논리적이지만 절대로 나옵니다.) –

0

, 비교 자이 같은 값 0을 반환해야 신분 평등을 수반 (뭔가 자신에게 항상 동일)와 평등이 등가을 수반으로 (의 경우는가 2 개의 다른 물건을 동등하게 주문하고 있습니다 만, 의 순서 2 개의 동등한 것이어야합니다.

.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이 클래스 인 경우 null 검사를 포함해야합니다.

관련 문제