Jump to content
xisto Community
Sign in to follow this  
turbopowerdmaxsteel

C# Tutorial : Lesson 9 - Constructors & Destructors

Recommended Posts

The need for Initialization

A class contains data members (variables) and member functions. Initializing the values of these data members is essential, at times. Take a look at the following scenarios:-

 

int MyNumber;Console.WriteLine("My Number = {0}", MyNumber);

This block of code declares a variable MyNumber and then prints it on the screen. However, when you try to execute these instructions, an error Use of unassigned local variable 'Product' will be generated. This is because, we are trying to use the value of MyNumber, even before we have assigned it one. This is where initialization comes in. Many languages do implicit initialization based on the type of these atomic (int, char, bool, string, etc) data types. Example: 0 for int, false for bool, "" or NULL string for string. But, a strongly typed language like C# doesn't. The corrected code would be as follows:-

 

int MyNumber = 10;Console.WriteLine("My Number = {0}", MyNumber);

Take a look at this code snippet.

 

int Product;for (int I = 1; I <= 10; I  ){	Product *= I;}Console.WriteLine("The product of the first 10 natural numbers is {0}", Product);

This block of code is meant to calculate the product of the first 10 natural numbers. For this, we have setup a loop running from 1 to 10 and declared a variable named Product to store the running product. Finally, we display the result using Console.WriteLine. Again, this block of code generates an error on line 4. This is because, we haven't initialized the value of Product. The expression Product *= I is equivalent to Product = Product * I. When this expression is being evaluated for the first time, the Right Hand Side (RHS) part will be evaluated first. This generates the error because at the moment, Product has no value.

 

In the previous versions of VB (not VB .NET), the value for Product would have been automatically set to 0. While, this would take care of this error, a logical error would creep in and drive the calculations crazy - the product of first 10 natural numbers = 0. To correct this, Product must be initialized to 1. In situations like these, an initialization is a must. Here's the corrected code:-

 

int Product = 1;for (int I = 1; I <= 10; I  ){	Product *= I;}Console.WriteLine("The product of the first 10 natural numbers is {0}", Product);

Initializing Data Members

Data members can be initialized in a similar fashion:-

 

class MyClass{	int MyNumber = 69;}

However, its a better approach to have a method do all initializations inside a class.

 

class MyClass{	int MyNumber;	public void Initialize()	{		MyNumber = 69;	}}

After instantiating the object of this class, the method Initialize would have to be called to set the initial value for MyNumber.

 

MyClass ClassA = new MyClass();ClassA.Initialize();

This approach has a disadvantage too. The Initialize method needs to be called explicitly following the object instantiation. This is where the constructor jumps in. To define it: A Constructor is a special method which bears the same name as that of the class it is in and is used for initializing the data members of the class. Summing up the important properties of the constructor:-

A Method having the same name as that of the class it is defined in.

 

It does not return any value. Also, it doesn't have a return type associated with it, not even void.

 

It is used for initializing the data members.

 

A class can have multiple constructors.

 

It is automatically invoked when the class is instantiated.

Here is how the previous example would look when done with constructors.

class MyClass{	int MyNumber;	public MyClass()	{		MyNumber = 69;	}}

Now, when the class is instantiated, the method MyClass() will be automatically invoked and MyNumber will be assigned the value 69.

 

Static & Instance Constructors

Constructors can either be associated with a class's instance (object) or the class itself. Instance constructors are the ones associated with the object and are invoked when an object of the class is instantiated. They can be used to initialize the non static members of the class. The above example was that of an instance constructor.

 

Static constructors on the other hand, are invoked only once during the execution of the program and can be used to initialize the static variables.

 

Example:-

 

public class MyClass{	static int MyNumber;		static MyClass()	{		MyNumber = 69;	}}

A class can have these two constructors existing simultaneously:-

 

public class MyClass	{		static int MyNumber;		int YourNumber;		static MyClass()		{			MyNumber = 69;		}		MyClass()		{			YourNumber = 69;		}	}

Note: Static constructors can't be used to initialize non-static variables and Instance constructors can't be used to initialize static variables.

 

public class MyClass	{		static int MyNumber;		int YourNumber;		static MyClass()		{			YourNumber = 69;  // Error: YourNumber is not a static member		}		MyClass()		{			MyNumber = 69;  // Error: MyNumber is a static member		}	}

Parameterized Constructor

The instance constructors we have seen up until this point are all default constructors. They initialize the variables with hard-coded values and are hence not flexible. We can use parameterized constructors to overcome this problem. Parameterized constructors as the name suggests, take parameters with which they initialize the values of the member variables.

 

using System;namespace ConsoleApplication1{	class Program	{		static void Main(string[] args)		{			MyClass ClassA = new MyClass(69);		}	}	public class MyClass	{		int MyNumber;		public MyClass(int Number)		{			this.MyNumber = Number;		}	}}

Multiple, parameters can be supplied by separating each of them with a comma. The this keyword can be used to get a reference to the current instance of a class.

 

Destructors

That which can be created, can be destroyed. Hence came the destructor which has the same name as that of the class it is in and is prefixed by a tilde (~) symbol. Destructors are automatically invoked when the instance of the class is destroyed. They are ideally used to release any memory occupied by the member objects. The .NET Framework automatically manages the memory for the atomic data types (int, string, char, etc). However, user defined data types are managed using a safe mechanism which does not release the memory occupied by an object unless all references to it are destroyed. This can be done in the class destructor. The following example, instantiates an object of the Socket class (located in the System.Net.Sockets namespace) inside the constructor and closes it inside the destructor.

 

class MyClass	{		System.Net.Sockets.Socket Sck;		MyClass()		{			 Sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);		}		~MyClass()		{			Sck.Close();		}	}

Garbage Collection

The .NET Framework isolates the programmers from having to handle memory requirements. Garbage collection is the process of releasing the memory occupied by unused objects. Unlike, C there is no delete keyword in C# and objects cannot be explicitly destroyed. This job is automatically carried out by a special program of the .NET Framework known as the Garbage collector(GC). This program periodically scans the application for objects with no references and marks them for deletion. It is the GC which determines when the destructor of an object is invoked. This way, the GC ensures that only unused objects get destroyed.

 

Finalize() Method

This method allows an Object to attempt to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection.

Source: MSDN

 

This method is invoked when all of the references to an object are released from the memory. It does nothing by default and needs to be overridden. However, the precise timing of when the Finalize method would be invoked cannot be predicted. The CLR utilizes a system called reference-tracing Garbage collection, where by the GC periodically looks for objects that have no references left. Once such an object is found, the CLR invokes the Finalize method for the object, following which, the memory occupied by the object is released.

 

Dispose() Method

All classes that implement the IDisposable interface must define the Dispose() method. This method is to be used to perform application-defined tasks associated with freeing, releasing, or resetting unmanaged resources like Database connections, etc. Unlike, the Finalize() method, the Dispose() method is not automatically called and it must be explicitly called when the object is no longer in needed.

 

Fore more information on the Garbage Collection process, read this article written by Jeffrey Richter.

 

Previous Tutorial - Lesson 8 - Functions/methods

 

Lesson: 1 2 3 4 5 6 7 8

 

Notice from BuffaloHELP:
Member understands that tutorials contributed to Xisto would be 100% original from now on.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.