yyy a;
System.Console.WriteLine("hi");
a=new yyy();
} }
class yyy {
public void yyy() {
System.Console.WriteLine("yyy const");
} }
Compiler Error
a.cs(12,13): error CS0542: 'yyy': member names cannot be the same as their enclosing type Though we are returning void, we get the same error. This is because C# is very sure of what it says.
When you borrow from other people you do so on the pretext that you will return it. It's a different story that you never do! You rarely mean what you say. But when C# says that constructors cannot return values it means 'constructors cannot return values', not even 'void'. Remember, there is nothing that can accept the return values. Hence even void cannot be accepted. When a function returns a void we mean that it will return no value at all. For a constructor, the word return makes no sense at all.
Constructors with parameters
Just as we pass parameters to other functions, you can also pass parameters to constructors.
a.cs class zzz {
public static void Main() {
yyy a;
System.Console.WriteLine("hi");
a=new yyy("no");
} }
class yyy {
public yyy() {
System.Console.WriteLine("yyy const");
} }
Compiler Error
a.cs(7,3): error CS1501: No overload for method 'yyy' takes '1' arguments
You are already aware of the fact that parameters are passed to functions while calling them. Similarly, we will pass a parameter to the constructor yyy while creating the object a; because it is at this point that the constructor gets called.
Hence we are saying a=new yyy("no"). But on compiling this program you get an error. Here, the constructor is being called with a string 'no' as a parameter. But there is no variable in the constructor yyy to store the value 'no'. Add 'string s' in the constructor yyy and watch the error disappear.
a.cs
class zzz {
public static void Main() {
yyy a;
System.Console.WriteLine("hi");
a=new yyy("no");
} }
class yyy {
public yyy(string s) {
System.Console.WriteLine(s);
} } Output hi no
At first WriteLine will display 'hi'. Then we have a constructor yyy that takes a string 'no' as a parameter and accepts it in a variable s. Thus the moment the constructor yyy is called 'no' will be displayed. This is because the constructor yyy contains code that will print the value stored in the variable s. This is how constructors with parameters are called.
So far we created only one instance of the class yyy. In the following program we are creating two instances of the class yyy, 'a' and 'b'.
a.cs class zzz {
public static void Main() {
yyy a,b;
System.Console.WriteLine("hi");
a=new yyy("no");
b=new yyy();
} }
class yyy {
public yyy(string s) {
System.Console.WriteLine(s);
} }
Compiler Error
a.cs(8,3): error CS1501: No overload for method 'yyy' takes '0' arguments
While creating the object 'a' the constructor yyy is being passed a parameter 'hi'. In case of the object 'b' the constructor will be called without any parameters. But in our program we have code only for the constructor with parameters. Try executing this program and you will get an error saying that method yyy takes 0 arguments. This is because we do not have code for the constructor without parameters.
Let's understand the reason behind the error.
In our earlier programs, we did not specify a constructor. A relevant question here would be - how did the objects get created then, without the constructor being called? C# is a Good Samaritan, at that time it inserted a free constructor. It does so internally. On its own it inserts a constructor without any parameters, without any code into the class.
It looks like this-yyy() { }
Point to ponder - in the above program, when we didn't create a constructor without parameters why didn't we get one free? Remember we said C# is a Good Samaritan? And Good Samaritans help the needy. On seeing that we already have a constructor with parameters, C# looks the other way i.e., it takes the free one away. However, it is only when you have no constructor at all that C# melts its heart and gives you one free. Remember, even if it finds that you have even one constructor it will take away the free one. On the assumption that if you can provide one constructor, then with a little effort you can work towards providing the others too!
Now the only way to get rid of the error is to add the constructor yourself.
a.cs class zzz {
public static void Main() {
yyy a,b;
System.Console.WriteLine("hi");
a=new yyy("no");
b=new yyy();
} }
class yyy {
public yyy(string s) {
System.Console.WriteLine(s);
}
public yyy() {
System.Console.WriteLine("bad");
} } Output hi no bad
Here, initially, the two objects 'a' and 'b' are declared. In the next statement we have WriteLine, which will display 'hi'. We are then creating the object a. At this point the constructor with a string as a parameter is called. It will now display the value stored in the variable s which is 'no'. Thereafter, the object b is created. At this point the constructor without the parameters will be called. This constructor contains the WriteLine statement, which will print 'bad'. Here, we have as many constructors as we are calling and hence we do not get any errors.
So, essentially, a constructor is a special function that gets called when an object is created. It does not return any values, not even void. As far as parameters go it behaves like a normal function. If no constructors are specified you get one free, otherwise, you need as many constructors as you are calling.
Hence in the above case we cannot create an object as new yyy(100) as we do not have a constructor that accepts one int as a parameter.
Destructors
a.cs
public class zzz {
public static void Main() {
aa a = new aa();
} }
public class aa {
public aa() {
System.Console.WriteLine("Constructor ");
}
~aa() {
System.Console.WriteLine("Destructor");
} } Output Constructor Destructor
A destructor is a function with the same name as the name of a class but starting with the character ~. A constructor gets called at birth whereas a destructor gets called at death. In C# unlike other languages we do not know when an object dies as unlike James Bond, we do not have a license to kill. Thus even though the object a dies at the end of main, the destructor may not get called. Thus, in C# we cannot decide when the destructor gets called. This decision to call the destructor is made by a program within C# called the garbage collector.
The concept first gained currency with the advent of Java. In Java and C# we cannot remove our objects from memory. Thus it is for the garbage collector to decide when to call the destructor. The programming world was replete with errors mainly because programmers use new to allocate memory and then forget to deallocate it. This gave rise to a concept called memory leaks. On the flip side of the coin, programmers deallocated the memory, forgot about it and then accessed the object again. This generates an error occurring at random and difficult to pin down.
a.cs
public class zzz {
public static void Main() {
aa a = new aa();
} }
public class aa {
public aa() {
System.Console.WriteLine("Constructor");
}
public ~aa() {
System.Console.WriteLine("Destructor");
} }
Compiler Error
a.cs(14,9): error CS0106: The modifier 'public' is not valid for this item A destructor cannot have any modifiers like public preceding it.
a.cs
public class zzz {
public static void Main() {
aa a = new aa();
} }
public class aa {
public aa() {
System.Console.WriteLine("Constructor");
}
~aa(int i) {
System.Console.WriteLine("Destructor");
} }
Compiler Error
a.cs(14,5): error CS1026: ) expected a.cs(14,10): error CS1002: ; expected
a.cs(16,25): error CS1519: Invalid token '(' in class, struct, or interface member declaration a.cs(18,1): error CS1022: Type or namespace definition, or end-of-file expected
Constructors come in plenty with different numbers of arguments being passed to them. However, in the case of destructors, one size fits all, i.e., they come in only one size, with no parameters. Here we created a destructor with an int as a parameter thereby confusing the C# compiler completely.
C# lacks true synchronous or deterministic destructors i.e. destructors being called at a certain point in time. You cannot have your life depend on when a destructor would be called. The common grouse against C# is that unlike C++ it does not support true destructors.
a.cs
public class zzz {
public static void Main() {
aa a = new aa();
} }
public class aa {
public aa() {
System.Console.WriteLine("Constructor");
}
~aa() {
System.Console.WriteLine("Destructor");
}
protected override void Finalize() {
} }
Compiler Error
a.cs(18,25): error CS0111: Class 'aa' already defines a member called 'Finalize' with the same parameter types
We tried to create a function called Finalize. The compiler comes back and tells us that we already have a function called Finalize. This is weird as we have only one Finalize function. The reason for this error is that the compiler converts our destructor from ~aa to Finalize.
Arrays
All programming languages embrace the concept of arrays. An array is nothing but more of one entity i.e., a multiple of the same type. Simply put, when we have five books, we don't just say we have five books. Instead we say we have an array of five books. So, whenever you want to store multiple values of variables you store them in an array.
a.cs class zzz {
public static void Main() {
int[] a;
a= new int[3];
a[0]= 1; a[1]= 10; a[2]= 20;
System.Console.WriteLine(a[0]);
a[0]++;
System.Console.WriteLine(a[0]);
int i;
i=1;
System.Console.WriteLine(a[i]);
i=2;
System.Console.WriteLine(a[i]);
} } Output 1 2 10 20
Here 'a' is an array of ints. You declare arrays with a set of [] brackets. At this point it is not known how large the array will be. For that we have a=new int[3]; after new we have int meaning we want to create a variable of type int. We are putting 3 in the square brackets meaning we want to store 3 ints. This will create three ints a[0], a[1] and a[2]. They are then initialized to the values 1,10 and 20 respectively. To initialize an array variable we use the name, i.e. in this case a and follow it with the open and close []
brackets. Inside them we put the array number. The first variable is called a[0] , the second a[1] and so on. C# like most computer programming languages likes to start counting from 0 and not 1. Therefore, the last variable is a[2] and not a[3].
Since an array is many of the same type, they all have the same name. In our earlier example, even if we have many books, all the books will be called books. However, to refer to them individually you can say book1, book2, book3 etc.
WriteLine will display the value stored in a[0] which is 1. a[0]++ will increment the value stored in a[0]
by one. WriteLine will now display 2.
Thereafter, the variable i is declared as an int. It is then initialized to 1. Within the WriteLine function we have a[i]. It is not specifically stated which variable, instead we have said a[i]. There is no variable called a[i], but i has a value 1, so it is read as a[1]. Hence the value stored at a[1], which is 10, is displayed. The next WriteLine will display the value stored in a[2] as i is reinitialized to 2.
Doing this makes our program more generic. We haven't specifically stated which variable, we are letting a variable called i decide the name of the variable.
The next example demonstrates how arrays can be used within loops.
a.cs class zzz {
public static void Main() {
int[] a;
a= new int[3];
int i;
for( i=0; i<=2; i++) a[i]= i*10;
for( i=0; i<=2; i++)
System.Console.WriteLine(a[i]);
} } Output 0 10 20
The advantage of using arrays is that you can decide the name of the variable later and they can also be used in loops.
Here 'a' is an array of ints and i is a variable of type int. The array size is 3 i.e. it can store three ints. The first for loop is used to initialize the individual array items. Within the for loop, i is initialized to 0. The condition i<=2 indicates that the loop will execute thrice. So, when the control enters the for loop, for the first time i is 0. Looking at the right hand side of the expression, i*10 will now read as 0*10, which is 0. Hence, a[i] which is read as a[0] will be initialized to 0. i++ increments the value of i to 1. The second time a[i] will be read as a[1] which will be initialized to 10. Thereafter, a[i] will be read as a[2]
and initialized to 20 as i is now 2. Now i will be 3, so the condition evaluates to false and the loop terminates.
The second for loop displays the values stored in the array. This is similar to the above loop. Here we are displaying the values of the individual array items. As the for loop executes, WriteLine will read a[i]
as a[0], a[1] and a[2] in each case. As such, WriteLine displays 0,10,20. So, starting from the beginning and going upto the end, all the values stored in the array are displayed.
Arrays can also be used in a foreach statement. This is exemplified in the following program.
a.cs class zzz {
public static void Main() {
int[] a;
a= new int[3];
a[0]= 1; a[1]= 10; a[2]= 20;
foreach ( int i in a)
System.Console.WriteLine(i);
} } Output 1 10 20
The foreach statement lists the elements of the array. It executes a statement for each element of the array or collection. 'a' is an array of type int that can store three items. a[0], a[1] and a[2] are the elements or items of the array. They have been initialized to 1, 10 and 20 respectively. In the foreach statement we have ( int i in a ).
i is a variable of type int and a is the array created earlier. The first element of the array 'a' is a[0] and it holds the value 1. The foreach statement picks up this value and stores it in i. Since i now holds the value 1, WriteLine displays 1. The second element is a[1]. It picks up its value, which is 10 and stores it in i. Thus i now holds the value 10. WriteLine will now display 10. This goes on for all the elements of the array. Our array 'a' comprises three elements. Hence the foreach will execute the WriteLine statement for each of them and display their values 1,10 and 20. The variable i is only available in the foreach. The foreach makes it easier for us to run through all the members of any array.