Integrating Dispose and Finalize into the Language
A reader comments
re: Changes in Destructor Semantics in Support of Deterministic Finalization
I agree with Johan.
I use a pattern where all classes that need a finalizer must implement the Dispose pattern, and all classes with a Dipose method also have a finalizer; if you have one you must have the other. All clients using the class must call the Dispose method.
In the debug build if a finalizer ever gets called it throws an exception - it means that the client never honored the contract. In the release build we log it and continue.
About being safe during finalization...there are more issues than just which subsystems are still valid (e.g. it may not be safe to call Console.WriteLine during system shutdown), there are also issues related to thread safety. I believe it's possible for a finalizer to run at the same time that the Dispose method is called.
BTW: I'm looking at this from a perspective of pure C#, not managed C++.
This is all fine and good, but it is not language design. Rather, it is an intelligent response to an absence of support within your selected language. That is, it is a policy, and the primary difficulties of any policy are: (a) how do you communicate that policy to a heterogeneous community of programmers? (b) how do you integrate that policy with the policies imposed by other libraries that your library may be combined with and which you cannot anticipate? and (c) how do you enforce your policy over time and large scale?
What our language has done is integrate the notions of Dispose (~R()) and Finalize (!R()) into the class mechanism itself: we have provided both a vocabulary and automated support that fits intuitively as an extension of the native constructor/destructor `initialization as resource acquisition’ design of ISO-C++. I think this is both truly elegant and superior to anything provided by other .NET languages.
Comments
- Anonymous
May 10, 2004
What about destructors for value classes? Was it considered when you did the language design?
To become truly usable they are still missing couple of things, copy constructors being one of them. It’s possible that it has some implementation difficulties but if we abstract from them for a moment, the question is if such value classes with copy constructors and destructors are of any value.
Possible applications could be containers for native objects or managed equivalent of smart pointers. I was also thinking about something similar to gcroot<> implemented with value classes that doesn’t need to “root” the managed object. - Anonymous
July 06, 2004
To become truly usable they are still missing couple of things, copy constructors being one of them?? - Anonymous
July 07, 2004
support for class-specific copy constructors (and of course copy assignment operators) is provided under a reference class -- it is not permitted for a value class -- nor is a default constructor and destructor. reference classes have really neat unification in their design ...
stan - Anonymous
July 21, 2004
Nice One Stan !