How to properly dispose objects: injected vs. owned

Reynaldi

I have a question about disposing objects.

Consider this IDisposable class

public class MyClass : DisposableParentClass
{
    private MyProp _prop;        

    public MyClass(MyProp prop)
    {
        _prop = prop;
    }

    public MyClass()
    {            
        _prop = new MyProp();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _prop.Dispose();
        }

        base.Dispose(disposing);
    }

}       

On the first constructor, MyProp is injected. So MyClass is not the owner of the object. But on the second constructor, MyProp is created locally. Should I always dispose MyProp, or should I check first if it is injected or not.

public class MyClass : DisposableParentClass
{
    private MyProp _prop;        
    private bool _myPropInjected = false;

    public MyClass(MyProp prop)
    {
        _prop = prop;
        _myPropInjected = true;
    }

    public MyClass()
    {            
        _prop = new MyProp();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (!_myPropInjected) { _prop.Dispose(); }
        }

        base.Dispose(disposing);
    }

}       
Lasse V. Karlsen

If your class should handle these two situations:

  1. It is not the owner of the provided object, it should not dispose of it
  2. It is the owner of the created object, it should dispose of it

Then yes, you need to have a mechanism that tells these two situations apart.

A common method (common to me anyway) is to use naming convention like this:

private MyProp _prop;        
private bool _ownsProp = false;

ie. reverse the meaning of your flags, but this is details, your solution is just fine, and yes, you need to have a solution like this.


If you have a ton of these fields, where each must have its own bool field to handle this, it might be worth creating a helper class, such as this LINQPad program demonstrates:

void Main()
{
    Injectable i1 = new Injectable();
    Injectable i2 = new Injectable(new Injected("A"));
    Injectable i3 = new Injectable(new Injected("A"), new Injected("B"));

    Debug.WriteLine("dispose a and b");
    i1.Dispose();

    Debug.WriteLine("dispose b");
    i2.Dispose();

    Debug.WriteLine("no dispose");
    i3.Dispose();
}

public class Injected : IDisposable
{
    public Injected(string name) { Name = name; }
    public string Name { get; set; }
    public void Dispose() { Debug.WriteLine(Name + " disposed"); }
}

public class Injectable : IDisposable
{
    private Ownable<Injected> _A;
    private Ownable<Injected> _B;

    public Injectable(Injected a, Injected b)
    {
        _A = Ownable.NotOwned(a);
        _B = Ownable.NotOwned(b);
    }

    public Injectable(Injected a)
    {
        _A = Ownable.NotOwned(a);
        _B = Ownable.Owned(new Injected("B"));
    }

    public Injectable()
    {
        _A = Ownable.Owned(new Injected("A"));
        _B = Ownable.Owned(new Injected("B"));
    }

    public void Dispose()
    {
        _A.Dispose();
        _B.Dispose();
    }
}

public class Ownable<T> : IDisposable
    where T : class
{
    private readonly T _Instance;
    private readonly Action _CleanupAction;

    public Ownable(T instance, bool isOwned)
    {
        _Instance = instance;

        if (isOwned)
        {
            IDisposable disposable = instance as IDisposable;
            if (disposable == null)
                throw new NotSupportedException("Unable to clean up owned object, does not implement IDisposable");

            _CleanupAction = () => disposable.Dispose();
        }
    }

    public Ownable(T instance, Action cleanupAction)
    {
        _Instance = instance;
        _CleanupAction = cleanupAction;
    }

    public T Instance { get { return _Instance; } }

    public void Dispose()
    {
        if (_CleanupAction != null)
            _CleanupAction();
    }
}

public static class Ownable
{
    public static Ownable<T> Owned<T>(T instance)
        where T : class
    {
        return new Ownable<T>(instance, true);
    }

    public static Ownable<T> Owned<T>(T instance, Action cleanupAction)
        where T : class
    {
        return new Ownable<T>(instance, cleanupAction);
    }

    public static Ownable<T> NotOwned<T>(T instance)
        where T : class
    {
        return new Ownable<T>(instance, false);
    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to properly dispose objects in Flambe?

From Dev

Memory leaks in Delphi app. How to properly dispose objects and strings?

From Dev

Memory leaks in Delphi app. How to properly dispose objects and strings?

From Dev

Memory leaks, and strange bugs with runnable class - How to properly dispose of objects?

From Dev

How to use dispose() properly?

From Dev

How to Dispose SharpDX objects

From Dev

How to get objects owned by a user?

From Dev

How to properly dispose of ThreadLocal variables?

From Dev

How to properly dispose of a pthread mutex?

From Dev

How to properly dispose objects created for Ldap search using ADODB ADsDSObject provider

From Dev

How to properly use the dispose method on a class

From Dev

How to dispose properly using async and await

From Dev

How to properly dispose of pinvoke/unmanaged code

From Dev

How to properly dispose the stream when using StreamContent

From Dev

How to properly use the dispose method on a class

From Dev

How to properly dispose of pinvoke/unmanaged code

From Dev

How to close or dispose of TCP client properly?

From Dev

How to Dispose a list of objects;Does it Free the Memory

From Dev

How to dispose managed and unmanaged objects in C#?

From Dev

How to Dispose a list of objects;Does it Free the Memory

From Dev

dispose vs finalize how the object free the memory?

From Dev

How to properly copy objects

From Dev

How to properly copy objects

From Dev

How to free resources and dispose injected service in ASP.NET 5/Core by the end of request?

From Dev

How do I get PicoContainer to start/stop/dispose a component injected by a factory?

From Dev

How Symfony\Component\Validator\Validator could be properly injected into service?

From Dev

Dispose will dispose objects that are still referenced?

From Dev

How to properly dispose collection of unmanaged resources from finalizer?

From Dev

How to properly close ODP.net connection : dispose() or close()?

Related Related

  1. 1

    How to properly dispose objects in Flambe?

  2. 2

    Memory leaks in Delphi app. How to properly dispose objects and strings?

  3. 3

    Memory leaks in Delphi app. How to properly dispose objects and strings?

  4. 4

    Memory leaks, and strange bugs with runnable class - How to properly dispose of objects?

  5. 5

    How to use dispose() properly?

  6. 6

    How to Dispose SharpDX objects

  7. 7

    How to get objects owned by a user?

  8. 8

    How to properly dispose of ThreadLocal variables?

  9. 9

    How to properly dispose of a pthread mutex?

  10. 10

    How to properly dispose objects created for Ldap search using ADODB ADsDSObject provider

  11. 11

    How to properly use the dispose method on a class

  12. 12

    How to dispose properly using async and await

  13. 13

    How to properly dispose of pinvoke/unmanaged code

  14. 14

    How to properly dispose the stream when using StreamContent

  15. 15

    How to properly use the dispose method on a class

  16. 16

    How to properly dispose of pinvoke/unmanaged code

  17. 17

    How to close or dispose of TCP client properly?

  18. 18

    How to Dispose a list of objects;Does it Free the Memory

  19. 19

    How to dispose managed and unmanaged objects in C#?

  20. 20

    How to Dispose a list of objects;Does it Free the Memory

  21. 21

    dispose vs finalize how the object free the memory?

  22. 22

    How to properly copy objects

  23. 23

    How to properly copy objects

  24. 24

    How to free resources and dispose injected service in ASP.NET 5/Core by the end of request?

  25. 25

    How do I get PicoContainer to start/stop/dispose a component injected by a factory?

  26. 26

    How Symfony\Component\Validator\Validator could be properly injected into service?

  27. 27

    Dispose will dispose objects that are still referenced?

  28. 28

    How to properly dispose collection of unmanaged resources from finalizer?

  29. 29

    How to properly close ODP.net connection : dispose() or close()?

HotTag

Archive