If a dependency container, or data access factory, can return types that may implement IDisposable
, should it be the client's responsibility to check for that and handle it? In my code below, one data class implements IDisposable
and the other doesn't. Either can be returned by the data access factory.
private static void TestPolymorphismWithDisposable()
{
// Here we don't know if we're getting a type that implements IDisposable, so
// if we just do this, then we won't be disposing of our instance.
DataAccessFactory.Resolve().Invoke();
// Do we just have to do something like this?
IFoo foo = DataAccessFactory.Resolve();
foo.Invoke();
var fooAsDisposable = foo as IDisposable;
if (fooAsDisposable != null) { fooAsDisposable.Dispose(); }
}
The reason I ask is that this seems to place a burden on the client code to have to handle this, and how do you let clients know, when building an API, that they may need to call dispose? Is there a better way to handle this where the client doesn't have to check for IDisposable
?
In the interest of a full working example, here are the other classes:
public interface IFoo
{
void Invoke();
}
public class DataAccessBaseNotDisposable : IFoo
{
public void Invoke()
{
Console.WriteLine("In Invoke() in DataAccessBaseNotDisposable.");
}
}
public class DataAccessBaseDisposable : IFoo, IDisposable
{
public void Invoke()
{
Console.WriteLine("Invoke() in DataAccessBaseDisposable.");
}
public void Dispose()
{
Console.WriteLine("In Dispose() in DataAccessBaseDisposable.");
}
}
public static class DataAccessFactory
{
public static IFoo Resolve()
{
return new DataAccessBaseDisposable();
//return new DataAccessBaseNotDisposable();
}
}
using(SomeObjectThatMightOrMightNotBeDisposable as IDisposable) { }
. That way you don't have to explicitly check if it implementsIDisposable
. – Evacuateas
keyword but not assigning the result to anything, so nothing is set to null. I haven't seen that technique before but it looks quite clever. It'll just call Dispose if it's there and literally do nothing else. – EyebrowGetEnumerator
are made during the lifetime of a collection, and the created enumerators are subscribed to the collection's "changed" event, the collection may hold subscriptions for an unbounded number of enumerators, none of which will be eligible for cleanup during the lifetime of the collection. – AchondroplasiaDispose
on the enumerators will clean up the subscriptions. Failing to callDispose
may prevent them from being cleaned up in timely fashion. The fact that the GC might perhaps be able to perform necessary cleanup is not enough. If an object acquires ownership of an object which implementsIDisposable
and might encapsulate unknown arbitrary resources, it must callDispose
. – Achondroplasia