Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor for Abstract Class

In C++ I am aware that a virtual destructor should generally be used when one intends to inherit from a base class. However, with C# I am not sure what should be done. Consider the following code:

public abstract class Character
{
    private string characterName;
    public int health;

    Character()
    {

    }

    ~Character(){

    }

    public virtual void SetCharacterName( string tempName )
    {
        characterName = tempName;
    }

    public virtual string GetCharacterName( )
    {
        return characterName;
    }
}

(Note: I have heard that Unity3Ds implementation of C# is slightly different than standard. Perhaps ignore some minor formatting errors, the code is seemingly functional...)

My first instinct was the make the ~Character() destructor virtual, by defining it as:

virtual ~Character(){

}

yet doing so causes the IDE to return an error.

In C#, is it necessary or considered standard to use a virtual destructor for abstract classes which wish to be inherited? Or are there other means of making a virtual destructor with C#?

like image 318
TheYokai Avatar asked May 09 '14 23:05

TheYokai


People also ask

Can we have destructor in abstract class?

You can create an abstract base class with only a virtual destructor.

Can abstract class have destructor in C#?

An Abstract class can have instance variables (like constants and fields). An abstract class can have constructors and destructors.

Should abstract class have virtual destructor?

The answer to your question is often, but not always. If your abstract class forbids clients to call delete on a pointer to it (or if it says so in its documentation), you are free to not declare a virtual destructor. You can forbid clients to call delete on a pointer to it by making its destructor protected.

Should abstract class have constructor C++?

Can it have constructor? Yes it can and the purpose is to initialize local variables from the base class. You should avoid using public constructor in Abstract and use protected only.


Video Answer


1 Answers

C# doesn't have deterministic destruction. In fact, it doesn't really have destructors, per se: it has finalizers and IDisposable.

The GC will clean things up if and when it gets around to garbage collecting the object instance. All objects will [eventually] get cleaned up one way or another when the app domain terminates, but it's possible that a given object might hang around for the duration of the app domain. In your case, you don't need to do anything as your object has no resources that need cleaning up. Unreferenced objects will get properly disposed of when the GC sweeps them up.

Mostly, one doesn't need finalizers. You might want to read up on Finalizers at http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx and note that

The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a IDisposable.Dispose implementation.

You might also want to read Understanding when to use a Finalizer in your .NET class and note:

Why is a Finalize method bad?

...

If an object has a finalizer, it will be placed in the FinalizationQueue and is subject so some additional clean-up. Once the object is no longer referenced on a thread or from a global reference, the next time the Garbage Collector (GC) runs, it will see this object is ready to be collected. But it can’t collect it yet. It has to let the Finalizer run first. So the GC will finish collecting, then the Finalizer will Finalize the object, and then another GC collection will occur.

This can have a huge affect on performance as you should remember that all managed threads will be stopped waiting on the GC and then the GC will be stopped waiting on the Finalizer thread.

There is a lot more data out there about Finalization so I encourage you to read about it as much as possible so that you use it in the best way possible.

If your object needs something deterministic, you can implement IDisposable and either explicitly invoke Dispose() or use a using block:

using ( Character foo = CharacterFactory.CreateInstance("Jane") )
{
   // do something useful with Jane
}

when the enclosing using block is exited, foo.Dispose() is guaranteed to be invoked. It's identical to this code (with the exception of the scope of foo):

Character foo = ... ;
try
{
  ...
}
finally
{
  foo.Dispose() ;
}

However, the point of IDisposable is more about making sure that unmanaged resource are released in a timely manner. DBAs tends to get all grumpy when you block 400 users when your object goes out of scope and is hanging out waiting to be GC'd, leaving an in-flight query running. Or your object goes out of scope, leaving an exclusively locked file open.

like image 167
Nicholas Carey Avatar answered Sep 29 '22 00:09

Nicholas Carey