17

我试图了解ConditionalWeakTable。和有什么区别

class ClassA
{
    static readonly ConditionalWeakTable<ClassA, OtherClass> OtherClassTable
        = new ConditionalWeakTable<ClassA, OtherClass>();
}

class ClassB
{
    OtherClass otherClass;
}

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

4

3 回答 3

48

我不完全明白你在问什么,我假设虽然你问是否应该在你的类型中使用属性 or ConditionalWeakTable,你可以为该特定类型实例附加这样的属性。如果是这样,您也可以询问是否应该单独使用属性而不是字典,字典可以在特定键下包含此属性(这将是您的特定类型实例)。除非你需要这样的字典,否则这很废话。

理解ConditionalWeakTable<TKey, TValue>

实际上,它允许您ConditionalWeakTable将附加信息附加到现有的、托管的、非动态的 CLR 对象。本质上它可以被理解为一个字典,其中键被弱引用,因此只要键还活着,值就会保持活动状态。更多信息可以在MSDN上找到。

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

var classA = ClassA(); 
var classB = ClassB(); 
var other = OtherClass();

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

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

而不是下面这个?

/* set */
classB.OtherClass = other;
/* get */
var result = classB.OtherClass;

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

什么是弱引用,为什么要使用它?

这篇MSDN文章简要介绍了该主题。它基本上说弱引用不会延长对象的生命周期,因为一旦应用程序代码仍然可以访问这样的对象,它就可以被垃圾回收。弱引用可用于指向应该可用于 GC 的对象(如果它们没有被主动使用)。但是,如果程序使用大量小对象,弱引用会对内存使用产生负面影响。像thisthis这样的线程也应该澄清一些剩余的疑问。

如果您正在寻找可以使用ConditionalWeakTable<TKey, TValue>over standard的示例,请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;       
    } 
}

当然,您总是可以手动删除它们,但是下面显示的这种方法不是更简单吗?

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

同时(MSDN

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

上面显示的这些扩展方法取自这个线程

于 2013-09-04T12:26:39.533 回答
10

两者之间的最大区别——事实上,ConditionalWeakTable存在的主要原因和它是其中一部分的原因——CompilerServices是添加一个字段ClassA 需要能够添加一个字段到ClassA,但构造ConditionalWeakTable一个键类型为 的ClassA不需要。实际上,ConditionalWeakTable存在是为了允许代码有效地“添加字段”到任何类的实例,而无需修改类本身。虽然在许多情况下可以使用基于身份的弱键字典来实现这样的目的,但这只有在没有值直接或间接引用其键并且没有键循环时才会起作用。直接或直接通过其他键的值引用。的设计ConditionalWeakTable即使存在这样的循环,也允许收集键和值。

于 2014-11-12T17:22:37.447 回答
1

第一种方法的一个优点是您可以缓存OtherClass. 例如,

class ClassA
{
    static readonly ConditionalWeakTable<ClassA, OtherClass> OtherClassTable
        = new ConditionalWeakTable<ClassA, OtherClass>();

    public void Attach(OtherClass otherClass)
    {
        OtherClassTable.Add(this, otherClass);
    }

    public bool Get(out OtherClass otherClass)
    {
        return OtherClassTable.TryGetValue(this, out otherClass);
    }
}

然后,您可以将 的实例附加OtherClass到 的实例ClassAOtherClass只要ClassA它所连接的实例保持活动状态,该实例就会保存在内存中。

于 2013-09-03T19:34:18.877 回答