NINPUTER comments on "http://blog.joycode.com/lijianzhong/archive/2005/01/13/42991.aspx#feedback) (http://blog.joy/2005/01/13/42991.aspx#feedback) comments to" VB to Finalize Loose, you can rewrite, call directly, allowing the Finalize of the parent class, or multiple times of Finalize, etc., unless you are not like C # ".
In fact, the Finalize method of the C # looks only better than VB, but still has a very hidden problem. Questions are as follows.
First, look at the following code:
Using System; Public Class GrandPapa {~ GrandPapa () {Console.WriteLine ("GrandPapa. ~ GrandPapa);}} public class Parent: GrandPapa {~ Parent () {Console.WriteLine (" Parent. ~ Parent ");} PUBLIC CLASS SON: PUBLIC CLASS SON: Parent {~ SON () {Console.Writeline ("SON. ~ SON");}} public class app {public static void main () {SON S = new SON (); gc.collect () Gc.waitforpendingfinalizers ();}}
This code runs no doubt:
SON. ~ SON PARENT. ~ Parent Grandpapa. ~ Grandpapa
There is no problem. But what happens if the Parent class is redefined as follows?
Public Pass Parent: GrandPapa {Protected Void Finalize () {Console.WriteLine ("Parent.Finalize");}}
The result of the operation becomes:
Son. ~ Son Parent.Finalize
The situation is already somewhat not, I define a "ordinary" Finalize method in Parent, which is called by the destructor of its subclass SON?
Of course, the Finalize method is not a "common" method in C #, and the sectator is compiled is a Finalize method with the above-mentioned signature. But the C # compiler does not ban we define "ordinary" Finalize,
The C # specification does not point out such a Finalize method to define a destructor - actually not, just the performance of the above code - even such a seductive mistake: The Compiler Behaves as if this Method Finalize), And Overrides of it, do not exist at all. Analysis IL code can be seen that "ordinary" Finalize method defined in Parent actually "deceives" its subclass. Its subclass is only concerned about whether its parent class defines Finalize (of course, it is the above form) method, which does not care whether the Finalize method has a "destructor" semantic.
If the behavior of the above code can be accepted by rational analysis, then the result of the following code is dizzy, and the Parent class is redefined as follows (a Virtual key) is added on the basis of the above):
Public Pass Parent: GrandPapa {Protected Virtual Void Finalize () {Console.writeline ("parent.finalize");}} After compiling, the results are as follows:
Grandpapa. ~ Grandpapa
This time, from the perspective of IL code, I suspect that the CLR's judgment of the destructor has additional conditions, but in any case, the behavior of the C # compiler is strange, because this result is put in It's hard to say it. I used to dig this SSCLi source code for a long time, but I can't find the reason.
This aspect is a bug of the C # compiler, and on the other hand, a bug of the CLR. This bug is from the 1.0 version of the .NET Framework version (VS.NET 2002), to version 1.1 (vs.net 2003), and 1.2 version of the Alpha version of the LONGHORN operating system. Later I wrote to the product manager for C # Eric gunnerson (http://blogs.msdn.com/ericgu/) tells them this bug. Eric Gunnerson then reply to tell me that they will fix this bug.
I am now using the Visual C # Express 2005 compiler compile (Version 8.00.41013) The above code, and the two modifications will get a WARNING:
WARNING CS0465: Introducing a 'Finalize' Method CAN Interfere with Destructor Invocation. Did you intend to declare a destructor?
But if you don't care about this warning, the execution behavior of the resulting EXE file is still very strange. That is to say, the bug in the CLR still does not difix. I personally think that WARNING is not enough for the C # compiler, and should completely disabate such a Finalize method.
In fact, there is such a terms in the Draft of my Effective .NET (in C #) book:
# Don't have idea of defining any Finalize method in a class, because it will cause potential serious damage to your "destructor chain".