Скажем, у меня есть какой-то особый класс WrappedDataTable
, и я хочу связать каждый WrappedDataTable
ровно с одним DataTable
. Кроме того, я хочу, чтобы для любого данного DataTable
.
существовало не более одного
WrappedDataTable
.
Коллега предложил мне кешировать свой WrappedDataTable
и использовать фабричный метод для доступа к нему, например:
public static class DataTableWrapper
{
private Dictionary<DataTable, WrappedDataTable> _wrappedTables;
static DataTableWrapper()
{
_wrappedTables = new Dictionary<DataTable, WrappedDataTable>();
}
public static WrappedDataTable Wrap(this DataTable table)
{
WrappedDataTable wrappedTable;
if (!_wrappedTables.TryGetValue(table, out wrappedTable))
_wrappedTables[table] = wrappedTable = new WrappedDataTable(table);
return wrappedTable;
}
}
Поначалу это показалось мне очень сомнительным, наверное, потому что я познакомился с идеей, что ключи в словаре должны быть неизменными. Но, возможно, это не обязательно так? Быстрый тест показал мне, что DataTable
, кажется, поддерживает непротиворечивый хэш-код в течение многочисленных модификаций его содержимого; * Dictionary<DataTable, TValue>
, следовательно, может последовательно возвращать правильное значение для ContainsKey
.
Что мне интересно, так это то, что базовая версия object.GetHashCode
по умолчанию будет возвращать неизменное значение для каждого отдельного объекта, или если то, что я вижу с DataTable
, является просто иллюзией?
Если первое верно - object.GetHashCode
работает просто отлично - похоже, совет «использовать только неизменяемые типы в качестве ключей» действительно применим только к сценариям, где:
- Вы хотите, чтобы равенство объектов соответствовало равенству значений, а не ссылочному равенству, и / или:
- У вас есть собственный тип с собственной реализацией
GetHashCode
, основанной на членах типа.
Кто-нибудь из мудрецов хочет пролить свет на это для меня?
ОБНОВЛЕНИЕ : Спасибо Джону Скиту за ответ на мой вопрос. В других новостях я немного покопался и подумал, что придумал IEqualityComparer<T>
, который действительно обеспечивает сравнение идентичности в конце концов! Проверьте это (извините, ненавистники VB.NET, у меня только что был проект VB.NET, поэтому я написал его - перевод тривиален):
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices
Public Class IdentityComparer(Of T As Class)
Implements IEqualityComparer(Of T)
Public Overloads Function Equals(ByVal x As T, ByVal y As T) As Boolean _
Implements IEqualityComparer(Of T).Equals
Return Object.ReferenceEquals(x, y)
End Function
Public Overloads Function GetHashCode(ByVal obj As T) As Integer _
Implements IEqualityComparer(Of T).GetHashCode
Return RuntimeHelpers.GetHashCode(obj)
End Function
End Class
Посмотрите на этот пример программы:
Dim comparer As IEqualityComparer(Of String) = New IdentityComparer(Of String)
Dim x As New String("Hello there")
Dim y As New String("Hello there")
Console.WriteLine(comparer.Equals(x, y))
Console.WriteLine(comparer.GetHashCode(x))
Console.WriteLine(comparer.GetHashCode(y))
Выход:
False
37121646
45592480