2011-12-09 4 views
22

Я пытаюсь исправить детали для истинного WeakKeyedDictionary<,> для C# ... но я столкнулся с трудностями.Можно ли создать действительно слабейший словарь в C#?

Я понимаю, что это нетривиальная задача, но кажущаяся неспособность объявить WeakKeyedKeyValuePair<,> (где GC следует только по ссылке значения, если ключ доступен) делает его кажущимся невозможным.

Есть две основные проблемы, которые я вижу:

  1. Каждая реализация я до сих пор видел не подрезать значения после того, как ключи были собраны. Подумайте об этом - одна из основных причин использования такого Словака - это предотвращать сохранение этих значений (а не только ключей!), Поскольку они недоступны, но здесь они указаны с помощью сильных ссылок.

    Да, добавьте/удалите из Словаря достаточно, и в конечном итоге они будут заменены, но что, если вы этого не сделаете?

  2. Без гипотетического значения WeakKeyedKeyValuePair<,> (или другое средство сообщить GC, что бы только отметить значение, если ключ достигнут) любое значение, относящееся к его ключу, никогда не будет собрано. Это проблема при сохранении произвольных значений.

Задача 1 может быть решена в довольно неидеальных/хаком образом: использовать GC Notifications ждать полного GC, чтобы завершить, а затем идти вперед и подрезать словарь в другом потоке. С этим я полуоочень.

Но проблема 2 меня в тупике. Я понимаю, что это легко противопоставляется «так не делай этого», но мне интересно, эта проблема даже разрешима?

ответ

28

Посмотрите на ConditionalWeakTable<TKey, TValue> Class.

Позволяет компиляторам динамически прикреплять поля объектов к управляемым объектам.

Это по существу словарь, в котором ключ и значение являются WeakReference, и значение сохраняется в живых до тех пор, пока ключ жив.

Примечание! Этот класс не использует GetHashCode и Equals для сравнения равенств, он использует ReferenceEquals.

+0

Приятная находка, самая интригующая! Как это реализовано? Интересно? Не зная этого, проблема становится «возможно ли создать действительно WeakValuedDictionary <,>». Я буду копаться в рефлекторе и посмотреть, смогу ли я это выяснить ... – Mania

+3

Какой позор, похоже, это зависит от внутренней .NET-магии «DependentHandle» для ее реализации. Кроме того, она игнорирует .GetHashCode и .Equals , что делает его некачественным Словарем в лучшем случае :(Кроме того, без доступа к DependentHandle проблема теперь переместилась на определение WeakValuedDictionary <,>. Я полагаю, что это может быть как можно ближе. – Mania

+7

@Mania DependentHandle - это реализация CLR из [ephemerons] (http://en.wikipedia.org/wiki/Ephemeron), который невозможно реализовать без сотрудничества с GC. Его следовало обнародовать, как GCHandle. Если вы не возражаете против обмана, вы можете включить статический CLR в делегатах и ​​реализовать свой собственный DependentHandle и WeakValuedDictionary. Будьте осторожны с изучением источника справочной системы .NET (который является общедоступным) или используйте какой-то декомпилятор, потому что у него сложная гонка нс. – Zarat