2011-12-09 25 views
22

Estoy tratando de sacar los detalles de un verdadero WeakKeyedDictionary<,> para C# ... pero me encuentro con dificultades.¿Es posible crear un diccionario de clave débil en C#?

Me doy cuenta de que esta es una tarea no trivial, pero la aparente incapacidad para declarar un WeakKeyedKeyValuePair<,> (donde el GC solo sigue la referencia de valor si la tecla es alcanzable) lo hace aparentemente imposible.

Hay dos problemas principales que veo:

  1. Cada aplicación que he visto hasta el momento no recortar valores después de llaves se han recogido. Piénselo: una de las principales razones para utilizar dicho diccionario es evitar que se mantengan esos valores (¡no solo las claves!), Ya que son inalcanzables, pero aquí las referencias fuertes lo señalan.

    Sí, agregue/elimine del Diccionario lo suficiente y eventualmente serán reemplazados, pero ¿y si no?

  2. Sin un hipotético WeakKeyedKeyValuePair<,> (u otro medio para decirle al GC que solo marque el valor si la clave es alcanzable), ningún valor que haga referencia a su clave nunca se recopilará. Esto es un problema cuando se almacenan valores arbitrarios.

Problema 1 podría abordarse de una manera bastante no ideal/hacker: usar GC Notificaciones que esperar a que un GC completo para terminar, y luego ir a lo largo y podar el diccionario en otro hilo. Este con el que estoy semi-bien.

Pero el problema 2 me tiene perplejo. Me doy cuenta de que esto es contrarrestado fácilmente por un "así que no hagas eso", pero me pregunto si este problema es posible de resolver.

Respuesta

28

Eche un vistazo a ConditionalWeakTable<TKey, TValue> Class.

Permite a los compiladores asociar dinámicamente campos de objeto a objetos gestionados.

Básicamente se trata de un diccionario donde la clave y el valor son un WeakReference, y el valor se mantiene viva, siempre y cuando la llave está vivo.

Nota! Esta clase no usa GetHashCode y Equals para hacer comparaciones de igualdad, usa ReferenceEquals.

+0

Buen hallazgo, más intrigante! ¿Cómo se implementa? Me pregunto? Sin saber esto, el problema se convierte en "¿es posible crear un verdadero DiluitivoVálido <,>". Voy a profundizar en el reflector y ver si puedo resolverlo ... – Mania

+3

Qué pena, parece que depende de un .NET-magic interno "DependentHandle" para su implementación ... además ignora .GetHashCode y .Equals , convirtiéndolo en un diccionario deficiente en el mejor de los casos :(. Además, sin acceso a DependentHandle, el problema ahora se ha trasladado a la definición de un WeakValuedDictionary <,>. Supongo que esto puede ser lo más cercano que podamos ... – Mania

+7

@Mania The DependentHandle es la implementación de CLR de [ephemerons] (http://en.wikipedia.org/wiki/Ephemeron) que es imposible de implementar sin la cooperación de GC. Debería haber sido hecho público como GCHandle. Si no te importa el truco de la reflexión, puedes activar la estática Los métodos CLR en delegados e implementar su propio DependentHandle y WeakValuedDictionary. Tenga cuidado de estudiar el origen de referencia de .NET (que es público), o use algún descompilador, ya que tiene condiciones de carrera complicadas. ns. – Zarat

Cuestiones relacionadas