Прекрасен это полностью для использования изменяемого объекта в качестве ключа в Словаре?

Скажите, что у меня есть некоторый специальный класс, 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 работает просто великолепно - это кажется "использованием только неизменные типы, поскольку ключи" совет действительно только относятся к сценариям где:

  1. Вы хотите равенство объектов быть о равенстве значения в противоположность ссылочному равенству, и/или:
  2. У Вас есть пользовательский тип с его собственным 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
1
задан Dan Tao 25 June 2010 в 13:47
поделиться

2 ответа

Необязательно возвращать уникальное значение. Он просто должен вернуть неизменный - и это то, что делает object.GetHashCode .

Пока DataTable не переопределяет Equals или GetHashCode , у вас в основном идентичность объекта как равенство, что означает, что это не имеет значения. если объект видоизменен.

Лично я хотел бы увидеть реализацию IEqualityComparer , которая обеспечивает равенство идентичности для любого типа, но мы не можем реализовать это сами - нет способа выяснение того, что GetHashCode вернул бы , если бы он не был переопределен. (Java имеет эту возможность в своих стандартных библиотеках, а .NET - нет. Grr.)

РЕДАКТИРОВАТЬ: Woot - с объектом .ReferenceEquals и RuntimeHelpers.GetHashCode () , мы можем легко реализовать IdentityEqualityComparer . Ура!

2
ответ дан 2 September 2019 в 23:30
поделиться

Думаю, вы все прекрасно понимаете. Чтобы объект был сохранен в словаре, любые характеристики, которые могут повлиять на его хеш-значение или тесты на равенство с другими объектами, должны быть неизменными. Характеристики, которые не влияют на эти вещи, не обязательно должны быть неизменными.

0
ответ дан 2 September 2019 в 23:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: