At 15:56 09.10.2002 -0500, you wrote:
>Hi all,
>
>I originally posted this to DOTNET-CLR and meant to voice the same ideas
>here.  I hope this issue is not an old one, but here goes.
>
>Up front, I was wondering if the C++ managed extensions package provides
>anything such as the C# 'using' statement to make use of the IDispose
>easier.  Something tells me that the answer is, "no".

Not that I'm aware of. But C++ has deterministic destructors so you might
put any Dispose calls for embedded objects in there. The using statement
and the whole IDispose pattern is really only required because .NET doesn't
have deterministic destruction. Sometimes you can't wait for the garbage
collector to come around to release certain resources (typically OS
handles) and that's what the IDispose pattern is for.

>For some reason, it seems to me that it would have been much more natural
>for MS to wire the C# destructor to the IDispose interface rather than the
>Finalize() method.  I understand there could be some implementation
>details in there that would make that difficult, but it does seem more
>natural.

No implementation issues, fundamental conceptual issues! IDispose exists to
offer a _deterministic_ way to release resources. The C# destructor is
_not_ deterministic. Hence, wiring IDispose to the C# dtor wouldn't make
any sense.

>Of course, there are garbage collection issues and then you're back to the
>whole refcounting madness that we had back in the COM days.  For example,
>it would not be good for an object to be disposed when it leaves a scope
>while another scope is using it.  But then again, you can get into this
>same boat using the IDispose pattern with ref type objects anyway.

Yes, you only should be disposing of objects when you know that nobody else
will be using them. That's another reason why Dispose calls shouldn't be
implicit and automatic.

>There are some issues here that need to be addressed.  This stuff is not
>easy to solve.

Actually, I think it works just fine once you're aware of the actual role
of IDispose within the .NET Framework. :-)

>Moreover, who else agrees that __finally blocks are ugly and extremely
>error prone and difficult to maintain?  What sort of solution could we use
>to allow what C++ developers know as a destructor to do automatic cleanup?

I don't agree, I love them! Much better than writing those stupid C++
object wrappers with one-line dtors just because some file handle needs
closing or whatever.

I suspect you're stuck in a C++ paradigm where you feel you have to design
objects that automatically eradicate themselves as soon as they get out of
scope. That's absolutely not the .NET paradigm. The finally block exists
for the same reason as the IDispose pattern, namely to provide a solution
for those _rare and exceptional_ circumstances when you have to do some
deterministic cleanup at the end of a method or of an object's lifetime.
Unlike unmanaged C++, you absolutely don't have to do this all the time. In
fact, you shouldn't. Let the garbage collector do most of the clean-up for you!

>I understand C#'s 'using' statement makes life easier in this regard.  I'm
>assuming that if an exception propagates from within one of those blocks
>that it will handle the IDispose the same way as if it left the 'using'
>block gracefully.

The using statement implies a try/finally construction with the final
Dispose statement placed in the finally block.

>By exception safety I mean, the state of the system is not left in a half
>baked state when an exception occurs.  Destructors (and IDispose) are
>essential in this regard, unless you want to litter your code with
>unmanageable, error prone __finally blocks.

No, you are completely wrong here. .NET does not work like unmanaged C++,
you don't have to clean up everything yourself. That's what the garbage
collector is for. You do _not_ have the responsibility to leave the system
in a well-defined state in the face of exceptions -- the system takes care
of that automatically.

>Within the confines of C++, and using managed objects, d'tors don't behave
>the way they used to.  So, in order to trigger the dispose pattern, it
>seems that a stack based native C++ class is useful for handling this
>situation, no?

You are not supposed to implement IDispose for every object that comes
along. Nor destructors, for that matter. You are supposed to let the
garbage collector handle object deallocation whenever possible.

>Am I smoking something, or does anyone else agree that there are some very
>open ended issues here.  :-)

I can't really tell if you're smoking anything, I suspect you just need to
read a good .NET introduction and get those C++ programming patterns out of
your mind. :-)  The standard book on the .NET Framework is Jeffrey
Richter's "Applied Microsoft .NET Framework Programming" (Microsoft Press).
It should clear up all the questions you have.


You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.
Cheers, Chris

Reply via email to