【发布时间】:2011-12-29 19:16:09
【问题描述】:
作为一名试图习惯 .NET 的经验丰富的 C++ 程序员,Microsoft 的 WeakReference“Target”属性中有一个实现细节困扰着我......
public class WeakReference : ISerializable
{
internal IntPtr m_handle;
internal bool m_IsLongReference;
...
public virtual object Target
{
[SecuritySafeCritical]
get
{
IntPtr handle = this.m_handle;
if (IntPtr.Zero == handle)
{
return null;
}
object result = GCHandle.InternalGet(handle);
if (!(this.m_handle == IntPtr.Zero))
{
return result;
}
return null;
}
[SecuritySafeCritical]
set
{
IntPtr handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
object oldValue = GCHandle.InternalGet(handle);
handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
GCHandle.InternalCompareExchange(handle, value, oldValue, false);
GC.KeepAlive(this);
}
}
...
}
困扰我的是——他们为什么要检查 m_handle 的有效性两次?特别是在“设置”方法中 - 在方法末尾使用 GC.KeepAlive 应该可以防止 WeakReference 被垃圾收集,从而保持句柄非零 - 对吗?
在“get”的情况下——一旦我们通过 InternalGet 实际检索到对目标的引用,为什么还要再次检查原始 m_handle 值?我所能想到的只是,也许他们试图防止在 InternalGet 期间或之后处理和完成 WeakReference - 但可以肯定的是,在我们返回对象之前,它不能也被处理和完成吗?我只是想不出一个有效的解释来解释为什么这里需要这种双重检查......
【问题讨论】:
-
你为什么这么关心实现?您发布的是实际的 Microsoft 许可代码,还是 Mono 的?
-
+1 好问题。在这两个访问器中似乎没有多大意义。
-
@Dykam 阅读代码是一种很好的学习方式,将图书馆代码视为“魔法”是一种不学习和发展迷信的好方法。另外,我不想认为这个 sn-p 即使受版权保护也不属于合理使用范围。
-
@Complicatedseebio,这是真的,但我会有点犹豫自己发布 MS 代码。
标签: c# .net thread-safety weak-references