Скажите, что у меня есть некоторый специальный класс, 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;
}
}
Это показалось мне очень сомнительный сначала, я предполагаю, потому что я познакомился с идеей, которая вводит словарь, должны быть неизменные типы. Но возможно это не обязательно имеет место? Быстрый тест показал мне это a DataTable
кажется, поддерживает последовательный хэш-код в течение многочисленных модификаций к его содержанию; a Dictionary<DataTable, TValue>
поэтому, кажется, может возвратить правильное значение для ContainsKey
последовательно.
То, что я задаюсь вопросом, то, если базовая версия object.GetHashCode
по умолчанию возвратит неизменное значение для каждого отдельного объекта, или если, с чем я вижу DataTable
просто иллюзия?
Если первый верен - и object.GetHashCode
работает просто великолепно - это кажется "использованием только неизменные типы, поскольку ключи" совет действительно только относятся к сценариям где:
GetHashCode
реализация, которая основана на участниках типа.Какие-либо мудрецы там хотят пролить некоторый свет на это для меня?
ОБНОВЛЕНИЕ: Благодаря Jon Skeet для ответа на мой вопрос. В других новостях я сделал некоторое рытье и думаю, что придумал 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
Необязательно возвращать уникальное значение. Он просто должен вернуть неизменный - и это то, что делает object.GetHashCode
.
Пока DataTable
не переопределяет Equals
или GetHashCode
, у вас в основном идентичность объекта как равенство, что означает, что это не имеет значения. если объект видоизменен.
Лично я хотел бы увидеть реализацию IEqualityComparer
, которая обеспечивает равенство идентичности для любого типа, но мы не можем реализовать это сами - нет способа выяснение того, что GetHashCode
вернул бы , если бы он не был переопределен. (Java имеет эту возможность в своих стандартных библиотеках, а .NET - нет. Grr.)
РЕДАКТИРОВАТЬ: Woot - с объектом .ReferenceEquals
и RuntimeHelpers.GetHashCode ()
, мы можем легко реализовать IdentityEqualityComparer
. Ура!
Думаю, вы все прекрасно понимаете. Чтобы объект был сохранен в словаре, любые характеристики, которые могут повлиять на его хеш-значение или тесты на равенство с другими объектами, должны быть неизменными. Характеристики, которые не влияют на эти вещи, не обязательно должны быть неизменными.