理解ConditionalWeakTable

cm0*_*007 12 .net dictionary weak-references

我想了解ConditionalWeakTable.有什么区别

class ClassA
{
    static readonly ConditionalWeakTable<ClassA, OtherClass> OtherClassTable
        = new ConditionalWeakTable<ClassA, OtherClass>();
}
Run Code Online (Sandbox Code Playgroud)

class ClassB
{
    OtherClass otherClass;
}
Run Code Online (Sandbox Code Playgroud)

?使用ClassA或ClassB引用可空字段的优缺点是什么?

jwa*_*zko 37

我不确切地得到你所问的内容,我假设你问你是否应该在你的类型中使用属性,或者ConditionalWeakTable你可以为这个特定类型实例附加这样的属性.如果是这样,您可以选择是否应该单独使用属性而不是字典,它可以在特定键(将是您的特定类型实例)下包含此属性.除非你需要这样的字典,否则这是非常废话.

了解ConditionalWeakTable<TKey, TValue>:

什么ConditionalWeakTable实际上做的是,它可以让你附加额外的信息存在,托管,非动态的CLR对象.本质上,它可以理解为字典,其中键和值都被弱引用,只要键处于活动状态,值就会保持活动状态.可以在MSDN上找到更多信息.

所以,你应该问问自己你的需求是什么.假设您的类型被实例化:

var classA = ClassA(); 
var classB = ClassB(); 
var other = OtherClass();
Run Code Online (Sandbox Code Playgroud)

是否要以这种方式使用绑定到此类实例的属性:

/* set */
var other = new OtherClass();        
ClassA.OtherClassTable.Add(classA, other);
/* get */
OtherClass data = null;
var result = ClassA.OtherClassTable.TryGetValue(classA, out data);
Run Code Online (Sandbox Code Playgroud)

而不是下面这个?

/* set */
classB.OtherClass = other;
/* get */
var result = classB.OtherClass;
Run Code Online (Sandbox Code Playgroud)

除非有特殊需要,否则答案似乎非常明显.这里当然还有其他问题:

什么是弱参考,为什么要使用它?

这篇MSDN文章很快解释了这个主题.它基本上表示弱引用不会延长对象的生命周期,只要应用程序代码仍然可以访问它,就可以对其进行垃圾回收.如果没有主动使用,那么弱引用对于指向应该可用于GC的对象非常有用.但是,如果程序使用大量小对象,则弱引用会对内存使用产生负面影响.像这样的线程,也应该澄清一些遗留的疑虑.

如果您正在寻找一个例子,当您可以使用ConditionalWeakTable<TKey, TValue>超标准时Dictionary<TKey, TValue>,请想象以下情况.您希望在运行时将属性字典绑定到实例,但同时如果您已停止使用它们,则不希望阻止它们被收集.不幸的是,在标准方法中它是不可能的 - GC被阻止,因为字典仍然拥有对它们的强引用,如下所示:

var x = new object();
x.Props().Y = "hello";

static class ExpandoExtensions 
{
    private static IDictionary<object, dynamic> props = 
        new Dictionary<object, dynamic>();
    public static dynamic Props(this object key)
    { 
        dynamic o;
        if (!props.TryGetValue(key, out o)){
            o = new ExpandoObject();
            props[key] = o;
        }
        return o;       
    } 
}
Run Code Online (Sandbox Code Playgroud)

当然你总是可以手动取下它们,但下面所示的方法不是更简单吗?

static class ExpandoExtensions
{
    private static readonly ConditionalWeakTable<object, ExpandoObject> props =
        new ConditionalWeakTable<object, ExpandoObject>();

    public static dynamic Props(this object key)
    { 
        return props.GetOrCreateValue(key);       
    } 
}
Run Code Online (Sandbox Code Playgroud)

同时(MSDN)

避免使用弱引用作为内存管理问题的自动解决方案.相反,开发一个有效的缓存策略来处理应用程序的对象.

上面显示的这些扩展方法取自此主题.


sup*_*cat 8

两者之间的最大区别 - 实际上,ConditionalWeakTable存在的主要原因及其所在的原因 - CompilerServices是添加一个字段ClassA 需要ClassA添加字段的能力,但构造ConditionalWeakTable一个键类型ClassA却没有.实际上,ConditionalWeakTable存在允许代码有效地"添加字段"到任何类的实例而无需修改类本身.虽然在许多情况下可能会出于这种目的使用基于身份的弱密钥字典,但只有在没有值直接或间接引用其密钥的情况下才能工作,并且没有密钥循环直接或直接通过其他键的值引用.ConditionalWeakTable即使存在这样的循环,也允许收集键和值的设计.