2014-09-10 3 views
3

이것은 C#입니다. Dictionary.ContainsKey가 거기에있는 키를 알고 있음에도 불구하고 false를 반환하는 문제가 있습니다.Dictionary.GetKey는 키가 존재하더라도 False를 반환합니다. GetHashCode/Equals가 이미 재정의되었습니다.

불행히도 표시 할 코드가 없습니다. 이 코드는 서로 끌어 당기기가 쉽지 않습니다. 그것은 여러 클래스에 퍼져서 이벤트 등을 통해 트리거됩니다. 내가 쓴 단위 테스트는 문제를 재현하지 못했다.

// throws KeyNotFoundException 
myDict[key] 

// throws KeyNotFoundException 
myDict[new MyKey("SomeString .1", "SomeOtherString", SomeEnum.Foo)] 

// Element [5] is the key 
myDict.Keys 
Count = 10 
    [0]: {...} 
    [1]: {...} 
    [2]: {...} 
    [3]: {...} 
    [4]: {...} 
    [5]: {Foo SomeOtherString SomeString .1} 
    [6]: {...} 
    [7]: {...} 
    [8]: {...} 
    [9]: {...} 

// Get key at element [5] 
enumerator.Current 
{Foo SomeOtherString SomeString .1} 
    [My.Namespace.KeyType]: {Foo SomeOtherString SomeString .1} 
    SomeEnum: Foo 
    SomeOtherStringProperty: "SomeOtherString" 

// key used to do lookup 
key 
{Foo SomeOtherString SomeString .1} 
    [My.Namespace.KeyType]: {Foo SomeOtherString SomeString .1} 
    SomeEnum: Foo 
    SomeOtherStringProperty: "SomeOtherString" 

// hash codes of key in dictionary matches hash code of lookup key 
enumerator.Current.GetHashCode() 
193014103 
key.GetHashCode() 
193014103 

일부 추가 참고 :

  • 키로 사용되는 유형이 여기에

    은 디버깅 세션 동안 직접 실행 창의 출력 (추가 의견 및 정보를 보호하기 위해 변경)입니다 GetHashCode 및 같음에 대해 재정의 된 메서드.
  • 사전은 여분의 생성자 인수가없는 이있는 새 Dictionary()로 생성됩니다. 디버깅으로
  • , 나는 키 유형에 GetHashCode를 호출 것을 확인했지만, 같지 않음은 (OBJ)는
  • 응용 프로그램이 실행이 단지 거기에 하나의 DLL 그 키 유형이로드 은 그래서 아마 동일한 DLL의 동일한 버전의 동일한 유형의 경우가 아님

이 문제의 원인을 아는 사람이 있습니까?

도움을 주셔서 감사합니다 - 여기 아이디어가 부족합니다.

답변

4

키로 사용되는 형식에는 GetHashCode 및 Equals에 대해 재정의 된 메서드가 있습니다.

이것이 내가 확인할 것입니다. 해시 코드가 변경 가능한 값을 기반으로하는 경우이 문제가 발생할 수 있습니다.

  • 당신은 변경할 수없는 분야의 해시 코드를 계산 할 수 있습니다 : MSDN에서

    : 경우에만 일반적으로

    , 변경 가능한 참조 유형, 당신은 GetHashCode를 오버라이드 (override) 또는

  • 개체가 해시 코드를 사용하는 컬렉션에 포함되어있는 동안 변경 가능한 개체의 해시 코드가 변경되지 않도록 할 수 있습니다.

그렇지 않으면 변경 가능한 개체가 해시 테이블에서 손실되었다고 생각할 수 있습니다. 변경할 수있는 참조 형식에 대해 GetHashCode를 재정의하도록 선택하는 경우 개체에서 해시 테이블에 개체를 저장하는 동안 개체 유형을 수정하지 않아야합니다.

+0

실제로. 문제의 개체가 사전 (또는 HashTable과 유사한 구조)에 저장되어있는 동안 GetHashCode/Equality 비교에 참여하는 속성을 변경하면 사전이 손상되어 모든 베팅이 해제됩니다.GetHashCode 및 Equality에 참여하는 모든 속성은 실제로 변경할 수 없어야합니다. 이를 위해 문서에 의존하지 마십시오. – spender

+0

감사합니다. 그러나 응용 프로그램이 중단 점에서 개최되고 해시 코드가 동일 할 때 위의 직접 창의 모든 출력이 취해 졌으므로 이것이 문제는 아닌 것 같습니다. 내가 놓친 게 있니? –

+1

@ck : 사전 손상이 중단 점 이전에 발생했음을 나타냅니다. 즉, 사전에 들어간 후 키를 변경하여 사전에 저장 한 것과 다른 코드를 생성하게합니다. 예, 키를 열거 할 수 있지만 다른 해시 코드에 대해 저장되었으므로 찾을 수 없습니다. – spender