Pregunta

decir que tengo alguna clase especial, WrappedDataTable, y quiero asociar cada WrappedDataTable con exactamente un DataTable. Por otra parte, yo quiero que haya más de un WrappedDataTable en existencia para cualquier DataTable dado.

Un colega me sugirió que podía almacenar en caché mi WrappedDataTable y utilizar un método de fábrica para acceder a uno, como esto:

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;
    }
}

Esto me pareció muy cuestionable en un primer momento, supongo que porque me he convertido en familiarizados con la idea de que las llaves en un diccionario deben ser tipos inmutables. Pero tal vez esto no es necesariamente el caso? Una prueba rápida me reveló que un DataTable parece mantener un código hash consistente a lo largo de numerosas modificaciones a su contenido; por lo tanto, un Dictionary<DataTable, TValue> parece ser capaz de devolver un valor correcto para ContainsKey consistente.

Lo que me pregunto es si la versión base del object.GetHashCode por defecto devolverá un valor que no cambia para cada objeto individual, o si lo que estoy viendo con DataTable es sólo una ilusión?

Si el primero es cierto - y object.GetHashCode funciona bien - parece que el "uso únicos tipos inmutables como teclas de" asesoramiento en realidad sólo se aplica a los escenarios en los que:

  1. ¿Quieres la igualdad de los objetos que se acerca la igualdad de valor en lugar de la igualdad de referencia, y / o:
  2. Usted tiene un tipo personalizado con su propia aplicación GetHashCode que se basa en los miembros del tipo.

Cualquier sabios por ahí para el cuidado de arrojar algo de luz sobre esto para mí?


Actualizar : Gracias a Jon Skeet por responder a mi pregunta. En otras noticias, he hecho un poco de excavación y creo que se me ocurrió una IEqualityComparer<T> que hace proporcionar la comparación de identidad después de todo! Comprobar que funciona (lo siento enemigos VB.NET, acabo de tener un proyecto VB.NET de modo que es lo que escribió en - traducción es trivial):

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

Tome un vistazo a este programa de ejemplo:

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))

Salida:

False
37121646
45592480
¿Fue útil?

Solución

No tiene que devolver un valor único. Sólo tiene que devolver un uno que no cambia -. Y eso es lo que hace object.GetHashCode

la identidad del objeto Mientras DataTable no anula Equals o GetHashCode, que ha conseguido básicamente como la igualdad -. Lo que significa que no importa si el objeto está mutado

Personalmente me gustaría ver una implementación de IEqualityComparer<T> que proporciona igualdad de identidad para cualquier tipo, pero no podemos aplicar a nosotros mismos de que - no hay manera de saber lo que GetHashCode < em> le han regresado si no hubiera sido anulado. (Java tiene esta capacidad en sus bibliotecas estándar, pero .NET no. Grr.)

EDIT: Woot - con object.ReferenceEquals y RuntimeHelpers.GetHashCode(), se puede implementar fácilmente un IdentityEqualityComparer<T>. Yay!

Otros consejos

Creo que entienden las cosas bien. Para que un objeto se almacena en un diccionario, cualquier característica que pueda modificar su valor hash o pruebas de igualdad con otros objetos deben ser inmutables. Características que no afectarían esas cosas no tienen por qué ser inmutable.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top