Следует ли использовать ConditionalWeakTable ‹TKey, TValue› для целей, не являющихся компилятором?

Недавно я наткнулся на класс ConditionalWeakTable<TKey,TValue> в своем поиске IDictionary который использует слабые ссылки, как предлагается в ответах здесь и здесь.

Существует исчерпывающая статья в MSDN, в которой представлен класс и в которой говорится:

Вы можете найти класс ... в пространстве имен System.Runtime.CompilerServices. Он находится в CompilerServices, потому что это не универсальный тип словаря: мы предполагаем, что он будет использоваться только разработчиками компилятора.

и позже снова:

... условная слабая таблица не предназначена для использования в качестве коллекции общего назначения ... Но если вы пишете собственный язык .NET и вам нужно предоставить возможность прикреплять свойства к объектам, вам обязательно нужно изучить Условные Слабый стол.

В соответствии с этим описание класса в MSDN гласит:

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

Очевидно, что изначально он был создан для очень конкретной цели - помочь DLR, и пространство имен System.Runtime.CompilerServices воплощает это. Но, похоже, он нашел гораздо более широкое применение - даже в среде CLR. Если я ищу ссылки на ConditionalWeakTable в ILSpy, например, я вижу, что он используется в классе MEF _ 4_ и, среди прочего, во внутреннем классе WPF DataGridHelper.

У меня вопрос, можно ли использовать ConditionalWeakTable вне компилятора и языковых инструментов, и есть ли при этом какой-либо риск с точки зрения дополнительных накладных расходов или значительного изменения реализации в будущих версиях .NET. (Или этого следует избегать и использовать индивидуальную реализацию, такую ​​как этот вместо этого).

Дополнительную информацию можно найти здесь, здесь и здесь о том, как ConditionalWeakTable использует скрытую реализацию CLR ephemerons (через System.Runtime.Compiler.Services. DependentHandle), чтобы решить проблему циклов между ключами и значениями, а также то, как это не может быть легко выполнено индивидуальным способом.


person rikoe    schedule 19.04.2012    source источник


Ответы (1)


Я не вижу ничего плохого в использовании ConditionalWeakTable. Если вам нужны эфемероны, у вас практически нет другого выбора.

Я не думаю, что будущие версии .NET будут проблемой - даже если бы этот класс использовали только компиляторы, Microsoft все равно не смогла бы изменить его, не нарушая совместимости с существующими двоичными файлами.

Что касается накладных расходов - накладные расходы по сравнению с обычным словарем, безусловно, будут. Наличие большого количества DependentHandle, вероятно, будет дорого, подобно тому, сколько WeakReference будет дороже, чем обычные ссылки (GC должен выполнить дополнительную работу, чтобы сканировать их, чтобы увидеть, нужно ли их обнулить). Но это не проблема, если у вас нет большого количества (нескольких миллионов) записей.

person Daniel    schedule 22.04.2012
comment
Спасибо, отмечу это как ответ. Я думаю, что вы правы - мне нужен словарь, в котором используются слабые ссылки, поэтому ConditionalWeakTable не должен создавать дополнительных накладных расходов по сравнению с любой другой реализацией, использующей слабые ссылки, с дополнительным преимуществом использования эфемеронов. - person rikoe; 24.04.2012
comment
Меня очень взволновала доступность ConditionalWeakTable, но я заметил это в документации: вы не можете контролировать сравнение на равенство, переопределив Object.GetHashCode, чтобы явно установить хэш-код для ключа. Класс ConditionalWeakTable ‹TKey, TValue› не использует метод Object.GetHashCode для вычисления хэш-кодов и, следовательно, не вызывает переопределения Object.GetHashCode. - Делать это бесполезным для моих целей. :( - person ctrlplusb; 22.03.2013
comment
@Sean: ConditionalWeakTable не может использовать что-либо, кроме эталонного идентификатора для ключей, поскольку для него было бы невозможно (проблема с остановкой) узнать, когда код больше не может предоставить ключ, который должен соответствовать элементу в Коллекция. - person supercat; 05.06.2013