在一些 C++/CLI 代码中,我有一个本地类,它有一个工厂方法GetWrapper()
来创建自己的托管 .NET 包装对象。在内部,它通过 GCHandle 持有对其包装器的弱引用。当GetWrapper()
被调用时,检查 GCHandle 并返回现有包装器的句柄,或者(如果它不再指向对象,因为旧包装器对象已被垃圾收集器销毁)创建一个新包装器回来。
// .h
class NativeClass
{
public:
WrapperClass^ GetWrapper();
private:
WrapperClass^ GetNewWrapper();
GCHandle m_wrapperGCHandle;
};
// .cpp
WrapperClass^ NativeClass::GetWrapper()
{
if(m_wrapperGCHandle.IsAllocated)
{
try
{
WrapperClass^ wrapper = nullptr;
wrapper = dynamic_cast<WrapperClass^>(wrapperGCHandle.Target);
if(wrapper == nullptr)
{
return GetNewWrapper();
}
else
{
return wrapper;
}
}
catch(System::InvalidOperationException^)
{
return GetNewWrapper();
}
else
{
return GetNewWrapper();
}
}
WrapperClass^ NativeClass::GetNewWrapper()
{
WrapperClass^ wrapper = gcnew WrapperClass(/*some args*/);
m_wrapperGCHandle = GCHandle::Alloc(wrapper, GCHandleType::Weak);
}
现在奇怪的是它m_wrapperGCHandle.IsAllocated
总是返回 true,即使包装器已被垃圾收集。MSDN告诉“在使用弱句柄时使用此属性来确定 GCHandle 是否仍然可用。”。但这总是正确的。如果它不可用,那么 Target 是一个 nullptr。
我错过了什么还是 MSDN 错了?