Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative syntax for C# using statement to automatically dispose objects?

I was wondering if anyone can think of a way to implement a mechanism that works like the using statement in C# but with a cleaner syntax.

In C++/CLR you can write

MyClass NewObject;

MyClass is a managed class here. As soon as the variable goes out of scope Dispose will be called. In essence, it does the same thing C# does with using but in a nicer way.

So, instead of writing

using (MyClass NewObject1=new MyClass())
{
    xxxx;
    using (MyClass NewObject2=new MyClass()
    {
    }
}

(I think this doesn't look very clean and it's also tedious to open a new block for every new variable)

I would prefer something like this:

autodispose MyClass NewObject1=new MyClass();
xxxx;
autodispose MyClass NewObject2=new MyClass();

Does anybody think it would be possible to implement something like this? It seems frameworks for AOP or code contracts use mechanisms that inject code but I am not sure how they do it.

like image 642
maxxxx Avatar asked Dec 02 '22 23:12

maxxxx


2 Answers

MyClass is a managed class here. As soon as the variable goes out of scope Dispose will be called.

That's just not true, even in C++/CLR. My understanding is that C++/CLR still relies on the core .Net garbage collector for managed objects, rather than traditional C++ destructor semantics... and by those rules the object is disposed at some non-deterministic point in the future; it might be immediate... but more likely not. It will probably be fairly soon... but you can't be sure.

Even in the C# world, a using block is reserved for unmanaged resources (ie: anything other than RAM). You don't need to put just any object in a using block: most things can be safely created without one. When you need a using block is when there's something like a network connection, database connection, file handle, gdi resource, system timer, etc wrapped up in the type you're creating.

like image 152
Joel Coehoorn Avatar answered Jan 10 '23 19:01

Joel Coehoorn


While I don't have answer I feel it's worth writing this up as an answer instead of just comments. The current answer with the most votes is as far as I know incorrect. According to Gordon Hogenson in Foundations of C++/CLI it does support "syntactic sugar or sleight of handle".... "To sum up, the heap-allocated object is immediately deleted at the end of the block, rather than lazily garbage collected, and as a consequence, the destructor is called immediately upon deletion." -emphasis mine, p 63 Stack vs. Heap Semantics

C++ programmers (pre smart pointers) are used to the fact that everything they new they must delete. However, when a C++ programmer creates a local variable, it does not have to be put on the heap. Stack semantics can be used and then the object doesn't have to explicitly deleted.

void Class::SomeMethod()
{ 
   DbConnection connection;  //No memory leak if not deleted
   DbConnection leaky_connection = new DbConnection(); //on the heap will leak if not deleted
}

In C++/CLI it would look a little different for heap allocation:

DbConnection^ connection = gcnew DbConnection();

But since MS knew C++ programmers are used to stack semantics they allow the stack semantic version:

DbConnection connection;

And assuming the existence of :

~DbConnection()
{
   //Close the connection
}

The stack semantic version will immediately call the destructor at the end of the method where connection is used.

I think the difficulty in doing this in C# is for the opposite of why it's allowed in C++/CLI (and here I may get into trouble). C# programmers are used to letting the garbage collector take care of things. They can allocate a local object stick it into a non-local container and not worry that it will go out of scope at the end of the method. The GC knows it's in the collection and it doesn't get prematurely destroyed. C# always deals with object references and you don't explicitly specify heap vs. stack storage. Implementing this "sleight of handle" in C# would probably break a lot of code and expectations.

In fact even the using statement syntax can create unexpected trouble in C#. I wrote up my favorite example of this in When Dispose Throws the Baby Out with the Bathwater a while back.

like image 25
Tod Avatar answered Jan 10 '23 18:01

Tod