15

So a using statement automatically calls the dispose method on the object that is being "used", when the using block is exited, right?

But when is this necessary/beneficial?

For example let's say you have this method:

public void DoSomething()
{
    using (Font font1 = new Font("Arial", 10.0f))
    {
        // Draw some text here
    }
}

Is it necessary to have the using statement here, since the object is created in the method? When the method exits, wont the Font object be disposed of anyway?

Or does the Dispose method get run at another time after the method exits?

For example if the method was like this:

public void DoSomething()
{
    Font font1 = new Font("Arial", 10.0f);

    // Draw some text here
}

// Is everything disposed or cleared after the method has finished running?
nobody
  • 19,814
  • 17
  • 56
  • 77
John B
  • 20,062
  • 35
  • 120
  • 170
  • Just because something goes out of scope doesn't mean all the resources get cleaned up. If you have handles to unmanaged objects (say, COM objects), those will be orphaned when your managed object dies. They'll hang around for the life of the process, creating memory leaks. – Rex M Apr 15 '09 at 16:41
  • In your example you explicitely tell the object to cleanup, this is useful for db connections or if you were holding a lock on a file. If you didn't, the objects finalizer would run sometime later on (not specifically after the method ends), cleaning it up - but perhaps to late. – meandmycode Apr 15 '09 at 16:42

14 Answers14

20

The 'using' statement is most useful when working with unmanaged objects, like database connections.

In this way, the connection is closed and disposed no matter what happens in the code block.

For more discussion, see this article on CodeProject: http://www.codeproject.com/KB/cs/tinguusingstatement.aspx

Jeff Fritz
  • 9,821
  • 7
  • 42
  • 52
  • So memory-wise, the object is still waiting to be cleaned up... but the benefit is that any resources the object has of its own, can be released in its Dispose method. But does exiting the method call Dispose on the objects? – John B Apr 15 '09 at 16:43
  • Yes, a return statement in the midst of a using block will call Dispose on the object. Finalizers and GC will fire later at an undetermined time. – Jeff Fritz Apr 15 '09 at 16:44
  • Only if the method contains "using", and only for the objects mentioned in the "using". – C. K. Young Apr 15 '09 at 16:44
  • Existing a function by itself will _not_ dispose objects in a deterministic way. A using statement will. – Joel Coehoorn Apr 15 '09 at 16:45
  • Technically the object should have a finalizer that WOULD run eventually and close the connection. – meandmycode Apr 15 '09 at 16:49
  • meandmycode: Yes, but that's not good enough; you want the connection to be disposed of (straight away) when you're done. – C. K. Young Apr 15 '09 at 16:50
  • Yes I noted this in my comment to the question- I'm just pointing out that dispose doesn't ensure a close no matter what happens, the close will happen regardless of dispose - just not reliably. – meandmycode Apr 15 '09 at 16:53
  • DBConnections that are not disposed of immediately after use run the risk of starving the connection pool, and throwing a nasty unable to connect to the database error. – Jeff Fritz Apr 15 '09 at 16:53
  • The key is "eventually" vs "deterministic". For many resources (database connections, sockets, semaphores/mutexes), "eventually" just isn't good enough. – Joel Coehoorn Apr 15 '09 at 16:53
  • Dispose will be called without a using statement, but you don't know when. The object could be held open for a long time. A using statement makes sure it's closed right away, even if an exception is thrown. – Joel Coehoorn Apr 15 '09 at 16:55
  • using is just a shortcut for try/finally. you get the same functionality, it's just syntactic sugar. – Darren Kopp Apr 15 '09 at 16:55
  • OK, I think I understand it now. Great conversation guys. Thanks to everyone involved! – John B Apr 15 '09 at 16:56
  • Technically Dispose isn't called without a using statement, the gc isn't aware of disposable- but it would run the finalizer, which by disposable guidelines would call into a consistent protected method that dispose would also call into, additionally specifying if the call was a dispose or a finaliz – meandmycode Apr 15 '09 at 16:58
  • (for reference^, as some people believe the Dispose() method is called at gc) – meandmycode Apr 15 '09 at 16:59
13

Without using (or manually calling Dispose()), the object will eventually be disposed of, just not at a deterministic time. That is, it can happen straight away, in two days' time, or (in some cases) never.

For things like, say, network connections, you want the connection to close when you're done with it, not "whenever", otherwise it'll idle around hogging up a socket.

Further, for things like mutex locks, you do not want those to be released "whenever", or else deadlock is likely to result.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • While this is likely true, this isn't true by rule. The GC does not call Dispose itself, so it's up to the developer to create a finalizer that ensures resources are cleaned up even if Dispose isn't called. – Adam Robinson Apr 15 '09 at 16:59
  • Agree. Although well-written finalizers will do what dispose is supposed to do. – C. K. Young Apr 15 '09 at 17:05
13

This:

public void DoSomething()
{
    using (Font font1 = new Font("Arial", 10.0f))
    {
        // Draw some text here
    }
}

maps directly to this:

public void DoSomething()
{
    {
        Font font1;
        try
        {
            font1 = new Font("Arial", 10.0f);
            // Draw some text here
        }
        finally
        {
            IDisposable disp = font1 as IDisposable;
            if (disp != null) disp.Dispose();
        }
    }
}

Note the finally block: the object is disposed even if an exception occurs. Also note the extra anonymous scope block: it means that not only is the object disposed, but it goes out of scope as well.

The other important thing here is disposal is guaranteed to happen right away. It's deterministic. Without a using statement or similar construct, the object would still go out of scope at the end of the method and could then be collected eventually. The resource then would ideally be destroyed so it can be reclaimed by the system. But "eventually" might not happen for a while, and "would ideally" and "will" are very different things.

Therefore, "eventually" isn't always good enough. Resources like database connections, sockets, semaphores/mutexes, and (in this case) GDI resources are often severely limited and need to be cleaned up right away. A using statement will make sure this happens.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
9

The using construct enforces deterministic disposal -- i.e. release of resources. In your example above, yes, if you don't employ a "using" statement, the object will be disposed, but only if the recommended disposable pattern (that is, disposing of resources from a class finalizer, if applicable) has been implemented for the class in question (in your example, the Font class). It should be noted, that the using construct can only be used with objects that implement the IDisposable interface. It is the presence of that interface on an object that allows using to "call" the Dispose method.

Additionally, underlying resources will only be released when the garbage collector decides to collect your out-of-scope Font object. A key concept in .Net programming (and most languages with a garbage collector) is that just because an object goes out of scope does not mean that it is finalized/released/destroyed, etc. Rather, the garbage collector will perform the clean-up at a time it determines -- not immediately when the object goes out of scope.

Finally, the using statement "bakes in" a try/finally construct to ensure that Dispose is called regardless of contained code throwing an exception.

Peter Meyer
  • 25,711
  • 1
  • 34
  • 53
  • 1
    It doesn't enforce finalization at all. It enforces deterministic disposal. I think it's a good idea to keep finalization and disposal separate in one's mind. (Many disposable types won't have a finalizer at all.) – Jon Skeet Apr 15 '09 at 17:01
  • Totally agree -- poor choice of terms on my part. Think I'll edit the question to reflect that. Finalizers are a completely different construct. – Peter Meyer Apr 15 '09 at 17:48
2

the "Using" comes into play when a resource needs to be disposed and it implements the IDisposable interface.

Jose Basilio
  • 50,714
  • 13
  • 121
  • 117
2

Here's what using really does (based on your example)

Font font1 = new Font(...);
try
{
    // code that uses font...
}
finally
{
    if (font1 != null)
        font1.Dispose();
}

So you don't need to worry about exception making your variable not disposed.

Migol
  • 8,161
  • 8
  • 47
  • 69
2

When the method exits, wont the Font object be disposed of anyway?

No, it will become unreferenced, and thus eligible for garbage collection. Unless something else (e.g. a reference held in another data structure) holds on to a reference.

Or does the Dispose method get run at another time after the method exits?

Yes, in a process not allocating much memory that could be a considerable time after the method has exited.

Garbage Collection is inherently asynchronous and lazy, thus making it a great way to ensure memory is freed, if memory is not too limited; but poor for almost any other resource.

Richard
  • 106,783
  • 21
  • 203
  • 265
2

It seems very simple to me.

If a class implements IDisposable, then it is almost asking you to please call Dispose on any instance that you create, as soon as you're done with it. This is the pattern I suggest should be used, whenever such an instance is created:

using (var instanceName = new DisposableClass())
{
    // Your code here
}

It's simple, it's clean, and it works for everything except for WCF proxy classes, which are broken. For those, see http://www.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • Not _every_ time. An acceptable alternative is to wrap one or several IDisposables in a class which itself implements IDisposable. This class then disposes it's dependants in it's own Dispose method and finalizer. – Joel Coehoorn Apr 15 '09 at 18:21
  • +1 though for IDisposable == asking to be safely disposed. I'd even say "begging" or "demanding". – Joel Coehoorn Apr 15 '09 at 18:23
  • @Joel: if multiple are wrapped, then what is exposed is a single IDisposable, which should be implemented following this pattern. The pattern is for instances you create, which implement IDisposable. – John Saunders Apr 15 '09 at 19:52
0

They are useful in any situation when you want cleanup code to be called on an object deterministically and regardless of exceptions (since a using statement is really just a try/finally).

Most often they are used to clean up unmanaged resources but you can use them however you see fit.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
0

It is purely syntactic sugar on top of a try-catch-finally block and a call to the Dispose method. It does not even necessarily define a lexical scope since you can hand it an instance variable. Basically, it makes your code cleaner and easier to maintain.

JP Alioto
  • 44,864
  • 6
  • 88
  • 112
0

Dispose is called when it exits the using statement because it's explicitly called by that construct. The dispose method isn't called explicitly when the variable goes out of scope (exiting method).

The behavior you MAY observe that looks like that is that usually things that implement IDisposable also call the Dispose method in the classes destructor, and the destructor COULD be called soon after the variable goes out of scope, but not guaranteed. The destructor is invoked by the garbage collector.

Darren Kopp
  • 76,581
  • 9
  • 79
  • 93
0

I like to use them like this:

    static public void AddSampleData(String name)
    {
        String CreateScript = GetScript(String.Format("SampleData_{0}", name));
        using (IDbConnection MyConnection = GetConnection())
        {
            MyConnection.Open();
            IDbCommand MyCommand = MyConnection.CreateCommand();
            foreach (String SqlScriptLine in CreateScript.Split(';'))
            {
                String CleanedString = SqlScriptLine.Replace(";", "").Trim();
                if (CleanedString.Length == 0)
                    continue;

                MyCommand.CommandText = CleanedString;
                int Result = MyCommand.ExecuteNonQuery();
            }
        }
    }

They work great for cases where you don't want to put error checking code only cleans up and passes the error on down. The alternative method would look like this:

    static public void AddSampleData(String name)
    {
        String CreateScript = GetScript(String.Format("SampleData_{0}", name));

        IDbConnection MyConnection = null;
        try
        {
            IDbConnection MyConnection = GetConnection();
            MyConnection.Open();
            IDbCommand MyCommand = MyConnection.CreateCommand();
            foreach (String SqlScriptLine in CreateScript.Split(';'))
            {
                String CleanedString = SqlScriptLine.Replace(";", "").Trim();
                if (CleanedString.Length == 0)
                    continue;

                MyCommand.CommandText = CleanedString;
                int Result = MyCommand.ExecuteNonQuery();
            }
        }
        finally
        {
            if (MyConnection != null
                && MyConnection.State == ConnectionState.Open)
                MyConnection.Close();
        }
    }

And frankly, which method is easier to read? Same thing with forms:

    public void ChangeConfig()
    {
        using (ConfigForm MyForm = new ConfigForm())
        {
            DialogResult ConfigResult = MyForm.ShowDialog();
            if (ConfigResult == DialogResult.OK)
                SaveConfig();
        }

        ConfigForm MyForm = new ConfigForm();
        DialogResult ConfigResult = MyForm.ShowDialog();
        MyForm.Dispose();
        if (ConfigResult == DialogResult.OK)
            SaveConfig();
    }
JasonRShaver
  • 4,344
  • 3
  • 32
  • 39
0

All the answers about deterministic vs. undeterministic and how the using works under the hood are correct.

But to pick your specific sample, don't forget that almost all System.Drawing (GDI+ wrapper) objects also hold references to unmanaged memory, so that you may run into trouble when using those extensively without disposing them properly (where using is the easiest way).

Lucero
  • 59,176
  • 9
  • 122
  • 152
0

I asked a very similar question here:

Resources that have to be manually cleaned up in C#?

And i got a nice piece of advice in the form of:

In general, if something has a Dispose method, you should call it when you've finished with it, or, if you can, wrap it up in a using statement.

Community
  • 1
  • 1
Gary Willoughby
  • 50,926
  • 41
  • 133
  • 199