我想了解ConditionalWeakTable。有什么区别
class ClassA
{
static readonly ConditionalWeakTable<ClassA, OtherClass> OtherClassTable
= new ConditionalWeakTable<ClassA, OtherClass>();
}
和
class ClassB
{
OtherClass otherClass;
}
?使用ClassA或ClassB引用可空字段的优缺点是什么?
答案 0 :(得分:36)
我并不完全明白你所问的问题,我假设你问你是否应该使用你的类型中的属性或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的对象非常有用。但是,如果程序使用大量小对象,则弱引用会对内存使用产生负面影响。像this和this这样的话题也应该澄清一些遗留问题。
如果您正在寻找一个示例,那么当您可以使用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;
}
}
当然你总是可以手动取下它们,但下面所示的方法不是更简单吗?
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)
避免使用弱引用作为内存的自动解决方案 管理问题。相反,为...制定有效的缓存策略 处理应用程序的对象。
上面显示的这些扩展方法取自thread。
答案 1 :(得分:8)
两者之间的最大区别 - 确实是ConditionalWeakTable
存在的主要原因及其CompilerServices
的部分原因 - 是向{{1}添加字段} 需要能够向ClassA
添加字段,但构建密钥类型为ClassA
的{{1}}则不然。实际上,ConditionalWeakTable
存在以允许代码有效地添加字段&#34;到任何类的实例,而无需修改类本身。虽然在许多情况下可能会出于这种目的使用基于身份的弱密钥字典,但只有在没有值直接或间接引用其密钥的情况下才能工作,并且没有密钥循环直接或直接通过其他关键值引用。 ClassA
的设计允许收集密钥和值,即使存在这样的循环也是如此。
答案 2 :(得分: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
的实例附加到ClassA
的实例。 OtherClass
的实例将保留在内存中,只要它附加的ClassA
实例保持活动状态。