views:

255

answers:

4

I was making a simple class for a small project and decided to just add a destructor for a quick impl instead of using IDisposable, and I came across a compiler error whenever there is a destructor with an access modifier on it.

public class MyClass
{
    public ~MyClass()
    {
        // clean resources
    }
}

I tried public, private, protected and internal. It worked fine with no access modifiers. Since this article shows that the ~destructor is essentially syntatic sugar for a protected Finalize function, it strikes me as odd that you cant use at least protected on the destructor. The article does say "Destructors cannot be called. They are invoked automatically." Is this how that behavior is enforced?

I ended up just implementing IDisposable anyway, but I am curious... is there some other reason why you cannot put access modifiers on a destructor?

+5  A: 

It's because, as you point out, "Destructors cannot be called. They are invoked automatically."

Having an access modifier on something that cannot be accessed is pointless.

Eric J.
Like putting a door handle on a wall.
Spencer Ruport
+13  A: 

An access modifier controls which scope of user-written-code can call the method.

public means any user-written-code can call the method, etc, etc.

However, destructors are not called by user-written-code. Destructors are called automatically by the GC. An access modifier means nothing to the GC.

Hence, putting an access-modifier on the method has no meaning. It cannot be accessed, and that access cannot be modified.

You might as well consider the access to a destructor to be "super-private", in that no one, not even the object itself, can actually call the destructor.

abelenky
Yup. Same thing for a static constructor. How about the "confidential" keyword?
Hans Passant
+11  A: 

The accessibility domain of a member declared in source code consists of the set of all sections of program text in which that member may be accessed.

An accessibility modifier modifies the contents of the accessibility domain.

An interesting fact about accessibility modifiers is that an accessibility modifier always makes the accessibility domain larger or keeps it the same size. An accessibility modifier never makes the accessibility domain smaller.

We desire that the accessibility domain of a destructor be always empty. That is, it should never be legal to access a destructor in any region of program text.

The reason for this is because we wish to provide to you the enforced invariant that a destructor for a particular instance is run exactly once in the lifetime of the object, at the end of said lifetime. ("Resurrection" of dead objects during finalization brings up interesting issues which I will discuss at a later date.) By disallowing access to the destructor we ensure that user code never calls a destructor early.

Therefore it would be foolish of us to allow the user to increase the size of the accessibility domain; we do not want to hand the user a tool to defeat this carefully-considered aspect of the design of the language.

Did you want to defeat this safety feature? Why? Can you describe a scenario in which it is important that you be able to call a destructor from some region of program text?

the destructor is essentially syntatic sugar for a protected Finalize function

Correct. The specification notes this in section 10.13. And note that the accessibility domain of the allegedly protected "Finalize" method is also empty; it may be neither overridden nor called.

We could have chosen some completely different mechanism to implement destructors, but that's the one we chose. The fact that we happened to choose some particular implementation strategy for the destructor feature has no particular bearing on the fact that the accessibility domain of a destructor should be enforced to remain empty for safety reasons.

Eric Lippert
I actually tried to answer your question before I posting. Since you can actively dispose of objects using the garbage collector, I cannot think of any case to call destructors explicity that doesn't already have an easy alternative. Aside from that, I did not understand the security concerns. Thank you for another lucid explanation.
NickLarsen
A: 

You should use the Disposable Pattern.

http://stackoverflow.com/questions/898828/c-finalize-dispose-pattern

JeremySpouken