Скажем, у меня есть специальный класс, WrappedDataTable
, и я хочу связать каждый WrappedDataTable
ровно с одним DataTable
. Кроме того, я хочу, чтобы существовало не более одного WrappedDataTable
для любого заданного DataTable
.Можно ли использовать изменяемый объект в качестве ключа в словаре?
Коллега предложил я мог кэшировать мой 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
, по-видимому, поддерживает согласованный хеш-код в ходе многочисленных модификаций его содержимого; a Dictionary<DataTable, TValue>
похоже, что нужно сделать правильный вывод для ContainsKey
.
Что мне интересно, если базовая версия object.GetHashCode
по умолчанию вернет неизменное значение для каждого отдельного объекта, или если то, что я вижу с DataTable
, просто иллюзия?
Если верно первое - и object.GetHashCode
прекрасно работает - кажется, «используют только неизменные типы в качестве ключей» совет действительно относится только к сценариям, где:
- Вы хотите равенство объектов быть о равенстве значений в противоположность эталонному равенству и/или:
- У вас есть собственный тип с собственной реализацией
GetHashCode
, основанный на членах типа.
Любые мудрецы там могут пролить свет на это для меня?
UPDATE: Благодаря Jon тарелочкам для ответа на мой вопрос. В других новостях, я сделал некоторые копания и думаю, что я придумал 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
@Jon: Как GetHashCodeBase? Я признаю, что я никогда не делал Java (nodatime был моим первым набегом, и я все время смотрел на код, а не на то, чтобы внести свой вклад) –
@Jeff: Какой-то статический метод где-то, в основном. В Java это 'System.identityHashCode' –
@Jon: Ах, это звучит полезно. Было бы также полезно иметь возможность получить исходные реализации «ToString» и «Equals» для других целей. –