2013-04-24 6 views
0

У меня есть POCOs из базы данных SQL Server с идентификационным полем идентификатора. Я хотел бы реализовать IEquatable таким образом я могу проверить, если они ту же запись, используйте .Contains() на List<T> и т.д.IEquatable в поле идентификации POCO

Предполагая, что я никогда не нужно сравнивать несохраненные экземпляров, это достаточно просто осуществить с помощью:

public bool Equals(MyClass other) 
    { 
     return this.ID == other.ID; 
    } 

    public override int GetHashCode() 
    { 
     return this.ID; 
    } 

Я собираюсь сделать это, но просто хотел проверить, что все в порядке, поскольку я не уверен на 100%, что с этим связано GetHashCode, или если есть какие-либо другие соображения (например, «несохраненный экземпляр», один, который я могу отбросить), о котором я не знаю.

+0

Чтобы узнать, что такое 'GetHashCode', см. [Этот ответ] (http://stackoverflow.com/a/16147925/572644). –

ответ

4

Вы должны переопределить GetHashCode() всякий раз, когда вы переопределить Equals() (который вы также должны делать, когда вы реализуете IEquatable<T>), так что классы, которые полагаются на него, такие как Dictionary<TKey, TValue>, может работать правильно. Это одна из тех внутренних деталей, которые раздражающе просачиваются. More information.

Что касается сравнения ваших идентификаторов достаточно для определения равенства, если вы абсолютно уверены, что два объекта с одинаковым идентификатором должны считаться эквивалентными при любых обстоятельствах, а затем идите на него. Это вопрос, на который могут ответить только требования вашего приложения. Я сделал это несколько раз сам, почти всегда с объектами только для чтения.

Я бы реализовать это следующим образом:

// IEquatable<MyClass> implementation 
public bool Equals(MyClass other) 
{ 
    if (other == null) 
    { 
    return false; 
    } 

    return this.ID == other.ID; 
} 

// Override of default Object.Equals() 
public override bool Equals(object other) 
{ 
    return this.Equals(other as MyClass); 
} 

public override int GetHashCode() 
{ 
    // Call ID.GetHashCode() because ID may not always be int, 
    // and the ID type might have a more useful implementation 
    // of GetHashCode() to offer. 
    return this.ID.GetHashCode(); 
} 

Вы, вероятно, следует также переопределить == и != операторы в этом случае. Вы всегда можете использовать Object.ReferenceEquals(), если хотите различать две разные ссылки с одним и тем же идентификатором.

+0

Документ Microsoft для [Object.GetHashCode] (https://docs.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=netframework-4.7.1#System_Object_GetHashCode) предлагает стратегии для реализации 'GetHashCode '. В частности, для хэширования значения, которое *** является *** числовым, раздел «Примеры» начинается с: * «Один из простейших способов вычисления хеш-кода для числового значения, которое имеет тот же или меньший диапазон, чем [Int32] (https://docs.microsoft.com/en-us/dotnet/api/system.int32?view=netframework-4.7.1) тип должен просто вернуть это значение. "* – DavidRR

1

Если вашими заказами ваши объекты равны друг другу, когда их идентификаторы равны, чем вы делаете все отлично!

Хеш-код объекта указывает, что каждый объект с другим состоянием должен возвращать другой хэш-код. Этот хэш-код не уникален, но мы можем попытаться сделать их как можно более разными. Просто проверьте hashcode строк "Hello".GetHashCode() и "Goodbye".GetHashCode().

HashCode используется в некоторых коллекциях, например System.Collections.Generic.Dictionary<K,V> и System.Collections.Generic.HashSet<T>. Используя этот хэш-код, эти словари могут искать и находить элемент очень быстро (почти O (1) -операция), используя этот «уникальный» хэш-код. Вычислите этот хэш-код, используя хэш-коды поля (ов) вашего объекта.

Если вы реализуете IEquatable<T>.Equals, также переопределяйте Equals(object).