Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `using(...)` effectively useless and/or inefficient?

Does the following code render the using(...) function/purpose irrelevant?
Would it cause a deficiency in GC performance?

class Program
{
    static Dictionary<string , DisposableClass> Disposables
    {
        get
        {
            if (disposables == null)
                disposables = new Dictionary<string , DisposableClass>();

            return disposables;
        }
    }

    static Dictionary<string , DisposableClass> disposables;

    static void Main(string[] args)
    {
        DisposableClass disposable;
        using (disposable = new DisposableClass())
        {
            //  do some work
            disposable.Name = "SuperDisposable";
            Disposables["uniqueID" + Disposables.Count] = disposable;
        }

        Console.WriteLine("Output: " + Disposables["uniqueID0"].Name);

        Console.ReadLine();
    }
}

class DisposableClass : IDisposable
{
    internal string Name
    {
        get { return myName; }
        set { myName = value; }
    }

    private string myName;

    public void Dispose( )
    {
        //throw new NotImplementedException();
    }
}

Output: SuperDisposable

My understanding of the using(...) function is to immediately coerce disposal of the DisposableClass. Yet within the code block, we are adding the class to a dictionary collection. My understanding is that a class is inherently a reference type. So my experiment was to see what would happen to the disposable object added to a collection in this manner.

In this case DisposableClass is still quite alive. Classes are a reference type - so my assumption then became that the collection is not simply referencing this type, but indeed holding the class as a value. But, that didn't make sense either.

So what is really going on?

EDIT: modified code with output to prove that the object is not dead, as might be suggested by some answers.

2nd EDIT: what this comes down to as I've gone through some more code is this:

    public void Dispose( )
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool dispose)
    {
        if (!isDisposed)
        {
            if (dispose)
            {
                // clean up managed objects
            }

            //  clean up unmanaged objects
            isDisposed = true;
        }
    }

    ~DisposableClass( )
    { Dispose(false); }

Stepping through the code (had a breakpoint at private void Dispose(bool dispose)), where false is passed to the method, it becomes imperative that resources are properly disposed of here. Regardless, the class is still alive, but you are definitely setting yourself up for exceptions. Answers made me more curious...

like image 514
IAbstract Avatar asked Dec 06 '22 03:12

IAbstract


1 Answers

Disposing an object does not destroy it; it simply tells it to clean up any unmanaged resources it uses as they are no longer needed. In your example, you're creating a disposable object, assigning to a dictionary, and then just telling it to remove some resources.

The correct scenario for the using statement is when you want to initialize a resource, do something with it, and then destroy it and forget about it; for example:

using (var stream = new FileStream("some-file.txt"))
using (var reader = new StreamReader(stream))
{
    Console.Write(reader.ReadToEnd());
}

If you want to retain the object after you've used it, you shouldn't be disposing it, and hence a using statement should not be used.

like image 56
Will Vousden Avatar answered Jan 02 '23 19:01

Will Vousden