C# .NET - c# deconstructor - Asked By Gerard Gleeson on 07-Jul-08 08:57 AM

I'm aware of csharp's finilizer ie "~CtorName(){}" but does csharp also have a deconstructor ?
http://en.csharp-online.net/CSharp_FAQ:_How_do_destructors_work_in_CSharp%3F

answer to c# deconstructor - Sakshi a replied to Gerard Gleeson on 07-Jul-08 08:59 AM

1. The term you are trying to say is Destructor not deconstructor.

2. ~func is the destructor.



Re : c# deconstructor - Ashutosh Dhok replied to Gerard Gleeson on 07-Jul-08 09:01 AM

Hi,

         In simple terms a destructor is a member that implements the actions required to destruct an instance of a class. The destructors enable the runtime system, to recover the heap space, to terminate file I/O that is associated with the removed class instance, or to perform both operations. For better understanding purpose I will compare C++ destructors with C# destructors. 

Generally in C++ the destructor is called when objects gets destroyed. And one can explicitly call the destructors in C++. And also the objects are destroyed in reverse order that they are created in. So in C++ you have control over the destructors. 

One may be thinking how C# treats the destructor. In C# you can never call them, the reason is one cannot destroy an object. So who has the control over the destructor (in C#)? it's the .Net frameworks Garbage Collector (GC). 

Now few questions arise why GC should control destructors why not us? 

The answer is very simple GC can do better object release than we can. If we do manual memory management one has to take care both allocation and de-allocation of memory. So there is always chance that one can forgot de-allocation. And also manual memory management is time consuming and complex process. So lets understand why C# forbids you from explicitly writing code for destructors. 

  1. If we are accessing unmanaged code usually we forget to destroy an object. This avoids the destructor call and memory occupied by the object will never get released. 

    Let examine this case by taking example, Below figure shows that Memory stacks in which application XYZ loads an unmanaged code of 30 bytes.

    When applications XYZ ends imagine it forgot to do destroy an object in Unmanaged code so what happens is Application XYZ memory gets deallocated back to the heap but unmanaged code remains in memory. So Memory gets wasted.

  2. If we are trying to release the object while object is still doing some process or i mean object is still active.

  3. If we are trying to release the object that is already been released. 

So lets see how GC will handle above situations: 

  1. If program ends GC automatically reclaims all the memory occupied by the objects in the program.
  2. GC keeps tracks of all the objects and ensures that each object gets destroyed once.
  3. GC ensures that objects, which are being referenced, are not destroyed.
  4. 4.GC destroys the objects only when necessary. Some situations of necessity are memory is exhausted or user explicitly calls System.GC.Collect() method. 

Understanding the complete working of Garbage collector (GC) is a big topic. But I will cover the some its details with respect to our topic. GC is a .net framework thread, which runs when needed or when other threads are in suspended mode. So first GC creates the list of all the objects created in the program by traversing the reference fields inside the objects. This list helps the GC to know how many objects it needs to keep track. Then it ensures that there are no circular references inside this list. In this list GC then checks for all the objects, which have destructor, declared and place them in another list called Finalization List. 

So now GC creates two threads one, which are reachable list and another unreachable, or finalization List. Reachable objects are cleared one by one from the list and memory occupied by these objects are reclaimed back. The 2nd thread, which reads the finalization lists and calls, the each object finalized in separate object. 

Lets see how C# compiler understands the destructor code. Below is a small class created in visual studio .Net, I have created a class called class1 which has a constructor and a destructor.  

using System;
namespace ConsoleApplication3
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
public Class1()
{}
~Class1()
{}
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Class1 c= new Class1();
}
}
}

So after compiling the code open the assemblies in ILDASM.EXE (Microsoft Diassembler Tool) tool and see the IL code. You will see something-unusual code. In above code the compiler automatically translates a destructor into an override of the Object.Finalize() method. In other words, the compiler translates the following destructor: 

class Class1
{
~Class1(){}
}

Into following: 

In Source Code Format: In IL Code Format:

class Class1
{
Protected override void Finalize()
{
try{..}
finally { base.Finalize();}
}
}

.method family hidebysig virtual instance void
Finalize() cil managed
{
// Code size 10 (0xa)
.maxstack 1
.try
{
IL_0000: leave.s IL_0009
} // end .try
finally
{
IL_0002: ldarg.0
IL_0003: call instance void [mscorlib]System.Object::Finalize()
IL_0008: endfinally
} // end handler
IL_0009: ret
} // end of method Class1::Finalize

The compiler-generated Finalize method contains the destructor body inside try block, followed by a finally block that calls the base class Finalize. This ensures that destructors always call its base class destructor. So our conclusion from this is Finalize is another name for destructors in C#. 

Points to remember:

  1. Destructors are invoked automatically, and cannot be invoked explicitly.
  2. Destructors cannot be overloaded. Thus, a class can have, at most, one destructor.
  3. Destructors are not inherited. Thus, a class has no destructors other than the one, which may be declared in it.
  4. Destructors cannot be used with structs. They are only used with classes.
  5. An instance becomes eligible for destruction when it is no longer possible for any code to use the instance.
  6. Execution of the destructor for the instance may occur at any time after the instance becomes eligible for destruction.
  7. When an instance is destructed, the destructors in its inheritance chain are called, in order, from most derived to least derived. 

 

Regrads

Ashutosh

c# deconstructor - Gerard Gleeson replied to Sakshi a on 07-Jul-08 09:10 AM

@Umapathy Kaliaperumal replied
2. ~func is the destructor.

But is this a finalizer in C#
http://www.java2s.com/Tutorial/CSharp/0140__Class/Demonstrateadestructor.htm

What I want is a destructor something which is called when an object's memory is released .
The output from the above eample would then be

Deconstructing 0
Deconstructing 1
Deconstructing 2
...
Done
answer to c# deconstructor - Sakshi a replied to Gerard Gleeson on 07-Jul-08 10:00 AM

You are asking about the dispose method.

You need to implement IDisposable interface and define the dispose method.



The example you pointed to is a very poor one. - Peter Bromberg replied to Gerard Gleeson on 07-Jul-08 10:01 AM

Because it gives the impression that you can have true destructors in C#, and you cannot.

Only the garbage collector can destroy an object and it does this when there are no longer any references to the object.   You need to get the concept that in .NET, you the programmer no longer control this as you do in C++ for example. The runtime takes care of it.

You can implement the IDisposable interface, and you can provide a finalizer, but only the GC can call it.

Reply - alice johnson replied to Gerard Gleeson on 07-Jul-08 01:20 PM

Contructor has the same name that of the class name

Example:

class classa

{

...............

}

public classa(int i, int j)

{

}

//This is aparameterised contructor.

static class()

{

}

// this is static contructor

Detructor also has the same nae that of a class but it is preceded by ~ symbol:

~class1(A)

{

}

//destructor example

there can be many contructors but only one destructor:

C# Destructor - Shailendrasinh Parmar replied to Gerard Gleeson on 08-Jul-08 01:25 AM
Destructors

The .NET framework has an in built mechanism called Garbage Collection to de-allocate memory occupied by the un-used objects. The destructor implements the statements to be executed during the garbage collection process. A destructor is a function with the same name as the name of the class but starting with the character ~.

Example:

class Complex
{
public Complex()
{
// constructor
}
~Complex()
{
// Destructor
}
}

Remember that a destructor can't have any modifiers like private, public etc. If we declare a destructor with a modifier, the compiler will show an error.Also destructor will come in only one form, without any arguments. There is no parameterized destructor in C#.

Destructors are invoked automatically and can't be invoked explicitly. An object becomes eligible for garbage collection, when it is no longer used by the active part of the program. Execution of destructor may occur at any time after the instance or object becomes eligible for destruction.

In C# all classes are implicitly derived from the super base class object. The object class contains one special method, Finalize(), which every class can override. The Garbage Collection mechanism in .NET will call this method prior to the garbage collection of the objects this class. Remember when we provide a destructor in a class, during the compilation time, the compiler automatically generates the Finalize() method. That means that a destructor and overridden Finalize() method can't co-exist in a class. The following code will generate a compilation error because of the above program

class Complex
{
~Complex()
{
}
protected override void Finaliz()
{
}
Destructors - Kalit Sikka replied to Gerard Gleeson on 08-Jul-08 01:45 AM

We use to call or override the http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx in C# and C# also uses destructors as the mechanism for writing finalization code.

Destructors in C# has following points:

  • Destructors cannot be defined in structs. They are only used with classes.

  • A class can only have one destructor.

  • Destructors cannot be inherited or overloaded.

  • Destructors cannot be called. They are invoked automatically.

  • A destructor does not take modifiers or have parameters.

For example, the following is a declaration of a destructor for the class Car:

class First
{
    ~First()
    {
        System.Diagnostics.Trace.WriteLine("First's destructor is called.");
    }
}

class Second : First
{
    ~Second()
    {
        System.Diagnostics.Trace.WriteLine("Second's destructor is called.");
    }
}

class Third : Second
{
    ~Third()
    {
        System.Diagnostics.Trace.WriteLine("Third's destructor is called.");
    }
}

class TestDestructors
{
    static void Main()
    {
        Third t = new Third();
    }

}
/* Output (to VS Output Window):
    Third's destructor is called.
    Second's destructor is called.
    First's destructor is called.
*/


In general, C# does not require as much memory management as is needed when you develop with a language that does not target a runtime with garbage collection. This is because the .NET Framework garbage collector implicitly manages the allocation and release of memory for your objects. However, when your application encapsulates unmanaged resources such as windows, files, and network connections, you should use destructors to free those resources. When the object is eligible for destruction, the garbage collector runs the Finalize method of the object.