C# 中是否有任何类提供 IDisposable 对象的共享所有权?像c++中的shared_ptr之类的东西?如果没有,这里的最佳实践是什么?
UPDATE
我正在本机库上编写一个 c++/cli 包装器。我需要释放本机资源(例如MAPI COM接口,所以我需要确定的资源释放).
原生部分:
//Message.h
class Message
{ ... };
//MessageSet.h
class MessageSet
{
...
class iterator : public std::iterator<std::forward_iterator_tag, Message*>
{
...
public:
Message* operator*();
bool operator!=(const iterator& that);
iterator& operator++();
};
iterator begin();
iterator end();
};
托管部分(c++/cli):
public ref class Message
{
native::Message* inst;
public:
Message(native::Message* inst);
~Message();
!Message();
};
public ref class MessageSet : public IEnumerable<Message^>
{
native::MessageSet* inst;
public:
MessageSet(native::Message* inst);
~MessageSet();
!MessageSet();
virtual IEnumerator<Message^>^ GetEnumerator();
virtual System::Collections::IEnumerator^ EnumerableGetEnumerator() = System::Collections::IEnumerable::GetEnumerator;
};
当我在 C# 中的 TPL 数据流(BroadcastBlock 块,即有许多并发消费者)中使用 Message 对象时,我不知道何时应该为这些消息调用 Dispose()。
我认为你能做的最好的事情就是这样:
public sealed class SharedDisposable<T> where T : IDisposable
{
public sealed class Reference : IDisposable
{
public Reference( SharedDisposable<T> owner )
{
mOwner = owner;
}
public void Dispose()
{
if( mIsDisposed ) return;
mIsDisposed = true;
mOwner.Release();
}
public T Value => mOwner.mValue;
private readonly SharedDisposable<T> mOwner;
private bool mIsDisposed;
}
public SharedDisposable( T value )
{
mValue = value;
}
public Reference Acquire()
{
lock( mLock )
{
if( mRefCount < 0 ) throw new ObjectDisposedException( typeof( T ).FullName );
mRefCount++;
return new Reference( this );
}
}
private void Release()
{
lock( mLock )
{
mRefCount--;
if( mRefCount <= 0 )
{
mValue.Dispose();
mRefCount = -1;
}
}
}
private readonly T mValue;
private readonly object mLock = new object();
private int mRefCount;
}
基本上这允许你拥有一个对象(SharedDisposable<T>
)管理底层一次性的生命周期,同时提供一种机制来分发对其的“共享”引用。
这里的一个缺点是,从技术上讲,任何人都可以通过共享引用访问底层值来处理它Value
财产。您可以通过创建某种外观对象来解决这个问题,该对象包装底层一次性类型但隐藏其Dispose
method.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)