Equals 메서드를 재정의 할 때 GetHashCode를 재정의해야하는 이유는 무엇입니까?


1444

다음 클래스를 감안할 때

public class Foo
{
    public int FooId { get; set; }
    public string FooName { get; set; }

    public override bool Equals(object obj)
    {
        Foo fooItem = obj as Foo;

        if (fooItem == null) 
        {
           return false;
        }

        return fooItem.FooId == this.FooId;
    }

    public override int GetHashCode()
    {
        // Which is preferred?

        return base.GetHashCode();

        //return this.FooId.GetHashCode();
    }
}

s 테이블 의 행을 나타 내기 Equals때문에 메서드를 재정의했습니다 . ? 를 재정의하는 데 선호되는 방법은 무엇입니까?FooFooGetHashCode

대체하는 것이 왜 중요 GetHashCode합니까?


36
특히 사전을 사용하는 동안 충돌로 인해 equals와 gethashcode를 모두 구현하는 것이 중요합니다. 두 객체가 동일한 해시 코드를 반환하면 체인으로 사전에 삽입됩니다. 항목 equals 방법에 액세스하는 동안 사용됩니다.
DarthVader

답변:


1319

예, 항목을 사전에 키로 사용하는 경우 또는 HashSet<T>등 이 중요합니다 . 사용자 지정이없는 경우 IEqualityComparer<T>항목을 버킷으로 그룹화 하는 데 사용되기 때문 입니다. 두 항목의 해시 코드가 일치하지 않으면 결코 같은 것으로 간주 되지 않을 수 있습니다 ( 같음 은 단순히 호출되지 않습니다).

GetHashCode () 메소드는 반영해야 Equals로직; 규칙은 다음과 같습니다.

  • 두 가지가 같으면 ( Equals(...) == true) 동일한 값을 반환 해야합니다.GetHashCode()
  • 경우 (가) GetHashCode()와 동일하다, 그 것이다 되지 들이 동일 할 필요; 이것은 충돌이며 Equals실제 평등인지 확인하기 위해 호출됩니다.

이 경우 " return FooId;"가 적합한 GetHashCode()구현 인 것 같습니다 . 여러 속성을 테스트하는 경우 대각선 충돌을 줄이기 위해 아래와 같은 코드를 사용하여 속성을 결합하는 것이 일반적입니다 (예 : new Foo(3,5)와 다른 해시 코드를 가짐 new Foo(5,3)).

unchecked // only needed if you're compiling with arithmetic checks enabled
{ // (the default compiler behaviour is *disabled*, so most folks won't need this)
    int hash = 13;
    hash = (hash * 7) + field1.GetHashCode();
    hash = (hash * 7) + field2.GetHashCode();
    ...
    return hash;
}

오 - 편의를 위해, 당신은 또한 제공 고려해 볼 수 있습니다 ==!=운영자가 오버라이드 (override) 할 때 EqualsGetHashCode.


이 오류가 발생하면 어떻게되는지 보여주는 데모가 여기 있습니다 .


49
당신이 그런 요소들을 곱한 이유를 물어볼 수 있습니까?
Leandro López

22
실제로, 나는 아마도 그들 중 하나를 잃을 수 있습니다. 요점은 충돌 횟수를 최소화하는 것입니다. 따라서 {1,0,0} 객체는 {0,1,0} 및 {0,0,1}과 다른 해시를 갖습니다 (내가 무슨 뜻인지 알면 ),
Marc Gravell

13
나는 숫자를 더 명확하게하기 위해 조정했습니다 (그리고 씨앗을 추가했습니다). 일부 코드는 다른 숫자를 사용합니다. 예를 들어 C # 컴파일러 (익명 형식의 경우)는 0x51ed270b의 시드와 -1521134295의 계수를 사용합니다.
Marc Gravell

76
@Leandro López : 일반적으로 요인은 충돌 횟수를 작게 만들기 때문에 소수로 선택됩니다.
Andrei Rînea

29
"아 - 편의를 위해, 당신은 또한 제공 ==하고 고려할 수 = 연산자를 같음과 GethashCode를 오버라이드 (override) 할 때!."불변하지 않은 개체에 대한 == 연산자를 구현하는 마이크로 소프트의 스타일을 장려을 - msdn.microsoft.com/en-us/library/을 ms173147.aspx- "변경할 수없는 유형의 연산자 ==를 재정의하는 것은 좋지 않습니다."
antiduh

137

GetHashCode()Marc가 이미 언급 한 규칙 외에도 해시 코드가 객체의 수명 동안 변경되지 않아야하기 때문에 실제로 올바르게 구현하기가 매우 어렵습니다 . 따라서 해시 코드를 계산하는 데 사용되는 필드는 변경 불가능해야합니다.

NHibernate와 함께 일할 때 마침내이 문제에 대한 해결책을 찾았습니다. 내 접근 방식은 객체의 ID에서 해시 코드를 계산하는 것입니다. ID는 생성자를 통해서만 설정할 수 있으므로 ID를 변경하려는 경우 매우 드물지만 새 ID를 가진 새 객체와 새 해시 코드를 만들어야합니다. 이 방법은 임의로 ID를 생성하는 매개 변수가없는 생성자를 제공 할 수 있으므로 GUID에 가장 적합합니다.


20
@vanja. 사전과 객체를 추가 한 다음 객체의 ID를 변경하면 나중에 가져올 때 다른 해시를 사용하여 검색 할 수 있으므로 사전에서 가져 오지 않습니다.
ANeves

74
GetHashCode () 함수에 대한 Microsoft의 설명서는 개체 해시가 일생 동안 일관성을 유지해야한다고 진술하거나 암시하지 않습니다. 실제로는 다음과 같은 경우가 허용 되지 않는 한 가지 경우를 구체적으로 설명합니다 . "
PeterAllenWebb

37
"해시 코드는 객체의 수명 동안 변경되어서는 안됩니다"– 이것은 사실이 아닙니다.
묵시록

7
"해시 코드 (또는 등가의 증발도)는 개체가 컬렉션의 키로 사용되는 기간 동안 변경되어야합니다." 사전에서 개체를 제거 할 때까지 GetHashCode 및 Equals는 지정된 입력에 대한 출력을 변경하지 않습니다.
Scott Chamberlain

11
@ScottChamberlain 나는 당신이 당신의 의견에서 잊어 버린 것을 생각합니다. 권리?
Stan Prokop

57

Equals를 재정의하면 기본적으로 자신이 주어진 유형의 두 인스턴스를 비교하는 방법을 더 잘 알고 있다고 주장하므로 최고의 해시 코드를 제공하는 가장 좋은 후보가 될 수 있습니다.

다음은 ReSharper가 GetHashCode () 함수를 작성하는 방법의 예입니다.

public override int GetHashCode()
{
    unchecked
    {
        var result = 0;
        result = (result * 397) ^ m_someVar1;
        result = (result * 397) ^ m_someVar2;
        result = (result * 397) ^ m_someVar3;
        result = (result * 397) ^ m_someVar4;
        return result;
    }
}

보시다시피 클래스의 모든 필드를 기반으로 좋은 해시 코드를 추측하려고 시도하지만 객체의 도메인 또는 값 범위를 알고 있기 때문에 여전히 더 나은 것을 제공 할 수 있습니다.


7
이것이 항상 0을 반환하지 않습니까? 아마도 결과를 1로 초기화해야합니다! 세미콜론이 몇 개 더 필요합니다.
Sam Mackrill

16
XOR 연산자 (^)의 기능을 알고 있습니까?
Stephen Drew

1
내가 말했듯이, 이것은 R #이 당신을 위해 쓰는 것입니다 (적어도 2008 년에 다시 한 것입니다). 분명히,이 스 니펫은 프로그래머가 어떤 식 으로든 조정하기위한 것입니다. 누락 된 세미 콜론은 ... 예, Visual Studio의 지역 선택에서 코드를 복사하여 붙여 넣을 때 생략 한 것처럼 보입니다. 또한 사람들이 둘 다 알아낼 것이라고 생각했습니다.
Trap

3
@ Samamackrill 누락 된 세미콜론에 추가했습니다.
Matthew Murdoch

5
@SamMackrill 아니, 그것은 항상 0을 반환하지 않습니다 0 ^ a = a, 그래서 0 ^ m_someVar1 = m_someVar1. 초기 값을 result로 설정했을 수도 있습니다 m_someVar1.
Millie Smith

41

null재정의 할 때 obj 매개 변수를 확인하는 것을 잊지 마십시오 Equals(). 또한 유형을 비교하십시오.

public override bool Equals(object obj)
{
    Foo fooItem = obj as Foo;

    if (fooItem == null)
    {
       return false;
    }

    return fooItem.FooId == this.FooId;
}

그 이유는 다음 Equals과 비교할 때 false를 반환해야합니다 null. http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx 참조


6
서브 클래스가 슈퍼 클래스 Equals 메소드를 자체 비교의 일부로 참조하는 상황 (예 : base.Equals (obj))에서 type 검사는 실패합니다. 대신에 사용해야합니다
sweetfa

@sweetfa : 서브 클래스의 Equals 메소드 구현 방법에 따라 다릅니다. 또한 base.Equals ((BaseType) obj)) 호출하면 정상적으로 작동합니다.
huha

2
아닙니다 : msdn.microsoft.com/en-us/library/system.object.gettype.aspx . 또한 메소드의 호출 방식에 따라 메소드 구현이 실패하거나 성공하지 않아야합니다. 객체의 런타임 타입은 다음 몇 가지의 base class의 서브 클래스 같음 인 경우 경우 ()가없는 baseclass의 true를 돌려 obj참으로 동일 this불렀다 방법 같음 ()가없는 baseclass의 상관없이.
목성

2
fooItem맨 위로 이동 한 다음 null을 확인하면 null이거나 잘못된 유형 인 경우 성능이 향상됩니다.
IllidanS4는 Monica를

1
@ 40Alpha 그렇다면, obj as Foo유효하지 않을 것입니다.
IllidanS4는 Monica를

35

어때요?

public override int GetHashCode()
{
    return string.Format("{0}_{1}_{2}", prop1, prop2, prop3).GetHashCode();
}

성능이 문제가 아니라고 가정 :)


1
음 -하지만 당신은 지능 기반 방법에 대한 문자열을 반환하고, _0
짐 tollan

32
아니요, 그는 int를 반환하는 String 객체에서 GetHashCode ()를 호출합니다.
Richard Clayton

3
나는 이것이 가치 유형과 관련된 권투뿐만 아니라의 성과를 위해서도 내가 원하는만큼 빠를 것으로 기대하지 않습니다 string.Format. 내가 본 또 다른 괴짜는 new { prop1, prop2, prop3 }.GetHashCode()입니다. 이 둘 사이에서 어느 쪽이 느려질 수는 있는지에 대해서는 언급하지 않았습니다. 도구를 남용하지 마십시오.
nawfal

16
{ prop1="_X", prop2="Y", prop3="Z" }및에 대해 true를 반환합니다 { prop1="", prop2="X_Y", prop3="Z_" }. 당신은 아마 그것을 원하지 않을 것입니다.
voetsjoeba

2
그러나 밑줄 기호를 항상 흔하지 않은 것으로 바꿀 수 있습니다 (예 : •, ▲, ►, ◄, ☺, ☻). 사용자가이 기호를 사용하지 않기를 바랍니다 ... :)
Ludmil Tinkov

13

극복해야 할 두 가지 문제가 있습니다.

  1. GetHashCode()객체의 필드를 변경할 수 있는 경우 적절한 정보를 제공 할 수 없습니다 . 또한 종종에 의존하는 컬렉션에서 개체를 사용하지 GetHashCode()않습니다. 따라서 구현 비용 GetHashCode()은 종종 가치가 없거나 불가능합니다.

  2. 누군가 호출하는 컬렉션에 객체를 넣고 올바른 방식으로 동작 하지 않고 GetHashCode()재정의 한 경우 해당 사람이 문제를 추적하는 데 며칠이 걸릴 수 있습니다.Equals()GetHashCode()

따라서 기본적으로 그렇습니다.

public class Foo
{
    public int FooId { get; set; }
    public string FooName { get; set; }

    public override bool Equals(object obj)
    {
        Foo fooItem = obj as Foo;

        if (fooItem == null)
        {
           return false;
        }

        return fooItem.FooId == this.FooId;
    }

    public override int GetHashCode()
    {
        // Some comment to explain if there is a real problem with providing GetHashCode() 
        // or if I just don't see a need for it for the given class
        throw new Exception("Sorry I don't know what GetHashCode should do for this class");
    }
}

5
GetHashCode에서 예외를 발생시키는 것은 개체 계약을 위반하는 것입니다. GetHashCode동일한 두 객체가 동일한 해시 코드를 반환하도록 함수를 정의하는 데 어려움이 없습니다 . return 24601;그리고의 return 8675309;유효한 구현입니다 GetHashCode. Dictionary항목 수가 적을 때만 성능이 좋으며, 항목 수가 많으면 매우 나빠지지만 어떤 경우에도 올바르게 작동합니다.
supercat

2
@supercat, 해시 코드가 절대로 변경되지 않아야하므로 개체의 식별 필드가 변경 될 수있는 경우 합리적인 방식으로 GetHashCode를 구현할 수 없습니다. 당신이 말한 것을 수행하면 누군가가 성능 문제를 추적하는 데 많은 시간을 소비하고 사전 사용을 제거하기 위해 큰 시스템을 재 설계하는 데 몇 주가 걸릴 수 있습니다.
Ian Ringrose

2
Equals ()가 필요하다고 정의한 모든 클래스에 대해 이와 같은 작업을 수행했으며 컬렉션에서 해당 객체를 키로 사용하지 않을 것이라고 완전히 확신했습니다. 그런 다음 어느 날 DevExpress XtraGrid 컨트롤에 대한 입력으로 이와 같은 객체를 사용하는 프로그램이 중단되었습니다. 그것은 XtraGrid가 내 뒤에서 HashTable 또는 내 객체를 기반으로 한 무언가를 만드는 것으로 나타났습니다. 나는 이것에 대해 DevExpress 지원 사람들과 사소한 논쟁을 벌였습니다. 나는 그들이 모호한 방법의 알려지지 않은 고객 구현에 그들의 구성 요소의 기능과 신뢰성을 기반으로하는 것이 현명하지 않다고 말했다.
RenniePet

DevExpress 사람들은 기본적으로 GetHashCode () 메서드에서 예외를 발생시키는 바보가되어야한다고 생각했습니다. 나는 여전히 그들이하고있는 일을 수행하는 다른 방법을 찾아야한다고 생각합니다. 나는 Marc Gravell이 GetHashCode ()에 의존하지 않고 임의의 객체 사전을 만드는 방법을 설명하는 다른 스레드에서 기억합니다. 그러나.
RenniePet

4
@RenniePet은 예외가 발생하여 호감되는 것이 좋으며, 잘못된 구현으로 인해 버그를 찾기가 매우 어렵습니다.
Ian Ringrose 2018 년

12

프레임 워크는 동일한 두 개의 객체가 동일한 해시 코드를 가져야하기 때문입니다. equals 메소드를 대체하여 두 오브젝트의 특수 비교를 수행하고 메소드에서 두 오브젝트를 동일한 것으로 간주하는 경우 두 오브젝트의 해시 코드도 동일해야합니다. (사전 및 해시 테이블은이 원칙에 의존합니다).


11

위의 답변을 추가하면됩니다.

같음을 재정의하지 않으면 기본 동작은 객체의 참조가 비교되는 것입니다. 기본 코드는 일반적으로 참조의 메모리 주소를 기반으로합니다. Equals를 재정의했기 때문에 올바른 동작은 참조가 아닌 Equals에 구현 한 내용을 비교하는 것이므로 해시 코드에 대해서도 동일하게 수행해야합니다.

클래스의 클라이언트는 해시 코드가 equals 메소드와 유사한 논리를 가질 것으로 예상합니다. 예를 들어 IEqualityComparer를 사용하는 linq 메소드는 먼저 해시 코드를 비교하고 동일 할 경우에만 더 비싼 Equals () 메소드를 비교합니다 실행하려면 해시 코드를 구현하지 않으면 동일한 객체에 다른 해시 코드가있을 것입니다 (메모리 주소가 다르기 때문에) 동일하지 않은 것으로 잘못 결정됩니다 (Equals ()는 적중되지 않습니다).

또한 사전에서 객체를 사용하면 객체를 찾을 수없는 문제를 제외하고 (하나의 해시 코드로 삽입되었으므로 찾을 때 기본 해시 코드가 다를 수 있음) Equals () Marc Gravell이 그의 답변에서 설명하는 것처럼 호출되지 않을 것입니다. 동일한 키를 허용하지 않아야하는 사전 또는 해시 세트 개념의 위반을 소개합니다. 데이터 구조에서 두 키를 서로 다른 키로 사용하여 고유 한 키를 가지길 원하지는 않지만 해시 코드가 다르기 때문에 "같은"키가 다른 키로 삽입됩니다.


8

해시 코드는 Dictionary, Hashtable, HashSet 등과 같은 해시 기반 컬렉션에 사용됩니다.이 코드의 목적은 특정 객체를 특정 그룹 (버킷)에 넣어서 매우 빠르게 사전 정렬하는 것입니다. 이 사전 정렬은 코드가 포함 된 모든 객체가 아닌 하나의 버킷에서 객체를 검색해야하기 때문에 해시 수집에서 객체를 다시 검색해야 할 때이 객체를 찾는 데 크게 도움이됩니다. 해시 코드 (더 나은 고유성)를 더 잘 분배할수록 검색이 더 빨라집니다. 각 객체에 고유 한 해시 코드가있는 이상적인 상황에서 O (1) 연산을 찾는 것입니다. 대부분의 경우 O (1)에 접근합니다.


7

반드시 중요한 것은 아닙니다. 컬렉션의 크기와 성능 요구 사항 및 클래스가 성능 요구 사항을 모르는 라이브러리에서 사용되는지 여부에 따라 다릅니다. 필자는 컬렉션 크기가 그리 크지 않으며 완벽한 해시 코드를 생성하여 얻은 몇 마이크로 초 이상의 성능보다 시간이 더 중요하다는 것을 자주 알고 있습니다. 그래서 (컴파일러에 의한 성가신 경고를 없애기 위해) 나는 단순히 다음을 사용합니다.

   public override int GetHashCode()
   {
      return base.GetHashCode();
   }

(물론 #pragma를 사용하여 경고를 끌 수도 있지만이 방법을 선호합니다.)

물론 다른 사람들이 언급 한 모든 문제가 적용되는 것보다 성능 필요한 위치에있을 때 물론입니다. 가장 중요 -그렇지 않으면 해시 세트 또는 사전에서 항목을 검색 할 때 잘못된 결과를 얻을 수 있습니다. 해시 코드는 오브젝트의 수명 시간에 따라 달라져서는 안됩니다 (보다 정확하게는 해시 코드가 필요할 때마다, 예를 들어 예를 들어 Value가 public이므로 인스턴스의 수명 기간 동안 클래스 외부에서 클래스를 변경할 수 있으므로 해시 코드의 기초로 사용해서는 안됩니다.


   class A
   {
      public int Value;

      public override int GetHashCode()
      {
         return Value.GetHashCode(); //WRONG! Value is not constant during the instance's life time
      }
   }    

반면에, Value를 변경할 수 없다면 다음을 사용해도됩니다 :


   class A
   {
      public readonly int Value;

      public override int GetHashCode()
      {
         return Value.GetHashCode(); //OK  Value is read-only and can't be changed during the instance's life time
      }
   }

3
공감. 이것은 명백한 잘못입니다. 심지어 Microsoft에서도 MSDN ( msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx )에서 개체 상태가 호출의 반환 값에 영향을 줄 수있는 방식으로 변경되면 GetHashCode의 값이 반드시 변경되어야한다고 명시하고 있습니다. Equals ()에, 그리고 심지어 예제에서도 공개적으로 변경 가능한 값에 전적으로 의존하는 GetHashCode 구현을 보여줍니다.
Sebastian PR Gingter

Sebastian, 나는 동의하지 않습니다 : 해시 코드를 사용하는 컬렉션에 객체를 추가하면 해시 코드에 따라 저장소에 저장됩니다. 이제 해시 코드를 변경하면 컬렉션에서 잘못된 저장소가 검색되므로 개체를 다시 찾을 수 없습니다. 사실 이것은 우리 코드에서 일어난 일이므로 지적해야 할 이유입니다.
ILoveFortran 12

2
Sebastian, 또한 GetHashCode ()가 변경되어야 하는 링크 ( msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx ) 에서 문을 볼 수 없습니다 . 반대로 Equals가 동일한 인수에 대해 동일한 값을 반환하는 한 변경되지 않아야합니다. "개체의 GetHashCode 메서드는 반환 값을 결정하는 개체 상태를 수정하지 않는 한 동일한 해시 코드를 일관되게 반환해야합니다. "이 문장은 반대의 의미를 나타내지 않으며, Equals의 리턴 값이 변경되면 변경되어야한다는 것을 의미합니다.
ILoveFortran

2
@Joao, 계약의 고객 / 소비자 측을 생산자 / 구현 자와 혼동하고 있습니다. GetHashCode ()를 재정의하는 구현 자의 책임에 대해 이야기하고 있습니다. 가치를 사용하는 소비자에 대해 이야기하고 있습니다.
ILoveFortran

1
완전한 오해 ... :) 진실은 상태가 객체의 아이덴티티와 무관하지 않는 한 객체의 상태가 변경되면 해시 코드가 변경되어야한다는 것입니다. 또한 MUTABLE 객체를 컬렉션의 키로 사용해서는 안됩니다. 이 목적으로 읽기 전용 개체를 사용하십시오. GetHashCode, Equals ... 그리고 지금 기억하지 못하는 이름의 다른 메소드는 절대 던져서는 안됩니다.
darlove

0

Equals ()에 정의 된대로 두 객체가 동일한 경우 항상 동일한 해시 코드를 반환해야합니다. 다른 의견 중 일부는 이론적으로 객체가 HashSet 또는 Dictionary와 같은 해시 기반 컨테이너에서 절대 사용되지 않는 경우 필수적이지 않습니다. 그래도 항상이 규칙을 따르는 것이 좋습니다. 그 이유는 실제로 성능을 향상 시키거나 코드 의미를 더 나은 방식으로 전달하려는 의도로 누군가가 한 유형에서 다른 유형으로 콜렉션을 변경하기가 너무 쉽기 때문입니다.

예를 들어, 일부 객체를 List에 유지한다고 가정합니다. 언젠가 누군가는 예를 들어 더 나은 검색 특성 때문에 HashSet이 훨씬 더 나은 대안이라는 것을 실제로 알고 있습니다. 우리가 곤경에 처할 수있는 때입니다. List는 내부적으로 기본 평등 비교자를 사용합니다. 이는 HashSet이 GetHashCode ()를 사용하는 경우 Equals를 의미합니다. 둘이 다르게 동작하면 프로그램도 마찬가지입니다. 이러한 문제는 해결하기 가장 쉬운 방법이 아닙니다.

이 동작을 블로그 게시물의 다른 GetHashCode () 함정과 함께 요약하여 추가 예제와 설명을 찾을 수 있습니다.


0

현재 .NET 4.7재정의 바람직한 방법은 GetHashCode()다음과 같다. 이전 .NET 버전을 대상으로하는 경우 System.ValueTuple nuget 패키지를 포함하십시오 .

// C# 7.0+
public override int GetHashCode() => (FooId, FooName).GetHashCode();

성능면에서이 메소드는 대부분의 복합 해시 코드 구현 보다 성능이 우수 합니다. ValueTuple는 A는 struct그래서 어떤 쓰레기가되지 않으며, 기본 알고리즘은 빨리이수록입니다.


-1

원래 GetHashCode ()가 객체의 메모리 주소를 반환한다는 것을 이해하고 있으므로 두 개의 다른 객체를 비교하려면이를 재정의해야합니다.

편집 : 잘못되었습니다. 원래 GetHashCode () 메소드는 2 값의 동등성을 보장 할 수 없습니다. 동일한 객체는 동일한 해시 코드를 반환하지만


-6

아래의 리플렉션 사용은 공용 속성을 고려할 때 더 나은 옵션 인 것처럼 보입니다. 이와 함께 속성 추가 / 제거에 대해 걱정할 필요가 없습니다 (일반적인 시나리오는 아니지만). 이 또한 성능이 더 우수하다는 것을 알았습니다. (대각선 스톱워치를 사용한 시간 비교).

    public int getHashCode()
    {
        PropertyInfo[] theProperties = this.GetType().GetProperties();
        int hash = 31;
        foreach (PropertyInfo info in theProperties)
        {
            if (info != null)
            {
                var value = info.GetValue(this,null);
                if(value != null)
                unchecked
                {
                    hash = 29 * hash ^ value.GetHashCode();
                }
            }
        }
        return hash;  
    }

12
GetHashCode ()의 구현은 매우 가벼울 것으로 예상됩니다. 나는 수천 개의 전화에서 StopWatch로 리플렉션을 사용하는 것이 눈에 띄지 않지만 확실하게 수백만입니다 (사전 목록에서 사전을 채우는 것을 생각하십시오).
bohdan_trotsenko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.