2013-09-04 8 views
1

Я использую RTBTextPointer в качестве пользовательского ключа в словаре ...словаря, используя это пользовательский ключ, но ключ всегда неравное

Init.SpintaxEditorPropertyMain.SpintaxListDict = new Dictionary<RTBTextPointer, SpintaxEditorProperties.SpintaxMappedValue>(new RTBTextPointerComparer()); 

Я Worte этого RTBTextPointer и классов RTBTextPointerComparer в библиотеке классов и использовать это в различных проектах Wpf ,

if (Init.SpintaxEditorPropertyMain.SpintaxListDict.ContainsKey(_index) == false) 
     { 
      Init.SpintaxEditorPropertyMain.SpintaxListDict.Add(_index,_SpintaxMappedVal); 
     } 

каждый ContainsKey возвращает ложь, даже он содержит, поэтому запись дублирование происходит в словаре .. ничего плохого в моем "GetHashCode()"

public class RTBTextPointer 
    { 
    static int _row; 
    static int _column; 

    public int Row 
    { 
     get 
     { 
      return _row; 
     } 
     set 
     { 
      _row = value; 
     } 
    } 
    public int Column 
    { 
     get 
     { 
      return _column; 
     } 
     set 
     { 
      _column = value; 
     } 
    } 

} 

public class RTBTextPointerComparer : IEqualityComparer<RTBTextPointer> 
{ 
    public bool Equals(RTBTextPointer x, RTBTextPointer y) 
    {   
     bool result = int.Equals(x.Column, y.Column) && (int.Equals(x.Row, y.Row)); 

     return result; 
    } 

    public int GetHashCode(RTBTextPointer obj) 
    { 
     var result = 0; 
     int hCode = obj.Column^obj.Row; 
     result = hCode.GetHashCode(); 
     return result; 
    } 
} 

Пожалуйста, помогите мне Спасибо заранее

+0

Что именно вы имеете в виду, всегда ключ не равен, даже равен. .? – jdphenix

+0

everyt time containsskey возвращает false if (Init.SpintaxEditorPropertyMain.SpintaxListDict.ContainsKey (_index) == false) { Init.SpintaxEditorPropertyMain.SpintaxListDict.Add (_index, _SpintaxMappedVal); } – Jay

ответ

1

Я не думаю, что вам нужно создать отдельный компаратор. Достаточно переопределить Equals и GetHashCode.

Кроме того, если у вас есть очень простые свойства, как это, вы могли бы перейти на auto properties

public class RTBTextPointer 
{ 
    public int Row 
    { 
     get; 
     set; 
    } 
    public int Column 
    { 
     get; 
     set; 
    } 
    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) 
     { 
      return false; 
     } 
     if (ReferenceEquals(this, obj)) 
     { 
      return true; 
     } 
     var other = obj as RTBTextPointer; 
     if (other == null) 
     { 
      return false; 
     } 
     return other.Row == Row && other.Column == Column; 
    } 
    public override int GetHashCode() 
    { 
     unchecked 
     { 
      // 397 or some other prime number 
      return (Row * 397)^Column; 
     } 
    } 
} 

См unchecked для получения дополнительной информации об этом.

Если у вас есть более чем два свойства, и если эти свойства могут быть нулевыми, GetHashCode может выглядеть следующим образом:

unchecked 
{ 
    var result = 0; 
    result = (result * 397)^(Prop1 != null ? Prop1.GetHashCode() : 0); 
    result = (result * 397)^(Prop2 != null ? Prop2.GetHashCode() : 0); 
    result = (result * 397)^(Prop3 != null ? Prop3.GetHashCode() : 0); 
    result = (result * 397)^(Prop4 != null ? Prop4.GetHashCode() : 0); 
    // ... 
    return result; 
} 
+0

+1 для заметки на unchecked – jdphenix

+0

Спасибо большое Корак .. это хорошо работает ... – Jay

+0

ok Я понял :) спасибо еще раз – Jay

1

Ваша проблема, вероятно, проистекает из следующих заявлений в RTBTextPointer:

static int _row; 
static int _column; 

Они не делают то, что я думаю, что вы намерены. Они должны быть

private int _row; 
private int _column; 

Как это прямо сейчас, эти переменные ссылаются static членов RTBTextPointer. Это означает, что любой доступ к ним будет иметь доступ или мутировать его членов static. static члены доступны для каждого экземпляра типа. Если вы сделаете их private, они будут применяться в каждом экземпляре, который, я считаю, является вашим намерением.

Как только это будет исправлено, я пересмотрю дизайн вашего класса, по крайней мере, если вы намерены использовать его в качестве ключа в Dictionary. RTBTextPointer должен быть неизменным или по крайней мере поля и свойства, от которых зависит GetHashCode(). Вот почему:

Когда вы добавляете объект в качестве ключа в словарь, его связанное значение помещается в хэш-ведро, которое представляет собой просто некоторую структуру данных, связанную с хеш-кодом. Предположим, что мы имеем произвольный ключ RTBTextPointer с Row = 2 и Column = 2 и значением «Foo». Это GetHashCode будет 0 (2 XOR 2).

Hash Key     Value 
0 RTBTextPointer(2,2) Foo 

Прямо сейчас, призыв к Dictionary.ContainsKey() будет возвращена истина ищет RTBTextPointer(2,2). Теперь рассмотрим, изменился ли этот RTBTextPointer на Row = 4. Это хэш-код теперь будет 6 (4 XOR 2). Теперь вызов Dictionary.ContainsKey() будет ложным, а значение Foo будет недоступным, поскольку ключ имеет хеш-код, который зависит от изменяемого состояния.

В заключение я хотел бы рассмотреть возможность переопределения методов Equals() и GetHashCode()object.

+0

Полностью пропустил 'static'. Хорошо поймал! – Corak

+0

спасибо за вашу ценную информацию :) – Jay

+0

Это очень полезно. Огромное спасибо :) – Jay

 Смежные вопросы

  • Нет связанных вопросов^_^