Vitali D.
Vitali D.

Reputation: 55

Disposing by setting to null?

I'm aware of technique to handle IDisposable in a traditional manner. Say, in OnStop() method of windows service I close message queue client:

        if (client != null)
        {
            client.Dispose();
        }

For the first time today I saw one guy doing that this way:

        using (client)
        {
            client = null;
        }

What is exactly happening inside his "using" or does he dispose correctly at all?

Upvotes: 5

Views: 232

Answers (5)

supercat
supercat

Reputation: 81277

If the scope of "client" extends outside the "using" block, as it would appear to, the code as written will ensure that "client" gets disposed before control leaves the "using" block, and the reference to the newly-defunct "client" object will be destroyed. Nulling out the reference to it may be important if it's a field, and may be critical if it's a property that attaches events.

My guess would be that "client" is a field or property, and that the author of the "using" code thought it was more concise than the version given by Marc Gravell. I would grant the author that the code is concise, but would suggest that even more concise and clearer would be to define a generic "Zap" routine which accepts an IDisposable by reference, uses Interlocked.Exchange to read and null it, and disposes it if it wasn't null. In that case, the "using" statement would be replaced with:

  Zap(ref client);

which has the benefit of being more concise while almost certainly being clearer.

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1064044

Your using-based colleague's code will work, but is arguably overkill;

using(client) {
    client = null;
}

is essentially:

{ // scope here to denote that 'tmp' is not defined outside this scope
  var tmp = client;
  try {
      client = null;
  } finally {
      if(tmp != null) tmp.Dispose();
  }
}

(not quite that in all cases, as there are value-types and explicit interface implementation to think about).

Personally, I'd just use using for the whole thing where possible (i.e. in the code that initially allocates client).

One time I might use this is a lazy:

using(client as IDisposable) { client = null; } // dispose if needed

i.e. client is something outside my control, and I'm not sure if it implements IDisposable or not, but if it does, I need to release it.

Upvotes: 4

Julien Brousseau
Julien Brousseau

Reputation: 318

To me it looks not effective at all. Since the client is set to null the using has nothing referenced to dispose anymore, even though the actual object is still in memory, just not referenced by any variable (it will be garbage collected later on, but what's the point of the using then?).

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273711

The using(){} statement grabs a copy of the reference var so this assignment with null is ineffective.

Upvotes: 6

Marco
Marco

Reputation: 57593

Exiting from

using (client)
{
}

client.Dispose() is called automatically for you.
client = null should be called out of that code in my opinion.
Remember that to use using(object) the object should implement IDisposable interface.

Upvotes: 3

Related Questions