Archive

Archive for August, 2007

C# Tutorial : Lesson 12 – Inheritance – Part I

August 24th, 2007

One of the important aspects of the Object Oriented Methodology is relationship. Objects do not exist as isolated entities, rather, they exhibit some kind of relationship with other objects. Some of the common relationships between the classes are listed below:-

Instantiation Relationship

This is the relationship that exists between a class and its instance or object. Real world examples of such a relationship can be:-

  • A Ferari is a Car
  • A Mobile Phone is a type of electronic device
1
2
3
4
5
6
7
8
9
10
11
class Car
{
	string Model;
	string Company;
	string SerialNumber;
}
 
void Main(string[] args)
{
	Car MyCar = new Car();	// Instantiation Relationship between MyCar & Car
}
Composition Relationship

Classes can be nested i.e a Class can contain another class. The relationship between two such classes is called composition relationship.

Composition

The following code represents the Composition relationship that is depicted in the above diagram.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Car
{
    string SerialNumber;
    string Model;
    string Color;
 
    class Engine
    {
        string Type;
        string Model;
    }
 
    class Wheel
    {
        int Width;
        string Manufacturer;
    }
}
Utilization Relationship

The concept of OOP allows a class to make use of another class i.e delegate some portion of its work to another specialized class. The relationship between these two classes is termed as utilization. Ferari an object of the car class, is driven by Michael, an object of the driver class. These two entities have a utilization relationship between them.

The following code snippet demonstrates the utilization relationship between the Sorter and the Swapper class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Sorter
{
    public static void Sort(int[] A)
    {
        for (int I = 0; I < A.Length - 1; I++)
        {
            for (int J = I + 1; J < A.Length; J++)
            {
                if (A[I] > A[J])
                {
                    // Utilizes the Swapper Class to do the swapping
                    Swapper.Swap(A[I], A[J]);
                }
            }
        }
    }
}
 
class Swapper
{
    public static void Swap(ref int Num1, ref int Num2)
    {
        int Temp = Num1;
        Num1 = Num2;
        Num2 = Temp;
    }
}

This example uses the bubble sort algorithm to sort an array of integers in the ascending order. While sorting, two elements of the list need to be swapped when they are not arranged ascendingly. The Sorter class employs the Swapper class for this job thus utilizing it.

Inheritance

Just as a child inherits qualities from his/her parents, a class can inherit data members and functions from another class. Consider the following class diagram:-

The Mammals class is the base class as it inherits its attributes to other classes. Dogs, cats & Humans are its child classes. This hierarchy is derived from the common set of attributes that the classes share. Mammals, for example are warm blooded, vertebrates, possess external ears and have hair on their body. These characteristics also pertain to Dogs, Cats, Humans, Lions, Tigers and Leopards, thus making them mammals. In C#, a class can have multiple child classes but only 1 base class. Multiple inheritance which existed in languages such as C++ has been scrapped because they tend to cause more problems than they solve.

Some key terms related to Inheritance are listed below.

  • Base(Super) Class – The class that inherits its properties to other classes.
  • Child(Sub) Class – The class that inherits its properties from other classes.
  • Multi-level Inheritance – A class which inherits from another class, serves as the base class for a third class. In the preeceding diagram, Lions, Tigers & Leopards are derived from the Cats class which itself is derived from the Mammals class. This is called multi-level inheritance.
  • Generalization – Classes that inherit from the same base class have certain common attributes which have been inherited from the common base class. This relationship is called Generalization.
  • Specialization – It refers to the uncommon characteristics of a sub class, those that make it different from others. When we say that Human is a kind of Mammal, we imply that they have the common properties of Mammals along with some specialized characteristics that make them different from other Mammals – They walk on two legs. Specialization is the opposite of Generalization.
Implementing Inheritance


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Cars MyFerari = new Cars();
            MyFerari.NumberOfWheels = 4;
            MyFerari.Drive();
        }
    }
 
    public class Vehicles
    {
        private string Name;
        public int NumberOfWheels;
        public void Drive()
        {
        }
    }
 
    public class Cars : Vehicles
    {
 
    }
}

In this example, the Cars class is a sub class which is derived from the Vehicles class. The Cars class inherits the data member NumberOfWheels and the member function – Drive() from the Vehicles class. So, the MyFerari object of the Car class has access to these members.

Note: Private members are not accessible from the sub class. So, the follwoing code would cause a ‘ConsoleApplication1.Vehicles.Name’ is inaccessible due to its protection level. error.

MyFerari.Name = "Ferari";
Determining Inheritance Hierarchies

This process is very simple as the only thing one needs to remember is that the sub class should be a type of the base class. For example: Human is a type of Mammal, Car is a type of vehicle and so on.

Note: Improper usage of Inheritance will not result in any syntactical error. But, the design model for the program would be at fault.

Constructor Inovking Order

Constructors being unique to a class are not inherited. Whenever an object of a child class is created, the constructor of both the parent and the child class is invoked. The parent class must come into existence before its child class can. Therefore, the constructor of the base class is invoked first followed by the constructor of the derived class. The destructors are invoked in the opposite order – derived to base. This is because the child class must be destroyed before the parent class.

The following program confirms these two order.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Cars MyFerari = new Cars();
            Console.ReadLine();
        }
    }
 
    public class Vehicles
    {
        public Vehicles()
        {
            Console.WriteLine("Vehicles -> Constructor Invoked");
        }
 
        ~Vehicles()
        {
            Console.WriteLine("Vehicles -> Destructor Invoked");
        }
    }
 
    public class Cars : Vehicles
    {
        public Cars()
        {
            Console.WriteLine("Cars -> Constructor Invoked");
        }
 
        ~Cars()
        {
            Console.WriteLine("Cars -> Destructor Invoked");
        }
    }
}

C#

Celebration @ NIIT: 60th Independence Year of India

August 18th, 2007

Today was the first event organized by the to-be-formed Students Forum at NIIT Shyambazar center, the occasion being the 60th year of India’s Independence. Scheduled to be started at 4 PM, the program was delayed due to the incomplete preparations. It finally began on 5:30 PM with a patriotic song, sung by a student. Other songs such as “Suno Gaur Se Duniya Walon”, “Vande Maataram” and a few Bengali songs followed up. A quiz on the topic “Independence” was also organized. Various questions pertaining to the events leading up-to India’s eventual freedom from the British empire were asked, most of which were Greek to me. The last item was an awesome display of drum mastery from Joy who also sang the song “Vande Maataram”. Finally, things wrapped up when the singers, the lone dancer whom I forgot to mention, members of the quiz winning team and the organizers were awarded prizes. At the very end, I was given a special prize for launching my site, where in, you incidentally are.

General

Microsoft.com is down

August 16th, 2007

I was testing a Winsock clone control when this mishap occurred. The “No Such Host Is Known” exception is certainly not you often see while testing on the Page Rank 10 pages, let alone Microsoft.com. Although, other sites (hotmail.com, msn.com) belonging to the corporation are running fine. I guess we will have to see how long this lasts and what caused it.

General

C# Tutorial : Lesson 11 – Polymorphism – Part II

August 11th, 2007
Operator Overloading

By default, out of the various C# operators, only the dot operator can be applied to user-defined types. Consider the following code snippet:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Program
{
    static void Main(string[] args)
    {
        Car Car1 = new Car();
        Car Car2 = new Car();
 
        Car Car3 = Car1 + Car2;
    }
}
 
class Car
{
    public int Speed;
    public string Name;
}

The compiler generates an error at line 8 saying that the operator + cannot be applied to objects of the Car class. How is the compiler supposed to know whether we want to add the speeds of two cars or concatenate their names. This is where the concept of Operator Overloading jumps in. Before we see how the + operator is prepared to work with the objects of the Car class, we need to understand how the concept works. Given below is a code snippet which accomplishes the addition in objects using a specialized method – Add().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
 
class Program
{
    static void Main(string[] args)
    {
        Car Car1 = new Car();
        Car Car2 = new Car();
        Car1.Speed = 30;
        Car2.Speed = 70;
 
        Car Car3 = Car.Add(Car1, Car2);
        Console.WriteLine("Car3's Speed = {0}", Car3.Speed);
        Console.Read();
    }
}
 
class Car
{
    public int Speed;
    public string Name;
 
    public static Car Add(Car Car1, Car Car2)
    {
        Car NewCar = new Car();
        NewCar.Speed = Car1.Speed + Car2.Speed;
        return NewCar;
    }
}

The Add method is declared as static so it can be invoked at the class level as Car.Add(). It takes two parameters of the type Car as inputs. It then creates a new object of the Car class, with a speed equal to the sum of the speeds of the input objects – Car1 and Car2. Finally, the new object is returned. In this way, the addition of two objects can be accomplished. The same concept is used in Operator Overloading, except for the fact that the specialized function in their case are of the format operator <operator name>.

Note: The logic inside the Add function is totally up to the the programmer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
 
class Program
{
    static void Main(string[] args)
    {
        Car Car1 = new Car();
        Car Car2 = new Car();
        Car1.Speed = 30;
        Car2.Speed = 70;
 
        Car Car3 = Car1 + Car2;
        Console.WriteLine("Car3's Speed = {0}", Car3.Speed);
        Console.Read();
    }
}
 
class Car
{
    public int Speed;
    public string Name;
 
    public static Car operator +(Car Car1, Car Car2)
    {
        Car NewCar = new Car();
        NewCar.Speed = Car1.Speed + Car2.Speed;
        return NewCar;
    }
}

As you can see, the + operator utilizes a function in the background to do its neat work. Although the concept in both the cases is same, using operators allows much greater ease. The code Car Car3 = Car1 + Car2; is much closer to the real world and its easier to type, isn’t it?

Here’s a table showing which operators can/cannot be overloaded in C#.

Operators Description
+ – ! ~ ++ – These being unary operators take one operand and can be overloaded.
+ – * / % Binary arithmetic operators take two operands and can be overloaded.
== != < > <= >= Comparison operators take two parameters and can also be overloaded.
&& || These need to be overloaded indirectly using the & and |
+= -= *= /= %= Arithmetic assignment operators cannot be overloaded.
= . ?: -> new is sizeof typeof These special operators cannot be overloaded.

Note: The overloading methods must be declared as public and static.

Overloading Prefix Unary Operators

Below is the logic to accomplish unary – operator overloading. This operator changes the sign of the relative speed and is used as: -<Object Name>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
 
class Program
{
    static void Main(string[] args)
    {
        Car Car1 = new Car();
        Car1.RelativeSpeed = 30;
        Car Car2 = -Car1;
    }
}
 
class Car
{
    public int RelativeSpeed;
    public string Name;
 
    public static Car operator -(Car CarObj)
    {
        Car NewCar = new Car();
        NewCar.RelativeSpeed = -CarObj.RelativeSpeed;
        return NewCar;
    }
}

Notice, that the overloaded function takes only a single parameter. If another parameter was specified, this function would overload the binary – operator. Structures being user-defined data types can also be overloaded in this fashion. The only difference is that structures being value types, can be implemented in an easier way.

1
2
3
4
5
6
7
8
9
10
11
struct Car
{
    public int RelativeSpeed;
    public string Name;
 
    public static Car operator -(Car CarObj)
    {
        CarObj.RelativeSpeed = -CarObj.RelativeSpeed;
        return CarObj;
    }
}

If the same implementation of the Operator – function was used in a class, both Car1 and Car2 would have the same RelativeSpeed of -30 after line 9. So, in the class implementation we have created a new object of the Car class.

Overloading Pre & Post Increment Operators

Unlike, C++, C# handles the Pre & Post Increment Operators by itself. Hence, we don’t need to overload them separately. Below is the implementation of the ++ operator in the Car structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
 
class Program
{
    static void Main(string[] args)
    {
        Car Car1 = new Car();
        Car1.RelativeSpeed = 30;
        Car Car2 = Car1++;
        Car Car3 = ++Car1;
        Console.WriteLine("Relative speed of Car1 = {0}, Car2 = {1} and Car3 = {2}"
        , Car1.RelativeSpeed, Car2.RelativeSpeed, Car3.RelativeSpeed);
        Console.Read();
    }
}
 
struct Car
{
    public int RelativeSpeed;
    public string Name;
 
    public static Car operator ++(Car CarObj)
    {
        CarObj.RelativeSpeed++;;
        return CarObj;
    }
}

At line 9, the overloaded function for the object Car1 is invoked. The operation being post increment, Car2 gets assigned the current value of Car1 which has a relative speed of 30. After this the RelativeSpeed is incremented by 1. So, Car1 has a relative speed of 31 now. In the next line, pre increment results in the value of Car1 to be incremented by 1 before the value is assigned to Car3. Car1′s RelativeSpeed is now equal to 32. This value gets copied in Car3. So, the output of the code is: Relative speed of Car1 = 32, Car2 = 30 and Car3 = 32.

If the same logic was used in the Car Class’s overloaded function, the output would be: Relative speed of Car1 = 32, Car2 = 32 and Car3 = 32. Why does this happen? As mentioned before, the class is a reference type. Hence, when we say Car1 = Car2, it implies that Car1 now points to the same object in the memory as does Car2. In structures, the same statement would be equivalent to Copy the value of Car2 in Car1.

Arithmetic Assignment Operators

Recall that, the Arithmetic Assignment operators ( += -= *= /= %= ) cannot be overloaded. This is because A += B is equivalent to A = A + B, A -= B is equivalent to A = A – B and so on. Once, you overload the binary + operator, you can perform the += operation on the objects of the class. Same is true for the rest of the Arithmetic operators.

Logical Operators

Overloading Logical Operators is a bit tricky. Firstly, to overload the && operator the function name should be operator & and for || operator it should be operator |. Secondly, before performing these boolean short-circuit operations, the true and false operators need to be defined.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
 
class Program
{
    static void Main(string[] args)
    {
        Car Car1 = new Car();
        Car Car2 = new Car();
        Car1.Running = true;
        Car2.Running = false;
 
        Car Car3 = Car1 && Car2;
        Console.WriteLine(Car3.Running);
        Console.Read();
    }
}
 
class Car
{
    public bool Running;
 
    public static Car operator &(Car Car1, Car Car2)
    {
        Car NewCar = new Car();
        NewCar.Running = Car1.Running && Car2.Running;
        return NewCar;
    }
 
    public static bool operator true(Car CarObj)
    {
        return true;
    }
 
    public static bool operator false(Car CarObj)
    {
        return false;
    }
}

C#

C# Tutorial : Lesson 10 – Polymorphism – Part I

August 9th, 2007

The term polymorphism means multiple forms. In the world of programming, it refers to the ability of an object to exist in multiple forms. Polymorphism is one one of the key concepts of Object Oriented Programming.

Why do we need polymorphism?

Polymorphism is there to increase the complexity of the already complex world of programming. Just kidding! By using functions, we break down the program into smaller logical parts that are easier to understand, implement and thereby maintain. In this sense, the function is the smallest self sufficient (ideally) logical block of a program. As you get to know more about the real world programming, you’ll find that even these small logical blocks are often very big and rather complex. Consider the following function which is used to calculate the area of a circle from the radius entered as integer.

1
2
3
4
5
double CalcArea(int Radius)
{
    double Area = Math.PI * Radius * Radius;
    return Area;
}

This function can only handle integers as input. What if the Radius was in double? The function would fail in such a case. We can create another function named CalcAreaDouble to handle the input in double.

1
2
3
4
5
double CalcAreaDouble(double Radius)
{
    double Area = Math.PI * Radius * Radius;
    return Area;
}

While, this works, there’s something wrong about this method. The name of a function should describe(in brief) what it does and not the type of values it returns or takes as input. Both these functions do the same job, Calculate Area. Hence, they should have the same name. Thanks to Polymorphism, we can declare two functions with the same name, inside the same class.

1
2
3
4
5
6
7
8
9
10
11
double CalcArea(int Radius)
{
    double Area = Math.PI * Radius * Radius;
    return Area;
}
 
double CalcArea(double Radius)
{
    double Area = Math.PI * Radius * Radius;
    return Area;
}

This is called function overloading. For two functions with the same name to co-exist, they must follow certain rules:-

  • The functions must differ in either the type, the sequence or the number of input parameters i.e they must have different function signatures. The CalcArea functions have different types of parameters.

    These two functions differ in the number of parameters:-

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    int SumOfNum(int Num1, int Num2)
    {
        return Num1 + Num2;
    }
     
    int SumOfNum(int Num1, int Num2, int Num3)
    {
        return Num1 + Num2 + Num3;
    }

    While, these have different sequence:-

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    float SumOfNum(int Num1, float Num2)
    {
        return Num1 + Num2;
    }
     
    float SumOfNum(float Num1, int Num2)
    {
        return Num1 + Num2;
    }
  • Return type has no influence on function overloading. Hence, these two functions cannot co-exist:-
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    double CalcArea(int Radius)
    {
        double Area = Math.PI * Radius * Radius;
        return Area;
    }
     
    int CalcArea(int Radius)
    {
        double Area = Math.PI * Radius * Radius;
        return Area;
    }
Static Polymorphism

Function overloading along with operator overloading which we shall look at in the next tutorial are ways of implementing static polymorphism. Static polymorphism inturn, is one of the two types of Polymorphism, the other being Dynamic polymorphism. Also called as early binding, this concept refers to an entity existing in different forms. Just like a teacher who carries on the role of a father, a husband, a comrade besides being a teacher, the functions exist in different forms, each specializing in handling one type of role. In static polymorphism, the response to a function is decided at compile time and hence it is also called early binding.

Overloading Constructors

Since constructors are also functions and can be parameterized(takes parameters as input), they can be overloaded. This allows flexibility while creating an object. Consider the Rectangle class declared in the System.Drawing namespace. It can be instantiated by either of the two methods.

Method 1: Using default constructor

In this method, the bounds of the rectangle object Rect are individually set.

1
2
3
4
5
Rectangle Rect = new Rectangle();
Rect.X = 10;
Rect.Y = 20;
Rect.Width = 30;
Rect.Height = 40;

Method 2: Using the Parametrized Constructor

Rectangle Rect = new Rectangle(10, 20, 30, 40);

Notice, how much easier this method is. The initialization in this case is handled by the constructor of the Rectangle class.

The rectangle class would have an implementation similar to this one:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Rectangle
{
    public int X;
    public int Y;
    public int Width;
    public int Height;
 
    Rectangle()
    {
        this.X = 0;
        this.Y = 0;
        this.Width = 0;
        this.Height = 0;
    }
 
    Rectangle(int x, int y, int width, int height)
    {
        this.X = x;
        this.Y = y;
        this.Width = width;
        this.Height = height;
    }
}

As you can see, the class has two overloaded constructors, one being the default constructor which takes no parameter and initializes the values of X, Y, Width and Height to 0. The other one initializes these values based on the inputs to it.

Note: This code is just to give you an idea of how the constructors are implemented. In actual fact, the rectangle class would be a lot more complex than this and would require further codes inside the constructors.

C#

Get the name of the currently executing Function/Method

August 8th, 2007

A StackFrame is created and pushed on the call stack for every function call made during the execution of a thread. The stack frame always includes MethodBase information, and optionally includes file name, line number, and column number information.

Source: MSDN

1
2
3
System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame();
System.Reflection.MethodBase mb = sf.GetMethod();
Console.WriteLine(mb.Name);

This code can be used to get the name of the current class.

string ClassName = this.GetType().Name;

Note: This code can only be called inside a non-static method/function. This is because a static method cannot put into use the instance retriever – this keyword.

Google

Default Return type of functions in C#

August 8th, 2007

There is NO default return type of functions in C#. If you don’t want to return any value, the function must be declared as void.

1
2
3
4
public void MyFunc()
{
    Console.Write("My Function");
}

Google

What statements can come with “continue” statement in C#

August 8th, 2007

The continue statement is used to pass the control to the next iteration of the loop it is in. So, it can only be used with loops.

for

1
2
3
4
5
6
7
8
for (int I = 0; I < 10; I++)
{
    if (I % 2 == 0)
    {
        continue;
    }
    Console.WriteLine(I);
}

foreach

1
2
3
4
5
6
7
8
9
int[] Numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
foreach (int Number in Numbers)
{
    if (Number % 2 == 0)
    {
        continue;
    }
    Console.WriteLine(Number);
}

while/do while

1
2
3
4
5
6
7
8
9
10
11
12
13
14
string Name = "";
do
{
    Console.Write("Enter a Name:");
    Name = Console.ReadLine();
    if (Name == "Parastratiosphecomyia stratiosphecomyioides")
    {
        // The animal with the longest Scientific Name???
        continue;
    }
    if(Name != "")
        Console.WriteLine("{0} is a good name", Name);
 
} while (Name != "");

Google

C# Tutorial : Lesson 09 – Constructors & Destructors

August 6th, 2007
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:-

1
2
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:-

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

Take a look at this code snippet.

1
2
3
4
5
6
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:-

1
2
3
4
5
6
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:-

1
2
3
4
class MyClass
{
    int MyNumber = 69;
}

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

1
2
3
4
5
6
7
8
9
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.

1
2
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.

1
2
3
4
5
6
7
8
9
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:-

1
2
3
4
5
6
7
8
9
public class MyClass
{
	static int MyNumber;
 
	static MyClass()
	{
		MyNumber = 69;
	}
}

A class can have these two constructors existing simultaneously:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    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.

C#