Die, You Gravy Sucking Pig Dog!

Shame, we can almost get there…

using System;

class SqlConnection: IDisposable
{
public void Dispose() {}

public void Close() {}

}

static class SqlConnectionExtensions
{
public static void DieYouGravySuckingPigDog(this SqlConnection connection)
{
connection.Close();
connection.Dispose();
}
}

class Program
{
static void Main()
{
SqlConnection c = new SqlConnection();
c.DieYouGravySuckingPigDog();
c = null; // Blast…
}
}

Use an extension method, almost…

sqlConnection.Close();
sqlConnection.Dispose();
sqlConnection = null;

That is one hellaciously closed database connection.

You can avoid this by using ‘using’ :

using (SqlConnection conn = new SqlConnection(Server=localhost; Database=myDatabase;))
{
SqlCommand command = conn.CreateCommand();
command.CommandType = CommandType.Text;
command.CommandText = SELECT myField FROM myTable;

conn.Open();
int i = (int) command.ExecuteScalar();
}

Or for that matter use C++/CLI where you can declare your reference type ‘on the stack’ (at least from a syntax perspective) and the compiler will automatically do the deterministic call to Dispose when you leave the scope.

True, you can use things like extension methods and/or wrapper classes for things like this (for example, we’ve a connection wrapper here that, along with it’s other uses, has it’s own ‘open/close’ which performs the close/dispose/null on it’s own…

But there are many objects or classes like that which have a Close() a Dispose() and then, well, there’s the good ole =null. Not having to do that in the first place is what I think the point of the article was at…?

So, GC is great, right? Throw cpu cycles at it - they’re basically free, after all!

Yeah, do that on a 400MHz embedded ARM9. The art of mallocing and freeing is still pretty important for a lot of applications.

I’m primarily a PHP programmer and I find myself calling the unset() function regularly and this is entirely down to being a little obsessive about resources. A typical page load lasts less than a second and with the amount of servers our company has we’re nowhere near capacity, but for some unknown reasons in my subconscious; I still feel the need to keep the memory usage as low as possible.

Explicitly setting sqlConnection to null is a legacy of the classic VB/COM days when these things were reference counted.

I thought that carrying it over into .NET and other programming languages with modern generational garbage collectors is more a case of ignorance and/or cargo cult programming than anything else.

What? Jeff learned C?!

This is an area where using dependency injection shines, as you can easily do deterministic disposal of all instances requested from your container.

Autofac in particular handles this scenario very well:

using (var inner = container.CreateInnerContainer())
{
var component = inner.ResolveSomeComponent();
// component, and any of its disposable dependencies, will
// be disposed of when the using block completes
}

Ronald: I think you completely missed the point of what was being said. Of course you can use using to avoid that. The point is to show how overzealous programmers get when trying to clean up resources, when it really isn’t necessary.

Very funny.

However, I would recommend just using a database connection pool.

In Java-land (where I spend most of my time) you can even go further. After setting the variable to null you can call System.gc() which forces the garbage collector to run Right Now.

Aviv, no of course he didn’t learn C. He would definitely write a blog entry so we could all know to stop chastising him about it.

I find it kinda funny that Double b1; is Jeff’s example of newing something up. Besides the lack of the word new, aren’t value-types stored on the stack in C# anyway?

From now on I’m putting the following code in all my programs…

//Holy crap!, that’s one hellaciously
//closed database connection
sqlConnection.Close();
sqlConnection.Dispose();
sqlConnection = null;

In general, any object having both Close Dispose, you’re ok calling only one.

It’s true dispose shouldn’t be required to be called, but some API’s (cough AutoCAD cough) get all sorts of pissed off if things get disposed/finalized in the wrong order.

There is always a give and take, but overzealous or not, it’s never a bad thing to think in terms of efficiency.

While I wouldn’t go so far as to set the object as null, I will indeed dispose of (or use a using block**) everything I can when I’m done with it, I think it’s just prudent to not ignore such a small and easily implemented optimization.

Maybe it’s just that my co-worker has been beating ultra optimization into my head for over a year now though, he is very zealous about optimizing his code, but it makes sense to go ahead and dispose of it…now if only I had a GC to take my trash to the dumpster for me…

Contrary to what you seem to think, it is NOT necessary to use malloc() for every variable in C. It’s also not necessary to use malloc() if you need to call a function that takes a pointer. It’s much easier to use (address-of operator). The only time I can think of that you need to use malloc() is when you don’t want the variable to be automatically deleted when the function ends.

But I agree that languages that allocate everything with the new operator, like Java, need a garbage collector. If they didn’t have a garbage collector, people would use a language that allocated most things on the stack, like C and C++.

@Sarel Botha: I’m fairly sure the System.gc() call in Java merely suggests that the VM do garbage collection immediately. I don’t think the programmer can really force it to run at all.

@Nate: Sometimes, your object is too large to live on the stack, so you have to put it on the heap, regardless of how long it will live.

What C programmer would put the explicit cast in the malloc call??? The two lines don’t mean the same thing either.

It should be:

double* b1 = malloc(msizeof(double));
if(b1 == NULL) exit(1); /
it just seems wrong to leave this out even in a demo! */

vs

Double[] b1 = new Double[m];

Of course the real point here is disposing of resources, which can get ugly.

free(b1);
b1 = NULL; /* optional */

vs

nothing!

(And it gets really fun when you consider error handling.)

But that isn’t necessarily garbage collector; C++ does the same with RAII:

std::vectordouble b1;
[…]
// it cleans itself up!