Next Page
Structure, Enumeration, Garbage Collection and Nested Classes
If you are new to C# School
This is the 6th in a series of lessons of our C# School. The C# School is a kind of interactive learning platform where those who want to learn .NET with C# can find help and support. With one issue a week, describing some areas of C# Programming Language with the Microsoft .Net Platform, this is not the same traditional passive tutorial where the author only writes and the reader only reads. There will be exercise problems at the end of each issue, which the reader is expected to solve after reading the issue. The solution to these problems will be provided in the next issue for testing purposes. There is also a dedicated
message board attached with the school, where you can ask questions about the article, and the author will respond to your question within 2/3 days. You can send your suggestions, feedback or ideas on how these lessons can be improved to either the Author (
farazrasheed@acm.org) or the WEBMASTER (
info@programmersheaven.com).
For previous lessons:
Lesson Plan
Today's lesson consists of four major topics: Structures, Enumeration, Garbage Collector and Nested Classes. We will cover these one by one.
Structures (struct)
Structures, denoted in C# by the struct keyword, are lightweight objects. Structures are very similar to classes in C#, but with the following properties:
- A struct is useful for creating types that are used to hold data like Point, Rectangle, Color types.
- A struct is of value type, contrary to classes which are of reference type. This means that structures are allocated on the stack and passed to methods by value, that is, by making their copies.
- A struct may contain constructors (except for the no-argument constructor), fields, methods and properties just like in classes.
- Like all value types, structs can neither inherit another class, nor can they be inherited.
- A struct can implement interfaces.
- Like every other type in C#, a struct is also implicitly inherited from the System.Object class.
- Instances of a struct can be created with and without using the new keyword.
- Most of the .Net framework types like System.Int32 (for int), System.Double (for double), System.Boolean (for bool), System.Byte (for byte),... are implemented as a struct.
- When kept small in size, a struct is more efficiently used by the system than a class.
Defining struct
A struct is defined just like a class, using the struct keyword. Suppose, in a drawing application, we need a Point data type. Since this is a simple and lightweight type, we implement it as a struct.
struct Point
{
public double x;
public double y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
Here, we have declared a struct named Point. Point contains two public fields, x and y, that represent the location of a Point in the coordinate system. We provide a public constructor to initialize the location of the point and we also override the ToString() method from the Object class, so that our point can be printed easily using the Console.WriteLine() method in the Main() method.
Instantiating the struct
A struct can be instantiated in three ways:
- Using the new keyword and calling the default no-argument constructor.
- Using the new keyword and calling a custom or user defined constructor.
- Without using the new keyword.
As we mentioned earlier, we can not provide the no-argument constructor in a struct and if we try to do so, the compiler will generate an error. The compiler implicitly provides a default no-argument constructor for each struct which initializes the fields of a struct with their default values. In the following Main() method, we instantiate Point using the above mentioned three ways
class Test
{
static void Main()
{
Point pt = new Point();
Point pt1 = new Point(15, 20);
Point pt2; // instantiation without using
// the new keyword
pt2.x = 6;
pt2.y = 3;
Console.WriteLine("pt = {0}", pt);
Console.WriteLine("pt1 = {0}", pt1);
Console.WriteLine("pt2 = {0}", pt2);
}
}
The output of the program is:
pt = (0, 0)
pt1 = (15, 20)
pt2 = (6, 3)
Press any key to continue
Here, we have instantiated three Point objects. The first one (referenced by pt) is instantiated using new and a default no-argument constructor (implemented by the compiler) which zeroed all the fields. Thus, the first Point (pt) is printed as (0, 0). The second one (referenced by pt1) is instantiated using the new keyword and a custom (double, double) constructor. The point (pt1) is initialized with the specified value and thus printed as (15, 20) on the console. The third object (referenced by pt2) is created without using the new keyword (like implicit data types). Note that we first initialized all the fields of pt2 before using it (in the Console.WriteLine() method). Before using a struct created without the new keyword, all its fields must be explicitly initialized. Hence, the Point (pt2) printed out as (6, 3). Note that we wrote:
Console.WriteLine("pt = {0}", pt);
instead of:
Console.WriteLine("pt = {0}", pt.ToString());
Console.WriteLine() expects a string, but since we overrided the ToString() method in our Point struct, the compiler will implicitly call the ToString() method when it expects a string in the Console.WriteLine() method.
Next Page