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?
UPDATE
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).
Native part:
//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();
};
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;
};
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:
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.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 itsDispose
method.You do not own
IDisposable
, you implement it, so .NET Garbage Collector will call overridden method in your class, notifying about a fact happened.It's a different concept from shared_ptr, where destructor is guaranteed to be called once last ownership of a pointer is gone.
In general, in .NET, unless you are not using unsafe programming techniques, you do not own anything, .NET Garbage Collector owns it. Even when you explicitly destroy an object, the memory allocated for it may not, and often will not, be reclaimed immediately, like once would expect from
C++
.EDIT
If you have native resources and want release them in precise moment, you can achieve that by :
1) Implementing
IDisposable
with your .NET wrapper object2) Inside
Dispose()
method of that wrapper write the code that releases native resources3) In the code that consumes wrapper object, in the moment you would like to release native resources allocated by wrapper object, call explicitly
Dispose()
on it.In this case
Dispose()
method is called, your code executes and releases native resources immediately.EDIT (2)
After that is more clear what's the question about:
If you can not determine when
Dispose()
has to be called, I would stay with @Hans's comment: just relay on eventual (soon or later)GC
call and avoid your own reference counter implementation (especially in multi threaded environment). Do not invent the wheel, if that is a feasible in your situation.That would a NO. Best way I found so far is quite clunky, using Dictionaries and WeakReferences. The Dictionary maps the object to it's refcount. WeakReference is used so you don't increase the ref count artificially.