C#中IDisposable对象的共享所有权 [英] Shared ownership of IDisposable objects in C#

查看:191
本文介绍了C#中IDisposable对象的共享所有权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#中是否有提供IDisposable对象共享所有权的类?像C ++中的shared_ptr一样?如果不是,这里的最佳做法是什么?

Is there any classes in C# which provide shared ownership of IDisposable objects? Something like shared_ptr in c++? And if not, what are best practices here?

更新

我正在通过本机lib编写一个c ++/cli包装器.而且我需要释放本机资源(例如, MAPI COM接口,因此我需要确定性的资源释放).

I'm writing a c++/cli wrapper over native lib. And I need release native resources (MAPI COM interfaces for example, so I need determenistic resource releasing).

本机部分:

//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):

Managed part (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 Dataflow中的Message对象(BroadcastBlock块,即有许多并发使用者)时,我不知道何时应该为这些消息调用Dispose().

When I use Message objects in TPL Dataflow (BroadcastBlock block i.e. there are many concurrent consumers) in C# I don't know when I should call Dispose() for these messages.

推荐答案

我认为您能做的最好的事情是这样的:

I think the best you could do is something like this:

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>)管理基础一次性物品的寿命,同时提供一种机制来分发对它的共享"引用.

Basically this allows you to have one object (SharedDisposable<T>) manage the lifetime of the underlying disposable while providing a mechanism to distribute "shared" references to it.

这里的一个缺点是,从技术上讲,任何人都可以通过共享引用Value属性访问基础值来处理基础值.您可以通过创建某种外观对象来解决此问题,该外观对象包装基本的一次性类型但隐藏其Dispose方法.

One shortcoming here is that technically anyone could dispose the underlying value by accessing it through the shared reference Value property. You could address this by creating some sort of facade object that wraps the underlying disposable type but hides its Dispose method.

这篇关于C#中IDisposable对象的共享所有权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆