2012-01-26 7 views
1

제목에서 언급 한 것이 좋은 습관인지 궁금합니다. 필자가 생각하기에 GetHashCode가 두 속성을 기반으로 값을 반환하도록 재정의하는 경우 일치하는 경우 두 개체를 동일하게 처리해야합니다. 논리가 잘 작동하고 코드가 작동하지만 다른 문제가 발생할 수 있는지 여부는 알 수 없습니다. == 연산자 오버라이드에서 GetHashCode 사용

은 GetHashCode 사용 :

public static bool operator ==(CartesianCoordinates a, CartesianCoordinates b) 
{ 
    return a.GetHashCode() == b.GetHashCode(); // Using GetHashCode here 
} 

public static bool operator !=(CartesianCoordinates a, CartesianCoordinates b) 
{ 
    return !(a == b); 
} 

public override bool Equals(object obj) 
{ 
    return this == (CartesianCoordinates)obj; // This just uses the == override 
} 

public override int GetHashCode() 
{ 
    return (this.X + this.Y.ToLower()).GetHashCode(); // GetHashCode hashes the two properties we care about 
} 

를 내가 전에 한 방법이다 :

public static bool operator ==(CartesianCoordinates a, CartesianCoordinates b) 
{ 
    return a.X == b.X && string.Equals(a.Y, b.Y, StringComparison.CurrentCultureIgnoreCase); // The difference is here 
} 

public static bool operator !=(CartesianCoordinates a, CartesianCoordinates b) 
{ 
    return !(a == b); 
} 

public override bool Equals(object obj) 
{ 
    return this == (CartesianCoordinates)obj; 
} 

public override int GetHashCode() 
{ 
    return (this.X + this.Y.ToLower()).GetHashCode(); 
} 

중요 참고 : CartesianCoordinates에서

객체는, X는 int이며 Y는 문자열입니다.

public int X { get; set; } 
public string Y { get; set; } 

Lmk, 미리 감사드립니다!

+4

왜 당신이 생각하는'새로운 점 (1, 2) == 새로운 점 (2, 1)'? – SLaks

+0

(1, 0)을 (0, 1)과 비교하여 잘못 표시하십시오. –

+0

죄송합니다, 나는 X가 숫자이고 Y가 편지라고 언급 했어야합니다. 질문 업데이트 중입니다. – Carlo

답변

8

이 작업을 수행하는 것은 나쁜 습관 일뿐만 아니라 단지 입니다! 과 같은 두 객체는 ​​이 동일한 해시 코드를 가져야하지만 그 반대는 사실이 아닙니다. 두 개의 서로 다른 객체 은 동일한 해시 코드를 사용합니다. 따라서 해시 코드를 사용하여 객체가 같은지 여부를 결정하는 경우 실제로 차이가 있지만 동일한 해시 코드를 사용하는 경우 동일하다고 생각할 수도 있습니다. 해시는 ...

하여 GetHashCode 구현을 기반 하지 고유 식별자

+0

(2^32 다른 해시 및 다른 개체의 무제한이 있기 때문에, 어떤 의미) – Carlo

+0

@Carlo, OK,하지만 "1A"와 "A1" 동일한 해시 코드를 가질 수 있습니다. 이 다른 문자열의 무한한 수이며, "전용"2^32 가지 해시 코드 ... 내가 그으로 연구 할 필요가 –

+0

, 나는 항상 같은 항상 다른 생산 것 "1A"와 "A1"으로, 2 개의 다른 문자열을 생각 해시 코드. 그러나 어쨌든 좋은 사례가 아니므로 분명합니다. 감사! – Carlo

4

매우 잘못되었습니다.
GetHashCode()은 고유하지 않습니다.

GetHashCode()은 교환 가능하기 때문에 더 구체적인 예가 있습니다.

+0

좀 더 자세히 설명해 주시겠습니까? 난 그냥 질문을 업데이트 – Carlo

+2

'GetHashCode()는'다른 개체에 대해 서로 다른 해시를 반환하지 않을 수 있습니다. X는 int이고, Y는 문자열입니다 (항상 문자입니다). 그래서 x + y = 1A와 y + x = A1 – SLaks

3

GetHashCode()CartesianCoordinates 대해 동일한 값을 반환 할 수있다 (이후 x + y == y + x) 동등한 것으로 간주한다 좌표 (x, y)(y, x) 개체 같지 않음, 예. c1c2과 같은 두 개체의 경우 c1.x == c2.yc1.y == c2.x입니다.

더 복잡한 개체의 경우 hashCode를 미리 계산하면 단락 회로로 사용할 수 있지만 결국 모든 필드를 비교해야합니다. 비교는 간단합니다

0

GetHashCode는 {3,1} 및 {1,3}에 대해 동일한 값을 반환합니다. 나는 이것이 의도되지 않았다고 의심한다.

GetHashCode 메서드가 더 나은 해시 코드를 반환하면 GetHashCode를 등호 비교로 사용하지 않는 것이 좋습니다. GetHashCode 규약에 따르면 동일한 추적 속성을 가진 두 객체가 동일한 해시 코드를 생성해야하며 동일한 해시 코드를 가진 두 객체는 ​​동일하지 않습니다.

편집 추가 :

가에 대한 자세한 내용은이 질문을 참조하십시오 더 나은 구현 특히 조쉬 블로흐/존 소총 응답, 어떻게 생겼는지.

+0

질문이 업데이트되었습니다. X는 int이고 Y는 문자열이므로 3 + 1 또는 1 + 3이 아닌 3A 또는 A3가 해시되어야하며 항상 4가됩니다. – Carlo

0

아니요, 서로 다른 객체가 동일한 해시 코드를 가질 수 있기 때문에 해시 코드를 사용하여 평등을 정의하는 것은 바람직하지 않습니다 (그리고 확실히 발생할 수있는 String.GetHashCode의 경우). 특정 경우

은 또한 GetHashCode이 경우를 제외하고 동일한 문자열에 대해 서로 다른 해시 코드를 반환합니다 때문에 Equals가에 true를 돌려줍니다 동안를 GetHashCode 방법도, 당신의 Equals 방법과 일치하지 않음을 주목해야한다 케이스.

0

귀하의 GetHashCode()(2,4)(4,2)에 대해 동일한 결과를 제공합니다. 아마도 당신이 원하는 것이 아닙니다.

GetHashCode()은 또한 평등을위한 좋은 테스트가 아닙니다. 정말 좋은 해시조차도 32 비트 정수입니다. 이것을 사용하여 직교 평면에서 평등을 테스트하면 충돌이 무수히 발생합니다.