An Intro to Constructors in C#
This is an article on Constructors in C#, for the beginner level programmers. It covers simple constructors, constructors overloading, behaviour of constructors in inheritance, constructor chaining and static constructors. At the end, it contains the general FAQs about constructors.
Introduction
Broadly speaking, a constructor is a method in the class which gets executed when its object is created. Usually, we put the initialization code in the constructor. Writing a constructor in the class is damn simple, have a look at the following sample:
Collapse | Copy Code
public class mySampleClass
{
public mySampleClass()
{
// This is the constructor method.
}
// rest of the class members goes here.
}
When the object of this class is instantiated, this constructor will be executed. Something like this:
Collapse | Copy Code
mySampleClass obj = new mySampleClass()
// At this time the code in the constructor will // be executed
Constructor Overloading
C# supports overloading of constructors, that means, we can have constructors with different sets of parameters. So, our class can be like this:
Collapse | Copy Code
public class mySampleClass
{
public mySampleClass()
{
// This is the no parameter constructor method.
// First Constructor
}
public mySampleClass(int Age)
{
// This is the constructor with one parameter.
// Second Constructor
}
public mySampleClass(int Age, string Name)
{
// This is the constructor with two parameters.
// Third Constructor
}
// rest of the class members goes here.
}
Well, note here that call to the constructor now depends on the way you instantiate the object. For example:
Collapse | Copy Code
mySampleClass obj = new mySampleClass()
// At this time the code of no parameter
// constructor (First Constructor)will be executed
mySampleClass obj = new mySampleClass(12)
// At this time the code of one parameter
// constructor(Second Constructor)will be
// executed.
The call to the constructors is completely governed by the rules of overloading here.
Calling Constructor from another Constructor
You can always make a call to one constructor from within another. Say, for example:
Collapse | Copy Code
public class mySampleClass
{
public mySampleClass(): this(10)
{
// This is the no parameter constructor method.
// First Constructor
}
public mySampleClass(int Age)
{
// This is the constructor with one parameter.
// Second Constructor
}
}
Very first of all, let us see what is this syntax:
Collapse | Copy Code
public mySampleClass(): this(10)
Here, this refers to same class, so when we say this(10), we actually mean execute the public mySampleClass(int Age) method. The above way of calling the method is called initializer. We can have at the most one initializer in this way in the method.
Another thing which we must know is the execution sequence i.e., which method will be executed when. Here, if I instantiate the object as:
Collapse | Copy Code
mySampleClass obj = new mySampleClass()
Then the code of public mySampleClass(int Age) will be executed before the code of mySampleClass(). So, practically the definition of the method:
Collapse | Copy Code
public mySampleClass(): this(10)
{
// This is the no parameter constructor method.
// First Constructor
}
is equivalent to:
Collapse | Copy Code
public mySampleClass()
{
mySampleClass(10)
// This is the no parameter constructor method.
// First Constructor
}
Note: Above (just above this line) code is mentioned there for pure analogy and will not compile. The intention here is to tell the flow of execution if initializers are used.
We cannot make an explicit call to the constructors in C#, treating them as if any simple method, for example: statement mySampleClass(10) in the above code will not work. The only way you can call one constructor from another is through initializers.
For the VB.NET programmers: you can make the call to another constructor of the same class by the syntax Me.New(param list), but it should be the first line of your calling constructor method. So ultimately, the code of the called constructor runs prior to the code of the calling constructor, which is same as initializers here.
Note that only this and base (we will see it further) keywords are allowed in initializers, other method calls will raise an error.
This is sometimes called Constructor chaining.
Huff… Simple thing made tough, but this is how it is. Anyway, let us proceed further.
Behavior of Constructors in Inheritance
Let us first create the inherited class.
Collapse | Copy Code
public class myBaseClass
{
public myBaseClass()
{
// Code for First Base class Constructor
}
public myBaseClass(int Age)
{
// Code for Second Base class Constructor
}
// Other class members goes here
}
public class myDerivedClass : myBaseClass
// Note that I am inheriting the class here.
{
public myDerivedClass()
{
// Code for the First myDerivedClass Constructor.
}
public myDerivedClass(int Age):base(Age)
{
// Code for the Second myDerivedClass Constructor.
}
// Other class members goes here
}
Now, what will be the execution sequence here:
If I create the object of the derived class as:
Collapse | Copy Code
myDerivedClass obj = new myDerivedClass()
Then the sequence of execution will be:
Note one thing here: we are not making any explicit call to the constructor of base class neither by initializer nor by the base keyword, but it is still executing. This is the normal behavior of the constructor.
If I create an object of the derived class as:
Collapse | Copy Code
myDerivedClass obj = new myDerivedClass(15)
Then the sequence of execution will be:
Also note the usage of Age variable in the syntax: public myDerivedClass(int Age):base(Age). [Understanding it is left to the reader].
Private Constructors
Private constructors, the constructors with the "private" access modifier, are a bit special case. It is because we can neither create the object of the class, nor can we inherit the class with only private constructors. But yes, we can have the set of public constructors along with the private constructors in the class and the public constructors can access the private constructors from within the class through constructor chaining.
Say for example, my class is something like this :
Collapse | Copy Code
public class myClass
{
private MyClass()
{
Console.WriteLine("This is no parameter Constructor");
}
public MyClass(int var):this()
{
Console.WriteLine("This is one parameter Constructor");
}
// Other class methods goes here
}
Then we can create the object of this class by the statement:
Collapse | Copy Code
MyClass obj = new MyClass(10);
The above statement will work fine, but the statement
Collapse | Copy Code
MyClass obj = new MyClass();
will raise an error : 'Constructors.MyClass.MyClass()' is inaccessible due to its protection level
It is possible to have the class with only the private constructors. But yes as I said, such class can neither be instantiated nor be inherited. If we try to inherit the class with only private constructors then we will get the same error as above. Also recall, once you provide constructor from your side the compiler will not add the no-parameter public constructor to your class.
Well, one of the usage scenarios of such class could be – when you have only static members in the class and you don't need to instantiate it.
Phew… lost… Anything left in constructors? Yes, Static Constructors. Ha!! Now, what are they? Let us see..
Static Constructors
This is a new concept introduced in C#. By new here, I mean that it was not available for the C++ developers. This is a special constructor and gets called before the first object is created of the class. The time of execution cannot be determined, but it is definitely before the first object creation - could be at the time of loading the assembly.
The syntax of writing the static constructors is also damn simple. Here it is:
Collapse | Copy Code
public class myClass
{
static myClass()
{
// Initialization code goes here.
// Can only access static members here.
}
// Other class methods goes here
}
Notes for Static Constructors:
Firstly, the call to the static method is made by the CLR and not by the object, so we do not need to have the access modifier to it.
Secondly, it is going to be called by CLR, who can pass the parameters to it, if required. So we cannot have parameterized static constructor.
Thirdly, non-static members in the class are specific to the object instance. So static constructor, if allowed to work on non-static members, will reflect the changes in all the object instances, which is impractical. So static constructor can access only static members of the class.
Fourthly, overloading needs the two methods to be different in terms of methods definition, which you cannot do with Static Constructors, so you can have at the most one static constructor in the class.
Now, one question raises here, can we have two constructors as:
Collapse | Copy Code
public class myClass
{
static myClass()
{
// Initialization code goes here.
// Can only access static members here.
}
public myClass()
{
// Code for the First myDerivedClass Constructor.
}
// Other class methods goes here
}
This is perfectly valid, though doesn't seem to be in accordance with overloading concepts. But why? Because the time of execution of the two methods are different. One is at the time of loading the assembly and one is at the time of object creation.
Constructors FAQs
Bottom of Form
ENCApsulation in c#
Introduction
In the OOProgramming will give the impression very unnatural to a programmer with lot of procedural programming experience. In OOP encapsulation is the main pace. Encapsulation is a procedure of covering up or hiding up of data and functions into a single unit which is called as a class. An encapsulated object is often called as an abstract data type.
Background
The need of encapsulation is to prevent the code from accidental corruption due to minor errors that we are all making. In OOP data is treated as a critical element in the application development & data is packed closely to the functions which operate on it and protects from accidental modification from other outside functions.
Encapsulation provides a way to protect data from accidental corruption. Rather than defining the data in the form of public we can also declare those fields as private. The private data are manipulated indirectly by two methods. The first method is using a pair of conventional accessor and mutator methods. Another method is using a named property, get and set.
Encapsulation using Accessors & Mutators
Lets see a small example to manipulate the data in the class:
Collapse | Copy Code
class Employee
{
private int empID;
private string empName;
private double empSal;
// Accessor
public int getEmpID()
{
return empID;
}
public string getEmpName()
{
return empName;
}
public double getEmpSal()
{
return empSal;
}
// Mutator
public void setEmpID(int eid)
{
empID = eid;
}
public void setEmpName(string ename)
{
empName = ename;
}
public void setEmpSal(double esal)
{
empSal = esal;
}
}
Like the above way we can protect the private data from outside world. Here we use two separate methods to assign and get the required data.
s see a small example to manipulate the data in the class:
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee();
e.setEmpID(1001);
e.setEmpName("Smith");
e.setEmpSal(25000.75);
Console.WriteLine("The Employee ID:" + e.getEmpID());
Console.WriteLine("The Employee Name:" + e.getEmpName());
Console.WriteLine("The Employee Salary:" + e.getEmpSal());
Console.ReadKey();
}
}
In the above example we can not access the private data empId, empName, empSal from any object instance. We can manipulate the data only using those two methods accessor and mutator.
Encapsulation Using Properties
Properties are the new feature introduced in C#. Properties in C# helps in protect a field in a class by reading the writing to it. Now let's see a small example on properties,
Collapse | Copy Code
class Employee
{
private int empID;
public int EmpID
{
get { return empID; }
set { empID = value; }
}
private string empName;
public string EmpName
{
get { return empName; }
set { empName = value; }
}
private double empSal;
public double EmpSal
{
get { return empSal; }
set { empSal = value; }
}
}
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee();
e.EmpID = 1001;
e.EmpName = "Smith";
e.EmpSal = 25000.75;
Console.WriteLine("The Employee ID: " + e.EmpID + " Name:" + e.EmpName + " Salary:" + e.EmpSal);
Console.ReadKey();
}
}
From the above example we see the usage of encapsulation by using the properties. The property has two properties get and set. The get is nothing but it returns a value of the some property field. The set will sets the value of the some property field with the contents of "value". Properties can be made read-only too. This can be done by the get property implementation.
Read Only Property:
In the below example we see how to implement a read only property. The class Employee has a EmpID, EmpName, EmpSal properties that only implements a get accessor. It leaves out the set accessor. This particular class creates a new object named e. The instantiation of the e object used the constructor of the Employee class that takes the int, string, double parameters. Since the below program is read-only we can not set the valuer to the field EmpID, EmpName, EmpSal and we only read or get the value of the data from the field. Properties can be made also write only. This can be implemented only a set accessor in the property implementation.
Collapse | Copy Code
class Employee
{
private int empID;
private string empName;
private double empSal;
public Employee(int eid, string ename, double esal)
{
empID = eid;
empName = ename;
empSal = esal;
}
public int EmpID
{
get { return empID; }
}
public string EmpName
{
get { return empName; }
}
public double EmpSal
{
get { return empSal; }
}
}
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee(1001, "Smith", 25000.75);
Console.WriteLine("The Employee ID: " + e.EmpID + " Name:" + e.EmpName + " Salary:" + e.EmpSal);
Console.ReadKey();
}
}
Write Only Property:
Collapse | Copy Code
class Employee
{
private int empID;
private string empName;
private double empSal;
public int EmpID
{
set
{
empID = value;
Console.WriteLine("The Employee ID:" + empID);
}
}
public string EmpName
{
set
{
empName = value;
Console.WriteLine("The Employee Name:" + empName);
}
}
public double EmpSal
{
set
{
empSal = value;
Console.WriteLine("The Employee Salary:" + empSal);
}
}
}
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee();
e.EmpID = 1001;
e.EmpName = "Smith";
e.EmpSal = 25000.75;
}
}
In the above example we see how to implement a write only property. The class Employee has a EmpID, EmpName, EmpSal properties that only implements a set accessor. It leaves out the get accessor. The set method is varied a little by it prints value of EmpID, EmpName, EmpSal after it is been assigned.
Conclusion
The Encapsulation is the first important step towards the object oriented programming. This artical will give you a little bit information about the encapsulation. Using the accessor & mutator methods we can encapsulate the data. Another approach by using the properties like get and set. The benefits of properties is that the users of your objects are able to manipulate internal data point using a single named item.
Interfaces in C # provide a way to achieve runtime polymorphism. Using interfaces we can invoke functions from different classes through the same Interface reference, whereas using virtual functions we can invoke functions from different classes in the same inheritance hierarchy through the same reference. Before things start getting difficult let me start using simple and short examples to explain the concept of interfaces. Here's a short example that shows you what an interface looks like.
class Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
}
Hello Interfaces
The above program compiles and runs successfully to produce the desired output. The above program consists of a class Demo and within it an entry point function Main() that prints Hello Interfaces. The above program also defines an interface abc. Interface abc is empty at this point of time. Let's add some elements to this interface.
class Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
int x;
}
P2.cs(11,3): error CS0525: Interfaces cannot contain fields
Error! Interfaces in C# cannot contain fields i.e variables. The above program declared an integer variable x in the interface abc. And that's what hit the C# compiler badly.
class Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
void xyz()
{
System.Console.WriteLine("In xyz");
}
}
P3.cs(11,8): error CS0531: 'abc.xyz()': interface members cannot have a
definition
This time over we included a function xyz() inside the interface found that this too hurt the C# compiler. It told us loudly that interface members cannot have a defination. Does this mean that if we just have a function declaration inside the interface abc that is fine with the C# compiler? Let's find it out.
class Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
void xyz();
}
Hello Interfaces
The above program compiles and runs successfully to produce the desired output. Finally we made the compiler happy. Interfaces in C# can only contain function declarations. Now let us see interfaces in action.
Interfaces are contracts that a class implements in its own way. This means an interface will contain function prototypes and a class that marries this interface will have to take the responsibility of defining the functions whose prototypes are declared by the marrying interface.
So its time to perform the marriage between our groom class Demo and the bride interface abc.
class Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
void xyz();
}
P4.cs(1,7): error CS0535: 'Demo' does not implement interface member
'abc.xyz()'
P4.cs(11,8): (Location of symbol related to previous error)
Well, in the above program class Demo did marry the interface abc through the line class demo : abc but as usual there's a small misunderstanding between the newlyweds. Class Demo needs to take the responsibility of defining the functions whose prototypes are declared by the marrying interface abc. Since class Demo in the above program has not been implemented i.e. defined the function xyz whose prototype is declared by the marrying interface abc we get an error in the above program. To fix this issue, the class Demo has to take the responsiility of defining the function xyz whose prototype is declared by the marrying interface abc. And that is what you get to see in the following program.
class Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
void xyz()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
a.cs(1,7): error CS0536: 'Demo' does not implement interface member
'abc.xyz()'.'Demo.xyz()' is either static, not public,
or has the wrong return type.
a.cs(16,8): (Location of symbol related to previous error)
a.cs(7,8): (Location of symbol related to previous error)
Error again! It's not enough for the class Demo to implement the function xyz. It has to impress the bride interface abc by declaring its implementation of xyz as public. And that's what is done by the following program.
class Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
xyz();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
Hello Interfaces
In xyz
Bingo! The above program compiles and runs successfully to produce the desired output. As mentioned earlier using interfaces we can invoke functions from different classes using the same interface reference. For this, we need to have different classes to implement the same interface. In the above program our class Demo is implementing the interface abc. Let's have another class Sample that implements the interface abc.
class Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
refDemo.xyz();
Sample refSample = new Sample();
refSample.xyz();
}
public void xyz()
{
System.Console.WriteLine("In Demo :: xyz");
}
}
interface abc
{
void xyz();
}
class Sample : abc
{
public void xyz()
{
System.Console.WriteLine("In Sample :: xyz");
}
}
In Demo :: xyz
In Sample :: xyz
The above program compiles and runs successfully to produce the desired output. refDemo is a reference to the object of class Demo. refSample is a reference to the object of class Sample. Both the classes implement the interface abc and hence define their own implementation of the function xyz(). From within the entry point function Main() xyz() of the respective classes Demo and Sample are invoked through references refDemo and refSample.
Now that we have two different classes implementing the same interface its time to show you how to invoke functions from different classes using the same interface reference.
class Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
abc refabc = new Demo();
refabc.xyz();
abc refabc = new Sample();
refabc.xyz();
}
public void xyz()
{
System.Console.WriteLine("In Demo :: xyz");
}
}
interface abc
{
void xyz();
}
class Sample : abc
{
public void xyz()
{
System.Console.WriteLine("In Sample :: xyz");
}
}
In Demo :: xyz
In Sample :: xyz
The above program compiles and runs successfully to produce the desired output. Inside Main() we have an interface reference refabc of type interface abc. Reference of object of class Demo is stored in refabc and xyz() of class Demo is invoked using refabc. Next, the reference of object of class Sample is stored in refabc and xyz() of class Sample is invoked using refabc. Thus, we were able to invoke xyz() that belongs to different classes Demo and Sample via a common interface reference refabc.
The following program uses a for loop to invoke the functions of different classes Demo and Sample that implement the same interface "interface abc" using a single interface reference refabc whose type matches the interface "interface abc" which the classes impliment.
class Demo : abc
{
public static void Main()
{
abc [] refabc = {new Demo(), new Sample()} ;
for (int i = 0; i<= 1; i++)
refabc[i].xyz();
}
public void xyz()
{
System.Console.WriteLine("In Demo :: xyz");
}
}
interface abc
{
void xyz();
}
class Sample : abc
{
public void xyz()
{
System.Console.WriteLine("In Sample :: xyz");
}
}
In Demo :: xyz
In Sample :: xyz
The above program compiles and runs successfully to produce the desired output. refabc is an array of type interface abc. It stores the references to objects of classes Demo and Sample. In the for loop, using the array refabc, we are invoking the function xyz() of class Demo and Sample. A class can impliment as many interfaces as it wants. Take the following program.
class Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
abc refabc = new Demo();
refabc.xyz();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void pqr();
}
Hello Interfaces
In xyz
The above program compiles and runs successfully to produce a desired output. Class Demo implements interface abc and thereby function xyz(). Class Demo also impliments interface def and thereby function pqr(). ref abc which is a variable of type Interface abc, refers to object of class Demo. Next xyz() of Demo is invoked via refabc as refabc is a variable of type Interface abc which contains the prototype for function xyz().
class Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
abc refabc = new Demo();
refabc.xyz();
refabc.pqr();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void pqr();
}
P11.cs(9,5): error CS0117: 'abc' does not contain a definition for 'pqr'
Error! An attempt to invoke pqr() of Demo via refabc fails as refabc is a variable of type Interface abc which contains the prototype for function xyz() and NOT pqr(). One can invoke pqr() of Demo via a reference variable of type Interface def as the interface def contains the prototype for function pqr(). And that's what is done by the following program.
class Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.pqr();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def
{
void pqr();
}
Hello Interfaces
In xyz
In pqr
The above program compiles and runs successfully to produce a desired output. Class Demo impliments the interfaces abc and def. An object of class Demo is created and its reference is stored in refDemo. refabc which is a variable of type Interface abc, refers to the object of class Demo. Next xyz() of Demo is invoked via refabc as refabc is a variable of type Interface abc which contains the prototype for function xyz(). Similarly, refdef which is a variable of type Interface def, refers to object of class Demo. Next pqr() of Demo is invoked via refdef as refdef is a variable of type Interface def which contains the prototype for function pqr().
class Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.xyz();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void xyz();
}
Hello Interfaces
In xyz
In xyz
The above program compiles and runs successfully to produce a desired output. Both the interfaces abc and def declare the prototypes for function xyz(). Class Demo implements interfaces abc as well as def and defines the function xyz() as well. Thus we can invoke the function xyz() through either of the interface reference variables (refabc or refdef) after storing the reference to the object of class Demo in refabc or refdef. This poses a question, how can we have an implementation of xyz that is specific to interface abc and implementation of xyz that is specific to def inside class Demo? Well, for this we need to use the fully qualified names as in the following program.
class Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.xyz();
}
public void abc.xyz()
{
System.Console.WriteLine("In abc.xyz");
}
public void def.xyz()
{
System.Console.WriteLine("In def.xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void xyz();
}
a.cs(13,15): error CS0106: The modifier 'public' is not valid for this item
a.cs(18,15): error CS0106: The modifier 'public' is not valid for this item
Bummer! We used the fully qualified name and we got an error. That's because when we use fully qualified names for functions whose prototypes are a part of interfaces, the compiler doesn't need decorators like public. So we decided to remove the access specifier public from the above program.
class Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.xyz();
}
void abc.xyz()
{
System.Console.WriteLine("In abc.xyz");
}
void def.xyz()
{
System.Console.WriteLine("In def.xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void xyz();
}
Hello Interfaces
In abc.xyz
In def.xyz
The above program compiles and runs successfully to produce a desired output. A fully qualified naming system allows us to define interfaces having same function prototypes. In the above example, interface abc and def contain the same function prototypes for function xyz(). Class Demo impliments both the interfaces. Using fully qualified names, it defines implementation of xyz that is specific to interface abc and implementation of xyz that is specific to interface def.
class Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
def refdef = refDemo;
refdef.xyz();
refdef.pqr();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
Hello Interfaces
In xyz
In pqr
The above program compiles and runs successfully to produce a desired output. Interfaces support inheritance. Interface def inherits prototypes from interface abc. Class Demo implements the interface def. Interface variable refdef stores the reference to object of class Demo. Functions xyz() and pqr() of class Demo are invoked through interface reference variable refdef.
What do you think of the fully qualified names of xyz() and pqr() would be after interface def inherits from interface abc.
class Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
def refdef = refDemo;
refdef.xyz();
refdef.pqr();
}
void def.xyz()
{
System.Console.WriteLine("In xyz");
}
void def.pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
P17.cs(12,8): error CS0539: 'def.xyz' in explicit interface declaration is
not a member of interface
P17.cs(29,11): (Location of symbol related to previous error)
P17.cs(1,7): error CS0535: 'Demo' does not implement interface member
'abc.xyz()'
P17.cs(26,8): (Location of symbol related to previous error)
Bummer! The prototype of function xyz is an original member of interface abc. Thus, even if interface def inherits from the interface abc, the fully qualified name of the function xyz() remains as abc.xyz and not def.xyz as done in the above program. In fact, we got a compiler error. This can be fixed by using the correct fully qualified name of function xyz() as shown in the following program.
class Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
def refdef = refDemo;
refdef.xyz();
refdef.pqr();
}
void abc.xyz()
{
System.Console.WriteLine("In xyz");
}
void def.pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
Hello Interfaces
In xyz
In pqr
The above program compiles and runs successfully to produce a desired output. But there are some pitfalls when using the fully qualified function names.
class Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
refDemo.xyz();
refDemo.pqr();
}
void abc.xyz()
{
System.Console.WriteLine("In xyz");
}
void def.pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
P19.cs(7,5): error CS0117: 'Demo' does not contain a definition for 'xyz'
P19.cs(8,5): error CS0117: 'Demo' does not contain a definition for 'pqr'
The above program fails to clear the compilation hurdle. refDemo refers to an object of class Demo. We are invoking xyz() using refDemo(). For C#, xyz() and ddd.xyz() are two different things. It knows that abc.xyz() exists. It also knows that just xyz() is nowhere in the class. That's why we get an error which says Class Demo does not contain a definition of xyz(). For C#, abc.xyz() can be invoked by an interface reference of type abc only. Similarly, def.pqr() can be invoked by an interface reference of type def only.
Bottom of Form
Introduction to inheritance, polymorphism in C#
Introduction
This little article is intended for rank .NET newbies who are making their first attempts at C# programming. I assume that they have done some elementary C++ programming and know what classes and member functions are. Using a few simple code snippets we'll see how C# supports inheritance and polymorphism.
Inheritance & Polymorphism
When you derive a class from a base class, the derived class will inherit all members of the base class except constructors, though whether the derived class would be able to access those members would depend upon the accessibility of those members in the base class. C# gives us polymorphism through inheritance. Inheritance-based polymorphism allows us to define methods in a base class and override them with derived class implementations. Thus if you have a base class object that might be holding one of several derived class objects, polymorphism when properly used allows you to call a method that will work differently according to the type of derived class the object belongs to.
Consider the following class which we'll use as a base class.
Collapse | Copy Code
class Animal
{
public Animal()
{
Console.WriteLine("Animal constructor");
}
public void Greet()
{
Console.WriteLine("Animal says Hello");
}
public void Talk()
{
Console.WriteLine("Animal talk");
}
public virtual void Sing()
{
Console.WriteLine("Animal song");
}
};
Now see how we derive another class from this base class.
Collapse | Copy Code
class Dog : Animal
{
public Dog()
{
Console.WriteLine("Dog constructor");
}
public new void Talk()
{
Console.WriteLine("Dog talk");
}
public override void Sing()
{
Console.WriteLine("Dog song");
}
};
Now try this code out.
Collapse | Copy Code
Animal a1 = new Animal();
a1.Talk();
a1.Sing();
a1.Greet();
//Output
Animal constructor
Animal talk
Animal song
Animal says Hello
Okay, that came out just as expected. Now try this code out.
Collapse | Copy Code
Animal a2 = new Dog();
a2.Talk();
a2.Sing();
a2.Greet();
//Output
Animal constructor
Dog constructor
Animal talk
Dog song
Animal says Hello
We have an object of type Animal, but it references an object of type Dog. Thus you can see the base class constructor getting called first followed by the derived class constructor. Now we call Talk() and find that the method that's executed is the base class method. That's not surprising when you consider that the object was declared to be of the base type which in our case is Animal. Now when we call Sing(), we find that the derived class method has got called. This is because in the base class the method is prototyped as public virtual void Sing() and in the derived class we have overridden it by using public override void Sing(). In C#, we need to explicitly use the override keyword as opposed to C++ where we didn't have to do that. And finally when we call Greet() the base class method gets called and this is not confusing at all specially since the derived class has not even implemented the method.
Now try the following code out.
Collapse | Copy Code
Dog d1 = new Dog();
d1.Talk();
d1.Sing();
d1.Greet();
//Output
Animal constructor
Dog constructor
Dog talk
Dog song
Animal says Hello
Okay, here everything came out as expected. No rude surprises there. The fact that we could invoke the Greet() method is proof of inheritance in C#, not that anyone had any doubts to begin with I guess. Now take a look at this new class we'll be using as a base class for some other classes.
Collapse | Copy Code
class Color
{
public virtual void Fill()
{
Console.WriteLine("Fill me up with color");
}
public void Fill(string s)
{
Console.WriteLine("Fill me up with {0}",s);
}
};
Now run this code out.
Collapse | Copy Code
Color c1 = new Color();
c1.Fill();
c1.Fill("red");
//Output
Fill me up with color
Fill me up with red
Okay, that went fine, I'd say. Now let's derive a class from this class.
Collapse | Copy Code
class Green : Color
{
public override void Fill()
{
Console.WriteLine("Fill me up with green");
}
};
Now let's try this code out.
Collapse | Copy Code
Green g1 = new Green();
g1.Fill();
g1.Fill("violet");
//Output
Fill me up with green
Fill me up with violet
Well, that went fine too. Thus if you have overloaded methods, you can mark some of them as virtual and override them in the derived class. It's not required that you have to override all the overloads. Now I want to demonstrate some stuff on overloaded constructors. For that we'll use the following base class.
Collapse | Copy Code
class Software
{
public Software()
{
m_x = 100;
}
public Software(int y)
{
m_x = y;
}
protected int m_x;
};
Now we'll derive a class from the above class.
Collapse | Copy Code
class MicrosoftSoftware : Software
{
public MicrosoftSoftware()
{
Console.WriteLine(m_x);
}
};
Now try this code out
Collapse | Copy Code
MicrosoftSoftware m1 = new MicrosoftSoftware();
//MicrosoftSoftware m2 = new MicrosoftSoftware(300); //won't compile
//Output
100
The base class had two overloaded constructors. One that took zero arguments and one that took an int. In the derived class we only have the zero argument constructor. Constructors are not inherited by derived classes. Thus we cannot instantiate a derived class object using the constructor that takes an int as parameter. As you will deduce from the output we got, the base class constructor that called was the default parameter-less constructor. Now take a look at this second derived class.
Collapse | Copy Code
class DundasSoftware : Software
{
//Here I am telling the compiler which
//overload of the base constructor to call
public DundasSoftware(int y) : base(y)
{
Console.WriteLine(m_x);
}
//Here we are telling the compiler to first
//call the other overload of the constructor
public DundasSoftware(string s, int f) : this(f)
{
Console.WriteLine(s);
}
};
Here we have two constructors, one that takes an int and one that takes a string and an int. Now lets try some code out.
Collapse | Copy Code
DundasSoftware du1 = new DundasSoftware(50);
//Output
50
DundasSoftware du2 = new DundasSoftware("test",75);
//Output
75
test
There, now that you've seen how it came out, things are a lot clearer I bet. You can use the this and base access keywords on other methods too, and not just on constructors.
Conclusion
This article does not discuss interfaces. At least not in it's current version. I'll probably add the usage of interfaces in the next update. But for now, I recommend that you read up on interfaces from elsewhere.
Operator Overloading
Let’s explain what operator overloading is all about with an example of a class that represents a date. Would it not be great if we could subtract two date objects and be returned an int representing the number of days elapsing between the two dates. We would like to use the good old subtraction operator – like we do when subtracting numbers. Also we would like the > operator to compare two date objects and tell us which one is larger. The + operator could add a number to a date resulting in a new date object.
Thus, operator overloading lets us redefine the existing operators so that they work with classes/objects we create like yyy. We have not yet instructed C# on how to use the trusty old + operator with two yyy objects. Though C# knows how to use the + to add two numbers, it does not know how to add two yyy’s.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
}
Compiler Error
a.cs(8,5): error CS0019: Operator ‘+’ cannot be applied to operands of type ‘yyy’ and ‘yyy’
We have created a simple class yyy which has one instance variable i which will distinguish different instances of yyy from each other. The constructor with an int as a parameter initializes i. We have tried to add two objects that look like yyy which does not go down well with C# and it objects to it.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public yyy operator + ( yyy x , yyy y)
{
}
}
Compiler Error
a.cs(18,12): error CS0558: User-defined operators ‘yyy.operator +(yyy, yyy)’ must be declared static and public
Error messages can be at times helpful. Our operator + is public but not static. C# demands that all operator overloads be static.
a.cs
public class zzz
{
public static void Main() {
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
System.Console.WriteLine(c.i);
}
}
public class yyy
{
public int i;
public yyy( int j) {
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Output
operator + 10 5
15
The word operator as the name of a function, is legal and the only way to overload operators. We follow this word with the operator we want to overload and then the parameters we will call the operator with. + is a binary operator and will need two yyy’s, one on its left and the other on its right. Then at beginning, we give the return value of the operator. In our case we want a + to add two yyy’s and return a third yyy whose i will be the sum of the individual i’s. Thus a+b will call the operator + with x being equal to a and y to b. Thus x.i will have a value 10 and y.i, 5. We are creating a new object z and in the constructor passing 15 i.e. 10 + 5. Thus the i of z will be 15 which is being returned. a + b will now be replaced by the object whose i has a value 15 and c will be equal to this object. Thus c.i will be equal to 15.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
System.Console.WriteLine(c.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator = ( yyy x , yyy y)
{
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Compiler Error
a.cs(19,28): error CS1020: Overloadable binary operator expected
The error message is telling us that we cannot overload the assignment operator =. Every class gets a free assignment operator which does a bitwise copy of the variables of the object from the left to the right.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c = new yyy(2);
yyy d;
d = a + b + c ;
System.Console.WriteLine(d.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Output
Operator + 10 5
Operator + 15 2
17
The only change is d = a + b + c. C# gets easily confused with complex statements so it does not read all of it. It sees two operators on the same line. In this case, the same plus. An internal rule tells it to read the plus left to right i.e. it will only see a + b. It will call the operator + with x.i as 10 and y.i as 5 because a’s i is 10 and b’s i is 5. This will create a temporary object like yyy whose i is 15, lets call it zz. The object z is very different from zz. C# then evaluates zz + c. Thus x.i will display 15 and y.i will have the value of c.i i.e. 2. To support multiple invocations of the operator on a single line, the code does not change.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
int d = a + b ;
System.Console.WriteLine(d);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static int operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
return x.i + y.i;
}
}
Output
operator + 10 5
15
C# does not and will never understand what addition of two yyy’s is all about. It is in your hands to decide what the code accomplishes. You decide whether the overloaded + returns a yyy or an int object. The class yyy is your creation not C#’s. Hence you decide what addition means in the context of a yyy class. In this case, we are returning an int unlike earlier where we returned a yyy.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
int d = a + b ;
System.Console.WriteLine(d);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static int operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
return x.i + y.i;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Compiler Error
a.cs(23,19): error CS0111: Class ‘yyy’ already defines a member called ‘ op_Addition ‘ with the same parameter types
You cannot have two operator + overloads which only differ in return types. Also the error messages change the name of the operator from + to op_Addition. When we overloaded functions, the return type was not considered part of the function signature. The same applies for operators.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy d = a + b + 20;
System.Console.WriteLine(d.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Compiler Error
a.cs(7,9): error CS0019: Operator ‘+’ cannot be applied to operands of type ‘yyy’ and ‘int’
C# is now telling you that you can add two yyy’s but cannot do the same, i.e. add a yyy and an int as we have not told C# how to do so.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy d = a + b + 20;
System.Console.WriteLine(d.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
public static yyy operator + ( yyy x , int y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y);
yyy z = new yyy(x.i+y);
return z;
}
}
Output
Operator + 10 5
Operator + 15 20
35
Life is fun in the fast lane. As we could have a large number of functions with the same name but differing number of parameters, ditto for operators. a + b as usual calls the first operator +. This as usual creates a temp object, say zz and now C# reads the line as zz + 20. This matches the second operator + which now gets called. You can have over a million plus operators with differing parameters if you desire.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
if ( a > b )
System.Console.WriteLine(“true”);
else
System.Console.WriteLine(“false”);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static bool operator > ( yyy x , yyy y)
{
System.Console.WriteLine(“operator < “ + x.i + “ “ + y.i);
return x.i > y.i;
}
}
Compiler Error
a.cs(20,20): error CS0216: The operator ‘yyy.operator >(yyy, yyy)’ requires a matching operator ‘<‘ to also be defined
C# is a romantic at heart and loves pairs. We tried to overload the > operator and C# tells us that we have to also overload the < operator. It makes sense as a user would want to know whether a yyy is greater than or less than another yyy.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
if ( a > b )
System.Console.WriteLine(“true”);
else
System.Console.WriteLine(“false”);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static bool operator > ( yyy x , yyy y)
{
System.Console.WriteLine(“operator > “ + x.i + “ “ + y.i);
return x.i > y.i;
}
public static bool operator < ( yyy x , yyy y)
{
System.Console.WriteLine(“operator < “ + x.i + “ “ + y.i);
return x.i < y.i;
}
}
Output
operator > 10 5
true
The operator < returns a bool as we would like to use it as part of an if or a while. In this case we are using it as part of an if and nothing stops us from using the < overloaded for ints and yyy’s to return a bool. What code you write in an operator is entirely your decision. The < operator looks like the + and can take different parameters. To overload the !=, you also have to overload the ==.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
System.Console.WriteLine(a.ToString());
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
}
Output
yyy
yyy
In the first WriteLine function to be called, we are passing the object a whereas the first parameter to WriteLine should be a string. Also we do not get an error and we see yyy displayed. A longtime back we told you that all classes finally derive from object. The class object has a function ToString. Thus calling the ToString function off a produces the same output as the above line. We have not created the ToString function. So either we got a free ToString implementation from C# like we get a free Constructor or the ToString function of object in some way determines the name of our class and returns it as a string.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
System.Console.WriteLine(a.ToString());
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Compiler Warning
a.cs(17,15): warning CS0114: ‘yyy.ToString()’ hides inherited member ‘object.ToString()’. To make the current method override that implementation, add the override keyword. Otherwise add the new keyword.
It is the same warning if a function exists in the base class.
Output
yyy
ToString
mukhi
WriteLine displays yyy and a.ToString displays mukhi. Which means that they call different ToString functions. The WriteLine(a) calls the ToString of object whereas the second WriteLine calls it of yyy. If we want to override a function in the base class, we have to specifically do so by using the modifier override. If we do not, the default is to call the base class ToString. All this has been explained earlier, in any case.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
System.Console.WriteLine(a.ToString());
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
ToString
mukhi
ToString
mukhi
Now both the System.Console.WriteLine calls the ToString function of yyy. We would like to convert a yyy into a string or an int for example. These type conversions are a major part of operator overloading.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static implicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator string
string 10
In spite of having a function ToString, it does not get called unlike earlier. After the keyword operator we have the name of a data type i.e. string. This function is called whenever we want to convert our object into a string. The parameter y stands for the object to be converted. In this function we can write whatever code we want to but we must return a string. In our case we return the text string concatenated with the current value of i.
Once again, the WriteLine function requires a string class. We are offering a yyy class. C# checks whether there is an operator string which is available to convert a yyy into a string. As there is one, it gets called. The word implicit means that we are indirectly implying that it should be called. Lets explain this with another example.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = a;
System.Console.WriteLine(s);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Compiler Error
a.cs(7,5): error CS0029: Cannot implicitly convert type ‘yyy’ to ‘string’
We have changed the word implicit which means imply. It also means giving a hint with the word explicit which means specify. Had we not changed implicit with explicit, we would have got no error and C# would have called the operator to convert a into a string and initialize s to it.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = (string)a;
System.Console.WriteLine(s);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator string
string 10
The () is called a cast and it takes any data type within brackets. We are explicitly asking for a conversion to a string and unlike earlier we are not being implicit but explicit.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = (string)a;
System.Console.WriteLine(s);
System.Console.WriteLine(a);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator string
string 10
ToString
mukhi
The explicit will get called only when we cast and as we do not have an implicit modifier, the ToString gets called. We get no error if we do not have an implicit modifier.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = (string)a;
System.Console.WriteLine(s);
System.Console.WriteLine(a);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public static implicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Compiler Error
a.cs(24,15): error CS0557: Duplicate user-defined conversion in class ‘yyy’
We cannot have both the implicit and explicit modifier as two separate functions. Thus you have to decide which one you would want to implement.
a.cs
public class zzz
{
public static void Main()
{
yyy a ;
a = 10;
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
a.cs(7,5): error CS0029: Cannot implicitly convert type ‘int’ to ‘yyy’
One more error. Here we are trying to equate a yyy to an int but unlike earlier, we have not created an object like yyy by saying new. We would need someone to create the yyy object and initialize it to 10, an int.
a.cs
public class zzz
{
public static void Main()
{
yyy a ;
a = 10;
System.Console.WriteLine(a.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
static public implicit operator yyy(int v)
{
System.Console.WriteLine(“operator yyy int “ + v);
yyy z = new yyy(v);
return z;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator yyy int 10
10
A constructor has the same name as the name of the class. Thus operator yyy may double up as a constructor. When we write a = 10, C# calls this constructor and passes the parameter v a value, 10. Operator yyy has now to create an object that looks like yyy and return it. Thus it does not act like a constructor in the sense that a constructor is responsible for creating the object. In other words, writing a = 10, creates a new object that looks like yyy and initializes it to 10. It is different from what we did earlier as previously the operator did not have to create an object that looks like yyy. In this case it has to.
a.cs
public class zzz
{
public static void Main()
{
yyy a ;
a = “Hi”;
System.Console.WriteLine(a.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
static public implicit operator yyy(int v)
{
System.Console.WriteLine(“operator yyy int “ + v);
yyy z = new yyy(v);
return z;
}
static public implicit operator yyy(string v)
{
System.Console.WriteLine(“operator yyy string “ + v);
yyy z = new yyy(100);
return z;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator yyy string Hi
100
We can have as many operator yyy functions as we like, provided we follow the rules of function overloading. Thus we have two of them, one that takes a string, another that takes an int. In this case as we are writing a = “hi”, the second operator that accepts a string get called. They all have to return an object that looks like yyy.
a = (short) 10;
Had we written the above line, we will not get any errors. We assumed we will get an error as we do not have an operator yyy which takes a short as a parameter. C# is highly intelligent. It first checks whether we have an operator yyy that matches what we wrote. In no case, there is a match. It will then check whether there is any other way it can prevent an error from being signaled. C# realizes that there is an operator yyy which accepts an int. Thus it converts a short to an int and then calls the operator yyy with the int parameter.
Six important concept STACK,HEAP,VALUES TYPe,REFERENCE TYPe,BOXING AND UNBOXING
Introduction
This article will explain six important concepts: stack, heap, value types, reference types, boxing, and unboxing. This article starts explaining what happens internally when you declare a variable and then it moves ahead to explain two important concepts: stack and heap. The article then talks about reference types and value types and clarifies some of the important fundamentals around them.
The article concludes by demonstrating how performance is hampered due to boxing and unboxing, with a sample code.
Watch my 500 videos on various topics like design patterns, WCF, WWF, WPF, LINQ, Silverlight, UML, SharePoint, Azure, VSTS, and a lot more: click here. You can also catch me on my trainings here.
Image taken from http://michaelbungartz.wordpress.com/.
What goes inside when you declare a variable?
When you declare a variable in a .NET application, it allocates some chunk of memory in the RAM. This memory has three things: the name of the variable, the data type of the variable, and the value of the variable.
That was a simple explanation of what happens in the memory, but depending on the data type, your variable is allocated that type of memory. There are two types of memory allocation: stack memory and heap memory. In the coming sections, we will try to understand these two types of memory in more detail.
Stack and heap
In order to understand stack and heap, let’s understand what actually happens in the below code internally.Collapse | Copy Code
Collapse | Copy Code
public void Method1()
{
// Line 1
int i=4;
// Line 2
int y=2;
//Line 3
class1 cls1 = new class1();
}
It’s a three line code, let’s understand line by line how things execute internally.
Exiting the method (the fun): Now finally the execution control starts exiting the method. When it passes the end control, it clears all the memory variables which are assigned on stack. In other words all variables which are related to int data type are de-allocated in ‘LIFO’ fashion from the stack.
The big catch – It did not de-allocate the heap memory. This memory will be later de-allocated by the garbage collector.
Now many of our developer friends must be wondering why two types of memory, can’t we just allocate everything on just one memory type and we are done?
If you look closely, primitive data types are not complex, they hold single values like ‘int i = 0’. Object data types are complex, they reference other objects or other primitive data types. In other words, they hold reference to other multiple values and each one of them must be stored in memory. Object types need dynamic memory while primitive ones needs static type memory. If the requirement is of dynamic memory, it’s allocated on the heap or else it goes on a stack.
Image taken from http://michaelbungartz.wordpress.com/
Value types and reference types
Now that we have understood the concept of Stack and Heap, it’s time to understand the concept of value types and reference types. Value types are types which hold both data and memory on the same location. A reference type has a pointer which points to the memory location.
Below is a simple integer data type with name i whose value is assigned to another integer data type with name j. Both these memory values are allocated on the stack.
When we assign the int value to the other int value, it creates a completely different copy. In other words, if you change either of them, the other does not change. These kinds of data types are called as ‘Value types’.
When we create an object and when we assign an object to another object, they both point to the same memory location as shown in the below code snippet. So when we assign obj to obj1, they both point to the same memory location.
In other words if we change one of them, the other object is also affected; this is termed as ‘Reference types’.
So which data types are ref types and which are value types?
In .NET depending on the data type, the variable is either assigned on the stack or on the heap. ‘String’ and ‘Objects’ are reference types, and any other .NET primitive data types are assigned on the stack. The figure below explains the same in a more detail manner.
Boxing and unboxing
Wow, you have given so much knowledge, so what’s the use of it in actual programming? One of the biggest implications is to understand the performance hit which is incurred due to data moving from stack to heap and vice versa.
Consider the below code snippet. When we move a value type to reference type, data is moved from the stack to the heap. When we move a reference type to a value type, the data is moved from the heap to the stack.
This movement of data from the heap to stack and vice-versa creates a performance hit.
When the data moves from value types to reference types, it is termed ‘Boxing’ and the reverse is termed ‘UnBoxing’.
If you compile the above code and see the same in ILDASM, you can see in the IL code how ‘boxing’ and ‘unboxing’ looks. The figure below demonstrates the same.
Performance implication of boxing and unboxing
In order to see how the performance is impacted, we ran the below two functions 10,000 times. One function has boxing and the other function is simple. We used a stop watch object to monitor the time taken.
The boxing function was executed in 3542 ms while without boxing, the code was executed in 2477 ms. In other words try to avoid boxing and unboxing. In a project where you need boxing and unboxing, use it when it’s absolutely necessary.
With this article, sample code is attached which demonstrates this performance implication.
Currently I have not included source code for unboxing but the same holds true for it. You can write code and experiment it using the stopwatch class.
Understanding Delegates
The C# Column - Yashawant Kanetkar
A delegate is an important element of C# and is extensively used in every type of .NET application. A delegate is a class whose object (delegate object) can store a set of references to methods. This delegate object is used to invoke the methods. Many developers find delegates complicated. But believe me, it’s a simple concept to understand. In this article we will see how delegates work and in what situations they are used.
Let’s start with a simple program that shows how to declare and use a delegate.
class sample
{
delegate void del1();
delegate void del2 (int i);
public void fun()
{
del1 d1 = new del1 (f1);
d1();
del2 d2 = new del2 (f2) ;
d2 ( 5 ) ;
}
public void f1()
{
Console.WriteLine (“Reached in f1”) ;
}
public void f2 (int i)
{
Console.WriteLine (“Reached in f2”) ;
}
}
In the sample class we have declared two delegates—del1 and del2. The statement delegate void del1( ) ;
indicates that the delegate del1 is going to encapsulate methods, which takes no parameter and returns void. When this statement is encountered, a class del1 derived from a pre-defined class MultiCastDelegate gets created. Similarly, the statement delegate void del2 ( int i ) ; indicates that the delegate del2 will be used for methods taking one integer and returning a void. This statement would create another class del2 derived from the MultiCastDelegate class. The classes del1 and del2 are called ‘delegate classes’. To use the delegate class, like any other class, we have to declare its reference. We have declared the reference to delegate class del1 in the fun( ) method through the statement del1 d1 = new del1 ( f1 ) ;
This would create a delegate object d1. To the constructor of the delegate class we have passed the address of the method f1( ). C++ programmers may know that mentioning a method name without parentheses represents its address. The delegate object would now hold an address of the method f1( ). Next, we have called the f1( ) method using the delegate object d1. This is achieved using the statement d1( ) ;
If d1 is an object, how can we use it as if it is a method? Actually, the call d1( ) gets converted into a call to the d1.Invoke( ) method. The Invoke( ) method calls the f1( ) method using its address stored in delegate object. A delegate can contain references to multiple methods. In this case a single call to Invoke( ) calls all the methods.
Similar to d1 we have instantiated another delegate object d2 and stored in it an address of the method f2( ). As the method f2( ) takes an integer as a parameter we pave passed 5 to d2( ). The value 5 would get passed to all the methods whose references are stored in this delegate object. This makes it obvious that the signature of the delegate and that of the methods to be invoked using the delegate must be identical.
If we create an object of sample class and call the fun( ) method both the f1( ) and f2( ) methods would get called through d1 and d2 respectively.
Delegates make possible calling of methods using reference to methods the object oriented way. This avoids using any complex technique like pointers to functions.
Delegates in Inheritance
Suppose there is a base class and a class derived from this class. A method is invoked from a base class method using a delegate. We can initialise this delegate in derived class so that when the method is invoked from the base class it is the derived class’s method that would get called. Here is the program that works similar to this situation.
using System;
namespace delegateinherit
{
public delegate void del1();
class mybase
{
public del1 d;
public void fun()
{
d();
}
}
class der : mybase
{
public der()
{
d = new del1 (f1);
fun();
d = new del1 (f2);
fun();
}
public void f1()
{
Console.WriteLine (“Reached in f1”) ;
}
public void f2()
{
Console.WriteLine (“Reached in f2”) ;
}
}
class Class1
{
static void Main (string[] args)
{
der d = new der();
}
}
}
Here, from the fun( ) method of the mybase class we have used the delegate object d to invoke a method. The fun( ) method is called twice from the constructor of the derived class der. Before calling fun( ) method, we have associated the delegate d, first with method f1( ) and then with f2( ). Thus, if we create an object of the der class, first the f1( ) and then f2( ) method get called. We can invoke both the methods in a single call to fun( ) as shown below.
d = new del1 ( f1 ) ;
d += new del1 ( f2 ) ;
fun( ) ;
Where Delegates are useful
In a general WinForm application, a class Form1 gets created, which is derived from the Form class. If we want to handle mouse click messages, we override the OnMouseDown( ) message handler in the Form1 class. When we click the mouse button, control reaches to the OnMouseDown( ) of the derived class i.e Form1 class because of the simple rule of inheritance. But if we click on a push button on the form, the OnMouseDown( ) of the Form1 class does not get called. Because Form1 class is not derived from the class that creates button. In such a situation, delegates prove useful. Calling methods using delegate require only that the signature of methods and that of the delegate should match. It does not require any inheritance chain to call the appropriate method. So, in .NET, all the event handlers are called through delegates, instead of relying on the inheritance chain.
Delegate at work
As said earlier, all the event handlers are called using delegates. We will now see a dummy program to explain how the Paint event handler must be getting called using a delegate.
using System;
namespace delegateatwork
{
public delegate void PaintHandler();
class Form
{
public PaintHandler Paint ;
public void OnPaint()
{
Paint();
}
}
class form1 : Form
{
public form1()
{
Paint += new PaintHandler (form1_Paint);
OnPaint() ;
}
public void form1_Paint()
{
Console.WriteLine (“form1_Paint”);
}
}
class Class1
{
static void Main (string[] args)
{
form1 f = new form1();
}
}
}
We have designed a class Form1 that contains a method called Form1_Paint( ). The Form1 class is derived from the Form class. In the Form class we have declared an object Paint of the delegate class PaintHandler. In Main( ) we have instantiated an object of the Form1 class. This results in its constructor being called. In the constructor of the Form1 class we have initialised the Paint object and encapsulated in it the Form1_Paint( ) method. Next we have called the OnPaint( ) method of the Form class (in WinForm application Paint event gets generated automatically), which in turn calls the Form1_Paint( ) method via Paint.
Datalist
Datalist
DataList is a data bound list control that displays items using certain templates defined at the design time. The content of the DataList control is manipulated by using templates sections such as AlternatingItemTemplate, EditItemTemplate, FooterTemplate, HeaderTemplate, ItemTemplate, SelectedItemTemplate and SeparatorTemplate. Each of these sections has its own characteristics to be defined but at a very minimum, the ItemTemplate needs to be defined to display the items in the DataList control. Other sections can be used to provide additional look and feel to the DataList control.
The contents of the DataList control can be manipulated by using templates. The following table lists the supported templates.
The DataList control displays data items in a repeating list, and optionally supports selecting and editing the items. The content and layout of list items in DataList is defined using templates. At a minimum, every DataList must define an ItemTemplate; however, several optional templates can be used to customize the appearance of the list.
AlternatingItemTemplate: If defined, provides the content and layout for alternating items in the DataList. If not defined, ItemTemplate is used.
EditItemTemplate: If defined, provides the content and layout for the item currently being edited in the DataList. If not defined, ItemTemplate is used.
FooterTemplate: If defined, provides the content and layout for the footer section of the DataList. If not defined, a footer section will not be displayed.
HeaderTemplate: If defined, provides the content and layout for the header section of the DataList. If not defined, a header section will not be displayed.
ItemTemplate: Required template that provides the content and layout for items in the DataList.
SelectedItemTemplate: If defined, provides the content and layout for the currently selected item in the DataList. If not defined, ItemTemplate is used.
SeparatorTemplate: If defined, provides the content and layout for the separator between items in the DataList. If not defined, a separator will not be displayed.
At the very minimum, the ItemTemplate needs to be defined to display the items in the DataList control. Additional templates can be used to provide a custom look to the DataList control.
class CApplication
{
public static void Main()
{
int x = 25;
string s = "fred";
DisplayMe( x );
DisplayMe( s );
}
static void DisplayMe( object o )
{
System.Console.WriteLine( "You are {0}", o );
}
}
This would display:
You are 25
You are fred
The most confusing aspect of this for C++ developers is that C# has predetermined which types are represented as values, and which are represented as references. A C++ developer expects to take responsibility for this decision.
For example, in C++ we can do this:
int x1 = 3; // x1 is a value on the stack
int *x2 = new int(3) // x2 is a pointer to a value on the heap
but in C# there is no control:
int x1 = 3; // x1 is a value on the stack
int x2 = new int();
x2 = 3; // x2 is also a value on the stack!
int x = 3; // new int value 3 on the stack
object objx = x; // new int on heap, set to value 3 - still have x=3 on stack
int y = (int)objx; // new value 3 on stack, still got x=3 on stack and objx=3 on heap
For example, look at the following method:
void displayStringLength( string s )
{
Console.WriteLine( "String is length {0}", s.Length );
}
The problem with this method is that it will throw a NullReferenceException if called like this:
string s = null;
displayStringLength( s );
Of course for some situations you may deem a NullReferenceException to be a perfectly acceptable outcome, but in this case it might be better to re-write the method like this:
void displayStringLength( string s )
{
if( s == null )
Console.WriteLine( "String is null" );
else
Console.WriteLine( "String is length {0}", s.Length );
}
using IntList = System.Collections.Generic.List<int>;
but the alias only applies in the file in which it is declared. A workaround in some cases is to use inheritance:
public class IntList : List<int> { }
The pros and cons of this approach are discussed here.
class Person
{
public Person( string name, int age ) { ... }
public Person( string name ) : this( name, 0 ) {}
public Person() : this( "", 0 ) {}
}
Another difference is that virtual method calls within a constructor are routed to the most derived implementation - see Can I Call a virtual method from a constructor.
Error handling is also somewhat different. If an exception occurs during construction of a C# object, the destuctor (finalizer) will still be called. This is unlike C++ where the destructor is not called if construction is not completed. (Thanks to Jon Jagger for pointing this out.)
Finally, C# has static constructors. The static constructor for a class runs before the first instance of the class is created.
Also note that (like C++) some C# developers prefer the factory method pattern over constructors. See Brad Wilson's article.
To achieve deterministic destruction, a class must offer a method to be used for the purpose. The standard approach is for the class to implement the IDisposable interface. The user of the object must call the Dispose() method when it has finished with the object. C# offers the 'using' construct to make this easier.
Note that it's rarely necessary to define a destructor for a C# class - it only makes sense where the class holds direct references to unmanaged resources, which is very unusual. Implementing IDisposable is somewhat more commonly required, but still only necessary for a small minority of classes.
C++ constructs objects from base to derived, so when the base constructor is executing the object is effectively a base object, and virtual method calls are routed to the base class implementation. By contrast, in .NET the derived constructor is executed first, which means the object is always a derived object and virtual method calls are always routed to the derived implementation. (Note that the C# compiler inserts a call to the base class constructor at the start of the derived constructor, thus preserving standard OO semantics by creating the illusion that the base constructor is executed first.)
The same issue arises when calling virtual methods from C# destructors. A virtual method call in a base destructor will be routed to the derived implementation.
Note that if you want your exception to cross remoting boundaries you'll need to do some extra work - see http://www.thinktecture.com/Resources/RemotingFAQ/CustomExceptions.html for details.
using System;
class CApp
{
public static void Main()
{
try
{
f();
}
catch( Exception e )
{
Console.WriteLine( "System.Exception stack trace = \n{0}", e.StackTrace );
}
}
static void f()
{
throw new Exception( "f went pear-shaped" );
}
}
produces this output:
System.Exception stack trace =
at CApp.f()
at CApp.Main()
Note, however, that this stack trace was produced from a debug build. A release build may optimise away some of the method calls which could mean that the call stack isn't quite what you expect.
using System;
class CApp
{
public static void Main()
{
string s = "fred";
long i = 10;
Console.WriteLine( "{0} is {1}an integer", s, (IsInteger(s) ? "" : "not ") );
Console.WriteLine( "{0} is {1}an integer", i, (IsInteger(i) ? "" : "not ") );
}
static bool IsInteger( object obj )
{
if( obj is int || obj is long )
return true;
else
return false;
}
}
produces the output:
fred is not an integer
10 is an integer
using System;
class CTest
{
class CApp
{
public static void Main()
{
long i = 10;
CTest ctest = new CTest();
DisplayTypeInfo( ctest );
DisplayTypeInfo( i );
}
static void DisplayTypeInfo( object obj )
{
Console.WriteLine( "Type name = {0}, full type name = {1}", obj.GetType(), obj.GetType().FullName );
}
}
}
produces the following output:
Type name = CTest, full type name = CTest
Type name = Int64, full type name = System.Int64
class Base { }
class Derived : Base { }
class Program
{
static void Main()
{
ShowType( new Derived() );
}
static void ShowType( Base b )
{
Console.WriteLine(typeof(Base));
Console.WriteLine(b.GetType());
}
}
gives the following output:
Base
Derived
"fred" == "Fred" // false
string.Compare( "fred", "Fred", StringComparison.CurrentCultureIgnoreCase ) == 0 // true
For more control over the comparison, e.g. exotic features like width-sensitivity, consider using System.Globalization.CompareInfo.Compare(), e.g.
CultureInfo.CurrentCulture.CompareInfo.Compare(
"fred", "Fred",
CompareOptions.IgnoreCase |
CompareOptions.IgnoreKanaType |
CompareOptions.IgnoreWidth
);
using System;
class CApp
{
public static void Main( string[] args )
{
Console.WriteLine( "You passed the following arguments:" );
foreach( string arg in args )
Console.WriteLine( arg );
}
}
(Take a look at Charles Cook's NOptFunc project for easy command-line parsing.)
using( obj1 )
{
using( obj2 )
{
...
}
}
However consider using this more aesthetically pleasing (but functionally identical) formatting:
using( obj1 )
using( obj2 )
{
...
}
int x = 10;
int y = 10;
Console.WriteLine( x == y );
Console.WriteLine( x.Equals(y) );
will display:
True
True
However things are more complex for reference types. Generally speaking, for reference types == is expected to perform an identity comparison, i.e. it will only return true if both references point to the same object. By contrast, Equals() is expected to perform a value comparison, i.e. it will return true if the references point to objects that are equivalent. For example:
StringBuilder s1 = new StringBuilder("fred");
StringBuilder s2 = new StringBuilder("fred");
Console.WriteLine( s1 == s2 );
Console.WriteLine( s1.Equals(s2) );
will display:
False
True
s1 and s2 are different objects (hence == returns false), but they are equivalent (hence Equals() returns true).
Unfortunately there are exceptions to these rules. The implementation of Equals() in System.Object (the one your class inherits by default) compares identity, i.e. it's the same as operator==. So Equals() only tests for equivalence if the class author overrides the method (and implements it correctly). Another exception is the string class - its operator== compares value rather than identity.
Bottom line: If you want to perform an identity comparison use the ReferenceEquals() method. If you want to perform a value comparison, use Equals() but be aware that it will only work if the type has overridden the default implementation. Avoid operator== with reference types (except perhaps strings), as it's simply too ambiguous.
To get a feel for the angst this causes among some C++ programmers, read the feedback on this post from Raymond Chen.
There are of course ways of addressing this issue. For example, see Brad Abram's post (and associated feedback) for some ideas on adding optional read-only behaviour to collection classes.
Delegate inference is a new feature of the C# compiler which makes delegate usage a little simpler. It allows you to write this:
Thread t = new Thread(ThreadFunc);
instead of this:
Thread t = new Thread( new ThreadStart(ThreadFunc) );
Another minor but welcome addition is the explicit global namespace, which fixes a hole in namespace usage in C# 1.x. You can prefix a type name with global:: to indicate that the type belongs to the global namespace, thus avoiding problems where the compiler infers the namespace and gets it wrong.
Finally C# 2.0 includes some syntactic sugar for the new System.Nullable type. You can use T? as a synonym for System.Nullable<T>, where T is a value type. As suggested by the name, this allows values of the type to be 'null', or 'undefined'.
Query expressions allow a SQL-like query syntax to be used in C#, e.g.
var nameList = new List<string> { "jack", "jill", "sue" };
var results = from name in nameList
where name.StartsWith("j")
select name;
Query expressions are just syntactic sugar - they resolve to standard method calls. For example the query expression above can be rewritten as:
var results = nameList.Where(name => name.StartsWith("j"));
The argument to Where() is a lambda expression, which represents an anonymous method. However a lambda expression is not just a more concise way to represent executable code - it can also be interpreted as a data structure (known as an expression tree), which allows the expression to be easily analysed or transformed at runtime. For example, LINQ-to-SQL makes use of this feature to transform C# queries to SQL queries, which gives much better performance than a simple in-memory filtering of results (as offered by DataTable.Select(), for example).
The Where() method shown above is an example of another new C# 3.0 feature: extension methods. Extension methods allow extra methods to be 'attached' to an existing type - any type, even sealed types or types you don't have the source code for. For example, the Where() method can be applied to any type that implements IEnumerable<T>.
Another new feature of C# 3.0 is the var keyword, which allows the compiler to infer the type of a variable from context, which is required for anonymous types but can be used with standard named types too:
var list = new List<string>() { "jack", "jill", "sue" }; // optional use with named types
var person = new { name = "jack", age = 20 }; // anonymous type
These examples also demonstrate the new object initializer and collection initializer syntax.
Finally, there are implicitly typed arrays and auto-implemented properties:
var names = new [] { "jack", "jill", "sue" }; // implicitly string[]
public string Name { get; set; } // auto-implemented property - private backing field auto-generated
Bottom of Form
This is an article on Constructors in C#, for the beginner level programmers. It covers simple constructors, constructors overloading, behaviour of constructors in inheritance, constructor chaining and static constructors. At the end, it contains the general FAQs about constructors.
Top of Form
Introduction
Broadly speaking, a constructor is a method in the class which gets executed when its object is created. Usually, we put the initialization code in the constructor. Writing a constructor in the class is damn simple, have a look at the following sample:
Collapse | Copy Code
public class mySampleClass
{
public mySampleClass()
{
// This is the constructor method.
}
// rest of the class members goes here.
}
When the object of this class is instantiated, this constructor will be executed. Something like this:
Collapse | Copy Code
mySampleClass obj = new mySampleClass()
// At this time the code in the constructor will // be executed
Constructor Overloading
C# supports overloading of constructors, that means, we can have constructors with different sets of parameters. So, our class can be like this:
Collapse | Copy Code
public class mySampleClass
{
public mySampleClass()
{
// This is the no parameter constructor method.
// First Constructor
}
public mySampleClass(int Age)
{
// This is the constructor with one parameter.
// Second Constructor
}
public mySampleClass(int Age, string Name)
{
// This is the constructor with two parameters.
// Third Constructor
}
// rest of the class members goes here.
}
Well, note here that call to the constructor now depends on the way you instantiate the object. For example:
Collapse | Copy Code
mySampleClass obj = new mySampleClass()
// At this time the code of no parameter
// constructor (First Constructor)will be executed
mySampleClass obj = new mySampleClass(12)
// At this time the code of one parameter
// constructor(Second Constructor)will be
// executed.
The call to the constructors is completely governed by the rules of overloading here.
Calling Constructor from another Constructor
You can always make a call to one constructor from within another. Say, for example:
Collapse | Copy Code
public class mySampleClass
{
public mySampleClass(): this(10)
{
// This is the no parameter constructor method.
// First Constructor
}
public mySampleClass(int Age)
{
// This is the constructor with one parameter.
// Second Constructor
}
}
Very first of all, let us see what is this syntax:
Collapse | Copy Code
public mySampleClass(): this(10)
Here, this refers to same class, so when we say this(10), we actually mean execute the public mySampleClass(int Age) method. The above way of calling the method is called initializer. We can have at the most one initializer in this way in the method.
Another thing which we must know is the execution sequence i.e., which method will be executed when. Here, if I instantiate the object as:
Collapse | Copy Code
mySampleClass obj = new mySampleClass()
Then the code of public mySampleClass(int Age) will be executed before the code of mySampleClass(). So, practically the definition of the method:
Collapse | Copy Code
public mySampleClass(): this(10)
{
// This is the no parameter constructor method.
// First Constructor
}
is equivalent to:
Collapse | Copy Code
public mySampleClass()
{
mySampleClass(10)
// This is the no parameter constructor method.
// First Constructor
}
Note: Above (just above this line) code is mentioned there for pure analogy and will not compile. The intention here is to tell the flow of execution if initializers are used.
We cannot make an explicit call to the constructors in C#, treating them as if any simple method, for example: statement mySampleClass(10) in the above code will not work. The only way you can call one constructor from another is through initializers.
For the VB.NET programmers: you can make the call to another constructor of the same class by the syntax Me.New(param list), but it should be the first line of your calling constructor method. So ultimately, the code of the called constructor runs prior to the code of the calling constructor, which is same as initializers here.
Note that only this and base (we will see it further) keywords are allowed in initializers, other method calls will raise an error.
This is sometimes called Constructor chaining.
Huff… Simple thing made tough, but this is how it is. Anyway, let us proceed further.
Behavior of Constructors in Inheritance
Let us first create the inherited class.
Collapse | Copy Code
public class myBaseClass
{
public myBaseClass()
{
// Code for First Base class Constructor
}
public myBaseClass(int Age)
{
// Code for Second Base class Constructor
}
// Other class members goes here
}
public class myDerivedClass : myBaseClass
// Note that I am inheriting the class here.
{
public myDerivedClass()
{
// Code for the First myDerivedClass Constructor.
}
public myDerivedClass(int Age):base(Age)
{
// Code for the Second myDerivedClass Constructor.
}
// Other class members goes here
}
Now, what will be the execution sequence here:
If I create the object of the derived class as:
Collapse | Copy Code
myDerivedClass obj = new myDerivedClass()
Then the sequence of execution will be:
- public myBaseClass() method.
- and then public myDerivedClass() method.
Note one thing here: we are not making any explicit call to the constructor of base class neither by initializer nor by the base keyword, but it is still executing. This is the normal behavior of the constructor.
If I create an object of the derived class as:
Collapse | Copy Code
myDerivedClass obj = new myDerivedClass(15)
Then the sequence of execution will be:
- public myBaseClass(int Age) method
- and then public myDerivedClass(int Age) method
Also note the usage of Age variable in the syntax: public myDerivedClass(int Age):base(Age). [Understanding it is left to the reader].
Private Constructors
Private constructors, the constructors with the "private" access modifier, are a bit special case. It is because we can neither create the object of the class, nor can we inherit the class with only private constructors. But yes, we can have the set of public constructors along with the private constructors in the class and the public constructors can access the private constructors from within the class through constructor chaining.
Say for example, my class is something like this :
Collapse | Copy Code
public class myClass
{
private MyClass()
{
Console.WriteLine("This is no parameter Constructor");
}
public MyClass(int var):this()
{
Console.WriteLine("This is one parameter Constructor");
}
// Other class methods goes here
}
Then we can create the object of this class by the statement:
Collapse | Copy Code
MyClass obj = new MyClass(10);
The above statement will work fine, but the statement
Collapse | Copy Code
MyClass obj = new MyClass();
will raise an error : 'Constructors.MyClass.MyClass()' is inaccessible due to its protection level
It is possible to have the class with only the private constructors. But yes as I said, such class can neither be instantiated nor be inherited. If we try to inherit the class with only private constructors then we will get the same error as above. Also recall, once you provide constructor from your side the compiler will not add the no-parameter public constructor to your class.
Well, one of the usage scenarios of such class could be – when you have only static members in the class and you don't need to instantiate it.
Phew… lost… Anything left in constructors? Yes, Static Constructors. Ha!! Now, what are they? Let us see..
Static Constructors
This is a new concept introduced in C#. By new here, I mean that it was not available for the C++ developers. This is a special constructor and gets called before the first object is created of the class. The time of execution cannot be determined, but it is definitely before the first object creation - could be at the time of loading the assembly.
The syntax of writing the static constructors is also damn simple. Here it is:
Collapse | Copy Code
public class myClass
{
static myClass()
{
// Initialization code goes here.
// Can only access static members here.
}
// Other class methods goes here
}
Notes for Static Constructors:
- There can be only one static constructor in the class.
- The static constructor should be without parameters.
- It can only access the static members of the class.
- There should be no access modifier in static constructor definition.
Firstly, the call to the static method is made by the CLR and not by the object, so we do not need to have the access modifier to it.
Secondly, it is going to be called by CLR, who can pass the parameters to it, if required. So we cannot have parameterized static constructor.
Thirdly, non-static members in the class are specific to the object instance. So static constructor, if allowed to work on non-static members, will reflect the changes in all the object instances, which is impractical. So static constructor can access only static members of the class.
Fourthly, overloading needs the two methods to be different in terms of methods definition, which you cannot do with Static Constructors, so you can have at the most one static constructor in the class.
Now, one question raises here, can we have two constructors as:
Collapse | Copy Code
public class myClass
{
static myClass()
{
// Initialization code goes here.
// Can only access static members here.
}
public myClass()
{
// Code for the First myDerivedClass Constructor.
}
// Other class methods goes here
}
This is perfectly valid, though doesn't seem to be in accordance with overloading concepts. But why? Because the time of execution of the two methods are different. One is at the time of loading the assembly and one is at the time of object creation.
Constructors FAQs
- Is the constructor mandatory for a class?
Yes, it is mandatory to have the constructor in the class and that too should be accessible for the object i.e., it should have a proper access modifier. Say, for example, we have only private constructor(s) in the class and if we are interested in instantiating the class, i.e., want to create an object of the class, then having only private constructor will not be sufficient and in fact it will raise an error. So, proper access modifies should be provided to the constructors.
- What if I do not write the constructor?
In such case, the compiler will try to supply the no parameter constructor for your class, behind the scene. Compiler will attempt this only if you do not write the constructor for the class. If you provide any constructor (with or without parameters), then compiler will not make any such attempt.
- What if I have the constructor public myDerivedClass(), but not the public myBaseClass()?
It will raise an error. If either the no parameter constructor is absent or it is in-accessible (say it is private), it will raise an error. You will have to take the precaution here.
- Can we access static members from the non-static (normal) constructors?
Yes, we can. There is no such restriction on non-static constructors. But there is one on static constructors that it can access only static members.
Bottom of Form
ENCApsulation in c#
Introduction
In the OOProgramming will give the impression very unnatural to a programmer with lot of procedural programming experience. In OOP encapsulation is the main pace. Encapsulation is a procedure of covering up or hiding up of data and functions into a single unit which is called as a class. An encapsulated object is often called as an abstract data type.
Background
The need of encapsulation is to prevent the code from accidental corruption due to minor errors that we are all making. In OOP data is treated as a critical element in the application development & data is packed closely to the functions which operate on it and protects from accidental modification from other outside functions.
Encapsulation provides a way to protect data from accidental corruption. Rather than defining the data in the form of public we can also declare those fields as private. The private data are manipulated indirectly by two methods. The first method is using a pair of conventional accessor and mutator methods. Another method is using a named property, get and set.
Encapsulation using Accessors & Mutators
Lets see a small example to manipulate the data in the class:
Collapse | Copy Code
class Employee
{
private int empID;
private string empName;
private double empSal;
// Accessor
public int getEmpID()
{
return empID;
}
public string getEmpName()
{
return empName;
}
public double getEmpSal()
{
return empSal;
}
// Mutator
public void setEmpID(int eid)
{
empID = eid;
}
public void setEmpName(string ename)
{
empName = ename;
}
public void setEmpSal(double esal)
{
empSal = esal;
}
}
Like the above way we can protect the private data from outside world. Here we use two separate methods to assign and get the required data.
s see a small example to manipulate the data in the class:
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee();
e.setEmpID(1001);
e.setEmpName("Smith");
e.setEmpSal(25000.75);
Console.WriteLine("The Employee ID:" + e.getEmpID());
Console.WriteLine("The Employee Name:" + e.getEmpName());
Console.WriteLine("The Employee Salary:" + e.getEmpSal());
Console.ReadKey();
}
}
In the above example we can not access the private data empId, empName, empSal from any object instance. We can manipulate the data only using those two methods accessor and mutator.
Encapsulation Using Properties
Properties are the new feature introduced in C#. Properties in C# helps in protect a field in a class by reading the writing to it. Now let's see a small example on properties,
Collapse | Copy Code
class Employee
{
private int empID;
public int EmpID
{
get { return empID; }
set { empID = value; }
}
private string empName;
public string EmpName
{
get { return empName; }
set { empName = value; }
}
private double empSal;
public double EmpSal
{
get { return empSal; }
set { empSal = value; }
}
}
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee();
e.EmpID = 1001;
e.EmpName = "Smith";
e.EmpSal = 25000.75;
Console.WriteLine("The Employee ID: " + e.EmpID + " Name:" + e.EmpName + " Salary:" + e.EmpSal);
Console.ReadKey();
}
}
From the above example we see the usage of encapsulation by using the properties. The property has two properties get and set. The get is nothing but it returns a value of the some property field. The set will sets the value of the some property field with the contents of "value". Properties can be made read-only too. This can be done by the get property implementation.
Read Only Property:
In the below example we see how to implement a read only property. The class Employee has a EmpID, EmpName, EmpSal properties that only implements a get accessor. It leaves out the set accessor. This particular class creates a new object named e. The instantiation of the e object used the constructor of the Employee class that takes the int, string, double parameters. Since the below program is read-only we can not set the valuer to the field EmpID, EmpName, EmpSal and we only read or get the value of the data from the field. Properties can be made also write only. This can be implemented only a set accessor in the property implementation.
Collapse | Copy Code
class Employee
{
private int empID;
private string empName;
private double empSal;
public Employee(int eid, string ename, double esal)
{
empID = eid;
empName = ename;
empSal = esal;
}
public int EmpID
{
get { return empID; }
}
public string EmpName
{
get { return empName; }
}
public double EmpSal
{
get { return empSal; }
}
}
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee(1001, "Smith", 25000.75);
Console.WriteLine("The Employee ID: " + e.EmpID + " Name:" + e.EmpName + " Salary:" + e.EmpSal);
Console.ReadKey();
}
}
Write Only Property:
Collapse | Copy Code
class Employee
{
private int empID;
private string empName;
private double empSal;
public int EmpID
{
set
{
empID = value;
Console.WriteLine("The Employee ID:" + empID);
}
}
public string EmpName
{
set
{
empName = value;
Console.WriteLine("The Employee Name:" + empName);
}
}
public double EmpSal
{
set
{
empSal = value;
Console.WriteLine("The Employee Salary:" + empSal);
}
}
}
Collapse | Copy Code
class ReadEmpMain
{
static void Main(string[] args)
{
Employee e = new Employee();
e.EmpID = 1001;
e.EmpName = "Smith";
e.EmpSal = 25000.75;
}
}
In the above example we see how to implement a write only property. The class Employee has a EmpID, EmpName, EmpSal properties that only implements a set accessor. It leaves out the get accessor. The set method is varied a little by it prints value of EmpID, EmpName, EmpSal after it is been assigned.
Conclusion
The Encapsulation is the first important step towards the object oriented programming. This artical will give you a little bit information about the encapsulation. Using the accessor & mutator methods we can encapsulate the data. Another approach by using the properties like get and set. The benefits of properties is that the users of your objects are able to manipulate internal data point using a single named item.
Interfaces in C# (For Beginners)
Top of Form
Introduction
Interfaces in C # provide a way to achieve runtime polymorphism. Using interfaces we can invoke functions from different classes through the same Interface reference, whereas using virtual functions we can invoke functions from different classes in the same inheritance hierarchy through the same reference. Before things start getting difficult let me start using simple and short examples to explain the concept of interfaces. Here's a short example that shows you what an interface looks like. P1.cs
Collapse | Copy Codeclass Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
}
Output
Collapse | Copy CodeHello Interfaces
The above program compiles and runs successfully to produce the desired output. The above program consists of a class Demo and within it an entry point function Main() that prints Hello Interfaces. The above program also defines an interface abc. Interface abc is empty at this point of time. Let's add some elements to this interface.
P2.cs
Collapse | Copy Codeclass Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
int x;
}
Output
Collapse | Copy CodeP2.cs(11,3): error CS0525: Interfaces cannot contain fields
Error! Interfaces in C# cannot contain fields i.e variables. The above program declared an integer variable x in the interface abc. And that's what hit the C# compiler badly.
P3.cs
Collapse | Copy Codeclass Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
void xyz()
{
System.Console.WriteLine("In xyz");
}
}
Output
Collapse | Copy CodeP3.cs(11,8): error CS0531: 'abc.xyz()': interface members cannot have a
definition
This time over we included a function xyz() inside the interface found that this too hurt the C# compiler. It told us loudly that interface members cannot have a defination. Does this mean that if we just have a function declaration inside the interface abc that is fine with the C# compiler? Let's find it out.
P4.cs
Collapse | Copy Codeclass Demo
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
void xyz();
}
Output
Collapse | Copy CodeHello Interfaces
The above program compiles and runs successfully to produce the desired output. Finally we made the compiler happy. Interfaces in C# can only contain function declarations. Now let us see interfaces in action.
Interfaces are contracts that a class implements in its own way. This means an interface will contain function prototypes and a class that marries this interface will have to take the responsibility of defining the functions whose prototypes are declared by the marrying interface.
So its time to perform the marriage between our groom class Demo and the bride interface abc.
P4.cs
Collapse | Copy Codeclass Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
}
interface abc
{
void xyz();
}
Output
Collapse | Copy CodeP4.cs(1,7): error CS0535: 'Demo' does not implement interface member
'abc.xyz()'
P4.cs(11,8): (Location of symbol related to previous error)
Well, in the above program class Demo did marry the interface abc through the line class demo : abc but as usual there's a small misunderstanding between the newlyweds. Class Demo needs to take the responsibility of defining the functions whose prototypes are declared by the marrying interface abc. Since class Demo in the above program has not been implemented i.e. defined the function xyz whose prototype is declared by the marrying interface abc we get an error in the above program. To fix this issue, the class Demo has to take the responsiility of defining the function xyz whose prototype is declared by the marrying interface abc. And that is what you get to see in the following program.
P5.cs
Collapse | Copy Codeclass Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
}
void xyz()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
Output
Collapse | Copy Codea.cs(1,7): error CS0536: 'Demo' does not implement interface member
'abc.xyz()'.'Demo.xyz()' is either static, not public,
or has the wrong return type.
a.cs(16,8): (Location of symbol related to previous error)
a.cs(7,8): (Location of symbol related to previous error)
Error again! It's not enough for the class Demo to implement the function xyz. It has to impress the bride interface abc by declaring its implementation of xyz as public. And that's what is done by the following program.
P6.cs
Collapse | Copy Codeclass Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
xyz();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
Output
Collapse | Copy CodeHello Interfaces
In xyz
Bingo! The above program compiles and runs successfully to produce the desired output. As mentioned earlier using interfaces we can invoke functions from different classes using the same interface reference. For this, we need to have different classes to implement the same interface. In the above program our class Demo is implementing the interface abc. Let's have another class Sample that implements the interface abc.
P7.cs
Collapse | Copy Codeclass Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
refDemo.xyz();
Sample refSample = new Sample();
refSample.xyz();
}
public void xyz()
{
System.Console.WriteLine("In Demo :: xyz");
}
}
interface abc
{
void xyz();
}
class Sample : abc
{
public void xyz()
{
System.Console.WriteLine("In Sample :: xyz");
}
}
Output
Collapse | Copy CodeIn Demo :: xyz
In Sample :: xyz
The above program compiles and runs successfully to produce the desired output. refDemo is a reference to the object of class Demo. refSample is a reference to the object of class Sample. Both the classes implement the interface abc and hence define their own implementation of the function xyz(). From within the entry point function Main() xyz() of the respective classes Demo and Sample are invoked through references refDemo and refSample.
Now that we have two different classes implementing the same interface its time to show you how to invoke functions from different classes using the same interface reference.
P8.cs
Collapse | Copy Codeclass Demo : abc
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
abc refabc = new Demo();
refabc.xyz();
abc refabc = new Sample();
refabc.xyz();
}
public void xyz()
{
System.Console.WriteLine("In Demo :: xyz");
}
}
interface abc
{
void xyz();
}
class Sample : abc
{
public void xyz()
{
System.Console.WriteLine("In Sample :: xyz");
}
}
Output
Collapse | Copy CodeIn Demo :: xyz
In Sample :: xyz
The above program compiles and runs successfully to produce the desired output. Inside Main() we have an interface reference refabc of type interface abc. Reference of object of class Demo is stored in refabc and xyz() of class Demo is invoked using refabc. Next, the reference of object of class Sample is stored in refabc and xyz() of class Sample is invoked using refabc. Thus, we were able to invoke xyz() that belongs to different classes Demo and Sample via a common interface reference refabc.
The following program uses a for loop to invoke the functions of different classes Demo and Sample that implement the same interface "interface abc" using a single interface reference refabc whose type matches the interface "interface abc" which the classes impliment.
P9.cs
Collapse | Copy Codeclass Demo : abc
{
public static void Main()
{
abc [] refabc = {new Demo(), new Sample()} ;
for (int i = 0; i<= 1; i++)
refabc[i].xyz();
}
public void xyz()
{
System.Console.WriteLine("In Demo :: xyz");
}
}
interface abc
{
void xyz();
}
class Sample : abc
{
public void xyz()
{
System.Console.WriteLine("In Sample :: xyz");
}
}
Output
Collapse | Copy CodeIn Demo :: xyz
In Sample :: xyz
The above program compiles and runs successfully to produce the desired output. refabc is an array of type interface abc. It stores the references to objects of classes Demo and Sample. In the for loop, using the array refabc, we are invoking the function xyz() of class Demo and Sample. A class can impliment as many interfaces as it wants. Take the following program.
P10.cs
Collapse | Copy Codeclass Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
abc refabc = new Demo();
refabc.xyz();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void pqr();
}
Output
Collapse | Copy CodeHello Interfaces
In xyz
The above program compiles and runs successfully to produce a desired output. Class Demo implements interface abc and thereby function xyz(). Class Demo also impliments interface def and thereby function pqr(). ref abc which is a variable of type Interface abc, refers to object of class Demo. Next xyz() of Demo is invoked via refabc as refabc is a variable of type Interface abc which contains the prototype for function xyz().
P11.cs
Collapse | Copy Codeclass Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
abc refabc = new Demo();
refabc.xyz();
refabc.pqr();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void pqr();
}
Output
Collapse | Copy CodeP11.cs(9,5): error CS0117: 'abc' does not contain a definition for 'pqr'
Error! An attempt to invoke pqr() of Demo via refabc fails as refabc is a variable of type Interface abc which contains the prototype for function xyz() and NOT pqr(). One can invoke pqr() of Demo via a reference variable of type Interface def as the interface def contains the prototype for function pqr(). And that's what is done by the following program.
P12.cs
Collapse | Copy Codeclass Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.pqr();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def
{
void pqr();
}
Output
Collapse | Copy CodeHello Interfaces
In xyz
In pqr
The above program compiles and runs successfully to produce a desired output. Class Demo impliments the interfaces abc and def. An object of class Demo is created and its reference is stored in refDemo. refabc which is a variable of type Interface abc, refers to the object of class Demo. Next xyz() of Demo is invoked via refabc as refabc is a variable of type Interface abc which contains the prototype for function xyz(). Similarly, refdef which is a variable of type Interface def, refers to object of class Demo. Next pqr() of Demo is invoked via refdef as refdef is a variable of type Interface def which contains the prototype for function pqr().
P13.cs
Collapse | Copy Codeclass Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.xyz();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void xyz();
}
Output
Collapse | Copy CodeHello Interfaces
In xyz
In xyz
The above program compiles and runs successfully to produce a desired output. Both the interfaces abc and def declare the prototypes for function xyz(). Class Demo implements interfaces abc as well as def and defines the function xyz() as well. Thus we can invoke the function xyz() through either of the interface reference variables (refabc or refdef) after storing the reference to the object of class Demo in refabc or refdef. This poses a question, how can we have an implementation of xyz that is specific to interface abc and implementation of xyz that is specific to def inside class Demo? Well, for this we need to use the fully qualified names as in the following program.
P14.cs
Collapse | Copy Codeclass Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.xyz();
}
public void abc.xyz()
{
System.Console.WriteLine("In abc.xyz");
}
public void def.xyz()
{
System.Console.WriteLine("In def.xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void xyz();
}
Output
Collapse | Copy Codea.cs(13,15): error CS0106: The modifier 'public' is not valid for this item
a.cs(18,15): error CS0106: The modifier 'public' is not valid for this item
Bummer! We used the fully qualified name and we got an error. That's because when we use fully qualified names for functions whose prototypes are a part of interfaces, the compiler doesn't need decorators like public. So we decided to remove the access specifier public from the above program.
P15.cs
Collapse | Copy Codeclass Demo : abc, def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
abc refabc = refDemo;
refabc.xyz();
def refdef = refDemo;
refdef.xyz();
}
void abc.xyz()
{
System.Console.WriteLine("In abc.xyz");
}
void def.xyz()
{
System.Console.WriteLine("In def.xyz");
}
}
interface abc
{
void xyz();
}
interface def
{
void xyz();
}
Output
Collapse | Copy CodeHello Interfaces
In abc.xyz
In def.xyz
The above program compiles and runs successfully to produce a desired output. A fully qualified naming system allows us to define interfaces having same function prototypes. In the above example, interface abc and def contain the same function prototypes for function xyz(). Class Demo impliments both the interfaces. Using fully qualified names, it defines implementation of xyz that is specific to interface abc and implementation of xyz that is specific to interface def.
P16.cs
Collapse | Copy Codeclass Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
def refdef = refDemo;
refdef.xyz();
refdef.pqr();
}
public void xyz()
{
System.Console.WriteLine("In xyz");
}
public void pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
Output
Collapse | Copy CodeHello Interfaces
In xyz
In pqr
The above program compiles and runs successfully to produce a desired output. Interfaces support inheritance. Interface def inherits prototypes from interface abc. Class Demo implements the interface def. Interface variable refdef stores the reference to object of class Demo. Functions xyz() and pqr() of class Demo are invoked through interface reference variable refdef.
What do you think of the fully qualified names of xyz() and pqr() would be after interface def inherits from interface abc.
P17.cs
Collapse | Copy Codeclass Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
def refdef = refDemo;
refdef.xyz();
refdef.pqr();
}
void def.xyz()
{
System.Console.WriteLine("In xyz");
}
void def.pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
Output
Collapse | Copy CodeP17.cs(12,8): error CS0539: 'def.xyz' in explicit interface declaration is
not a member of interface
P17.cs(29,11): (Location of symbol related to previous error)
P17.cs(1,7): error CS0535: 'Demo' does not implement interface member
'abc.xyz()'
P17.cs(26,8): (Location of symbol related to previous error)
Bummer! The prototype of function xyz is an original member of interface abc. Thus, even if interface def inherits from the interface abc, the fully qualified name of the function xyz() remains as abc.xyz and not def.xyz as done in the above program. In fact, we got a compiler error. This can be fixed by using the correct fully qualified name of function xyz() as shown in the following program.
P18.cs
Collapse | Copy Codeclass Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
def refdef = refDemo;
refdef.xyz();
refdef.pqr();
}
void abc.xyz()
{
System.Console.WriteLine("In xyz");
}
void def.pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
Output
Collapse | Copy CodeHello Interfaces
In xyz
In pqr
The above program compiles and runs successfully to produce a desired output. But there are some pitfalls when using the fully qualified function names.
P19.cs
Collapse | Copy Codeclass Demo : def
{
public static void Main()
{
System.Console.WriteLine("Hello Interfaces");
Demo refDemo = new Demo();
refDemo.xyz();
refDemo.pqr();
}
void abc.xyz()
{
System.Console.WriteLine("In xyz");
}
void def.pqr()
{
System.Console.WriteLine("In pqr");
}
}
interface abc
{
void xyz();
}
interface def : abc
{
void pqr();
}
Output
Collapse | Copy CodeP19.cs(7,5): error CS0117: 'Demo' does not contain a definition for 'xyz'
P19.cs(8,5): error CS0117: 'Demo' does not contain a definition for 'pqr'
The above program fails to clear the compilation hurdle. refDemo refers to an object of class Demo. We are invoking xyz() using refDemo(). For C#, xyz() and ddd.xyz() are two different things. It knows that abc.xyz() exists. It also knows that just xyz() is nowhere in the class. That's why we get an error which says Class Demo does not contain a definition of xyz(). For C#, abc.xyz() can be invoked by an interface reference of type abc only. Similarly, def.pqr() can be invoked by an interface reference of type def only.
Bottom of Form
Introduction to inheritance, polymorphism in C#
Introduction
This little article is intended for rank .NET newbies who are making their first attempts at C# programming. I assume that they have done some elementary C++ programming and know what classes and member functions are. Using a few simple code snippets we'll see how C# supports inheritance and polymorphism.
Inheritance & Polymorphism
When you derive a class from a base class, the derived class will inherit all members of the base class except constructors, though whether the derived class would be able to access those members would depend upon the accessibility of those members in the base class. C# gives us polymorphism through inheritance. Inheritance-based polymorphism allows us to define methods in a base class and override them with derived class implementations. Thus if you have a base class object that might be holding one of several derived class objects, polymorphism when properly used allows you to call a method that will work differently according to the type of derived class the object belongs to.
Consider the following class which we'll use as a base class.
Collapse | Copy Code
class Animal
{
public Animal()
{
Console.WriteLine("Animal constructor");
}
public void Greet()
{
Console.WriteLine("Animal says Hello");
}
public void Talk()
{
Console.WriteLine("Animal talk");
}
public virtual void Sing()
{
Console.WriteLine("Animal song");
}
};
Now see how we derive another class from this base class.
Collapse | Copy Code
class Dog : Animal
{
public Dog()
{
Console.WriteLine("Dog constructor");
}
public new void Talk()
{
Console.WriteLine("Dog talk");
}
public override void Sing()
{
Console.WriteLine("Dog song");
}
};
Now try this code out.
Collapse | Copy Code
Animal a1 = new Animal();
a1.Talk();
a1.Sing();
a1.Greet();
//Output
Animal constructor
Animal talk
Animal song
Animal says Hello
Okay, that came out just as expected. Now try this code out.
Collapse | Copy Code
Animal a2 = new Dog();
a2.Talk();
a2.Sing();
a2.Greet();
//Output
Animal constructor
Dog constructor
Animal talk
Dog song
Animal says Hello
We have an object of type Animal, but it references an object of type Dog. Thus you can see the base class constructor getting called first followed by the derived class constructor. Now we call Talk() and find that the method that's executed is the base class method. That's not surprising when you consider that the object was declared to be of the base type which in our case is Animal. Now when we call Sing(), we find that the derived class method has got called. This is because in the base class the method is prototyped as public virtual void Sing() and in the derived class we have overridden it by using public override void Sing(). In C#, we need to explicitly use the override keyword as opposed to C++ where we didn't have to do that. And finally when we call Greet() the base class method gets called and this is not confusing at all specially since the derived class has not even implemented the method.
Now try the following code out.
Collapse | Copy Code
Dog d1 = new Dog();
d1.Talk();
d1.Sing();
d1.Greet();
//Output
Animal constructor
Dog constructor
Dog talk
Dog song
Animal says Hello
Okay, here everything came out as expected. No rude surprises there. The fact that we could invoke the Greet() method is proof of inheritance in C#, not that anyone had any doubts to begin with I guess. Now take a look at this new class we'll be using as a base class for some other classes.
Collapse | Copy Code
class Color
{
public virtual void Fill()
{
Console.WriteLine("Fill me up with color");
}
public void Fill(string s)
{
Console.WriteLine("Fill me up with {0}",s);
}
};
Now run this code out.
Collapse | Copy Code
Color c1 = new Color();
c1.Fill();
c1.Fill("red");
//Output
Fill me up with color
Fill me up with red
Okay, that went fine, I'd say. Now let's derive a class from this class.
Collapse | Copy Code
class Green : Color
{
public override void Fill()
{
Console.WriteLine("Fill me up with green");
}
};
Now let's try this code out.
Collapse | Copy Code
Green g1 = new Green();
g1.Fill();
g1.Fill("violet");
//Output
Fill me up with green
Fill me up with violet
Well, that went fine too. Thus if you have overloaded methods, you can mark some of them as virtual and override them in the derived class. It's not required that you have to override all the overloads. Now I want to demonstrate some stuff on overloaded constructors. For that we'll use the following base class.
Collapse | Copy Code
class Software
{
public Software()
{
m_x = 100;
}
public Software(int y)
{
m_x = y;
}
protected int m_x;
};
Now we'll derive a class from the above class.
Collapse | Copy Code
class MicrosoftSoftware : Software
{
public MicrosoftSoftware()
{
Console.WriteLine(m_x);
}
};
Now try this code out
Collapse | Copy Code
MicrosoftSoftware m1 = new MicrosoftSoftware();
//MicrosoftSoftware m2 = new MicrosoftSoftware(300); //won't compile
//Output
100
The base class had two overloaded constructors. One that took zero arguments and one that took an int. In the derived class we only have the zero argument constructor. Constructors are not inherited by derived classes. Thus we cannot instantiate a derived class object using the constructor that takes an int as parameter. As you will deduce from the output we got, the base class constructor that called was the default parameter-less constructor. Now take a look at this second derived class.
Collapse | Copy Code
class DundasSoftware : Software
{
//Here I am telling the compiler which
//overload of the base constructor to call
public DundasSoftware(int y) : base(y)
{
Console.WriteLine(m_x);
}
//Here we are telling the compiler to first
//call the other overload of the constructor
public DundasSoftware(string s, int f) : this(f)
{
Console.WriteLine(s);
}
};
Here we have two constructors, one that takes an int and one that takes a string and an int. Now lets try some code out.
Collapse | Copy Code
DundasSoftware du1 = new DundasSoftware(50);
//Output
50
DundasSoftware du2 = new DundasSoftware("test",75);
//Output
75
test
There, now that you've seen how it came out, things are a lot clearer I bet. You can use the this and base access keywords on other methods too, and not just on constructors.
Conclusion
This article does not discuss interfaces. At least not in it's current version. I'll probably add the usage of interfaces in the next update. But for now, I recommend that you read up on interfaces from elsewhere.
Operator Overloading
Let’s explain what operator overloading is all about with an example of a class that represents a date. Would it not be great if we could subtract two date objects and be returned an int representing the number of days elapsing between the two dates. We would like to use the good old subtraction operator – like we do when subtracting numbers. Also we would like the > operator to compare two date objects and tell us which one is larger. The + operator could add a number to a date resulting in a new date object.
Thus, operator overloading lets us redefine the existing operators so that they work with classes/objects we create like yyy. We have not yet instructed C# on how to use the trusty old + operator with two yyy objects. Though C# knows how to use the + to add two numbers, it does not know how to add two yyy’s.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
}
Compiler Error
a.cs(8,5): error CS0019: Operator ‘+’ cannot be applied to operands of type ‘yyy’ and ‘yyy’
We have created a simple class yyy which has one instance variable i which will distinguish different instances of yyy from each other. The constructor with an int as a parameter initializes i. We have tried to add two objects that look like yyy which does not go down well with C# and it objects to it.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public yyy operator + ( yyy x , yyy y)
{
}
}
Compiler Error
a.cs(18,12): error CS0558: User-defined operators ‘yyy.operator +(yyy, yyy)’ must be declared static and public
Error messages can be at times helpful. Our operator + is public but not static. C# demands that all operator overloads be static.
a.cs
public class zzz
{
public static void Main() {
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
System.Console.WriteLine(c.i);
}
}
public class yyy
{
public int i;
public yyy( int j) {
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Output
operator + 10 5
15
The word operator as the name of a function, is legal and the only way to overload operators. We follow this word with the operator we want to overload and then the parameters we will call the operator with. + is a binary operator and will need two yyy’s, one on its left and the other on its right. Then at beginning, we give the return value of the operator. In our case we want a + to add two yyy’s and return a third yyy whose i will be the sum of the individual i’s. Thus a+b will call the operator + with x being equal to a and y to b. Thus x.i will have a value 10 and y.i, 5. We are creating a new object z and in the constructor passing 15 i.e. 10 + 5. Thus the i of z will be 15 which is being returned. a + b will now be replaced by the object whose i has a value 15 and c will be equal to this object. Thus c.i will be equal to 15.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c;
c = a + b ;
System.Console.WriteLine(c.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator = ( yyy x , yyy y)
{
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Compiler Error
a.cs(19,28): error CS1020: Overloadable binary operator expected
The error message is telling us that we cannot overload the assignment operator =. Every class gets a free assignment operator which does a bitwise copy of the variables of the object from the left to the right.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy c = new yyy(2);
yyy d;
d = a + b + c ;
System.Console.WriteLine(d.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Output
Operator + 10 5
Operator + 15 2
17
The only change is d = a + b + c. C# gets easily confused with complex statements so it does not read all of it. It sees two operators on the same line. In this case, the same plus. An internal rule tells it to read the plus left to right i.e. it will only see a + b. It will call the operator + with x.i as 10 and y.i as 5 because a’s i is 10 and b’s i is 5. This will create a temporary object like yyy whose i is 15, lets call it zz. The object z is very different from zz. C# then evaluates zz + c. Thus x.i will display 15 and y.i will have the value of c.i i.e. 2. To support multiple invocations of the operator on a single line, the code does not change.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
int d = a + b ;
System.Console.WriteLine(d);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static int operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
return x.i + y.i;
}
}
Output
operator + 10 5
15
C# does not and will never understand what addition of two yyy’s is all about. It is in your hands to decide what the code accomplishes. You decide whether the overloaded + returns a yyy or an int object. The class yyy is your creation not C#’s. Hence you decide what addition means in the context of a yyy class. In this case, we are returning an int unlike earlier where we returned a yyy.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
int d = a + b ;
System.Console.WriteLine(d);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static int operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
return x.i + y.i;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Compiler Error
a.cs(23,19): error CS0111: Class ‘yyy’ already defines a member called ‘ op_Addition ‘ with the same parameter types
You cannot have two operator + overloads which only differ in return types. Also the error messages change the name of the operator from + to op_Addition. When we overloaded functions, the return type was not considered part of the function signature. The same applies for operators.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy d = a + b + 20;
System.Console.WriteLine(d.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
}
Compiler Error
a.cs(7,9): error CS0019: Operator ‘+’ cannot be applied to operands of type ‘yyy’ and ‘int’
C# is now telling you that you can add two yyy’s but cannot do the same, i.e. add a yyy and an int as we have not told C# how to do so.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
yyy d = a + b + 20;
System.Console.WriteLine(d.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static yyy operator + ( yyy x , yyy y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y.i);
yyy z = new yyy(x.i+y.i);
return z;
}
public static yyy operator + ( yyy x , int y)
{
System.Console.WriteLine(“operator + “ + x.i + “ “ + y);
yyy z = new yyy(x.i+y);
return z;
}
}
Output
Operator + 10 5
Operator + 15 20
35
Life is fun in the fast lane. As we could have a large number of functions with the same name but differing number of parameters, ditto for operators. a + b as usual calls the first operator +. This as usual creates a temp object, say zz and now C# reads the line as zz + 20. This matches the second operator + which now gets called. You can have over a million plus operators with differing parameters if you desire.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
if ( a > b )
System.Console.WriteLine(“true”);
else
System.Console.WriteLine(“false”);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static bool operator > ( yyy x , yyy y)
{
System.Console.WriteLine(“operator < “ + x.i + “ “ + y.i);
return x.i > y.i;
}
}
Compiler Error
a.cs(20,20): error CS0216: The operator ‘yyy.operator >(yyy, yyy)’ requires a matching operator ‘<‘ to also be defined
C# is a romantic at heart and loves pairs. We tried to overload the > operator and C# tells us that we have to also overload the < operator. It makes sense as a user would want to know whether a yyy is greater than or less than another yyy.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
yyy b = new yyy(5);
if ( a > b )
System.Console.WriteLine(“true”);
else
System.Console.WriteLine(“false”);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static bool operator > ( yyy x , yyy y)
{
System.Console.WriteLine(“operator > “ + x.i + “ “ + y.i);
return x.i > y.i;
}
public static bool operator < ( yyy x , yyy y)
{
System.Console.WriteLine(“operator < “ + x.i + “ “ + y.i);
return x.i < y.i;
}
}
Output
operator > 10 5
true
The operator < returns a bool as we would like to use it as part of an if or a while. In this case we are using it as part of an if and nothing stops us from using the < overloaded for ints and yyy’s to return a bool. What code you write in an operator is entirely your decision. The < operator looks like the + and can take different parameters. To overload the !=, you also have to overload the ==.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
System.Console.WriteLine(a.ToString());
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
}
Output
yyy
yyy
In the first WriteLine function to be called, we are passing the object a whereas the first parameter to WriteLine should be a string. Also we do not get an error and we see yyy displayed. A longtime back we told you that all classes finally derive from object. The class object has a function ToString. Thus calling the ToString function off a produces the same output as the above line. We have not created the ToString function. So either we got a free ToString implementation from C# like we get a free Constructor or the ToString function of object in some way determines the name of our class and returns it as a string.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
System.Console.WriteLine(a.ToString());
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Compiler Warning
a.cs(17,15): warning CS0114: ‘yyy.ToString()’ hides inherited member ‘object.ToString()’. To make the current method override that implementation, add the override keyword. Otherwise add the new keyword.
It is the same warning if a function exists in the base class.
Output
yyy
ToString
mukhi
WriteLine displays yyy and a.ToString displays mukhi. Which means that they call different ToString functions. The WriteLine(a) calls the ToString of object whereas the second WriteLine calls it of yyy. If we want to override a function in the base class, we have to specifically do so by using the modifier override. If we do not, the default is to call the base class ToString. All this has been explained earlier, in any case.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
System.Console.WriteLine(a.ToString());
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
ToString
mukhi
ToString
mukhi
Now both the System.Console.WriteLine calls the ToString function of yyy. We would like to convert a yyy into a string or an int for example. These type conversions are a major part of operator overloading.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
System.Console.WriteLine(a);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static implicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator string
string 10
In spite of having a function ToString, it does not get called unlike earlier. After the keyword operator we have the name of a data type i.e. string. This function is called whenever we want to convert our object into a string. The parameter y stands for the object to be converted. In this function we can write whatever code we want to but we must return a string. In our case we return the text string concatenated with the current value of i.
Once again, the WriteLine function requires a string class. We are offering a yyy class. C# checks whether there is an operator string which is available to convert a yyy into a string. As there is one, it gets called. The word implicit means that we are indirectly implying that it should be called. Lets explain this with another example.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = a;
System.Console.WriteLine(s);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Compiler Error
a.cs(7,5): error CS0029: Cannot implicitly convert type ‘yyy’ to ‘string’
We have changed the word implicit which means imply. It also means giving a hint with the word explicit which means specify. Had we not changed implicit with explicit, we would have got no error and C# would have called the operator to convert a into a string and initialize s to it.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = (string)a;
System.Console.WriteLine(s);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator string
string 10
The () is called a cast and it takes any data type within brackets. We are explicitly asking for a conversion to a string and unlike earlier we are not being implicit but explicit.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = (string)a;
System.Console.WriteLine(s);
System.Console.WriteLine(a);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator string
string 10
ToString
mukhi
The explicit will get called only when we cast and as we do not have an implicit modifier, the ToString gets called. We get no error if we do not have an implicit modifier.
a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy(10);
string s;
s = (string)a;
System.Console.WriteLine(s);
System.Console.WriteLine(a);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public static explicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public static implicit operator string(yyy y)
{
System.Console.WriteLine(“operator string”);
return “string “ + y.i;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Compiler Error
a.cs(24,15): error CS0557: Duplicate user-defined conversion in class ‘yyy’
We cannot have both the implicit and explicit modifier as two separate functions. Thus you have to decide which one you would want to implement.
a.cs
public class zzz
{
public static void Main()
{
yyy a ;
a = 10;
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
a.cs(7,5): error CS0029: Cannot implicitly convert type ‘int’ to ‘yyy’
One more error. Here we are trying to equate a yyy to an int but unlike earlier, we have not created an object like yyy by saying new. We would need someone to create the yyy object and initialize it to 10, an int.
a.cs
public class zzz
{
public static void Main()
{
yyy a ;
a = 10;
System.Console.WriteLine(a.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
static public implicit operator yyy(int v)
{
System.Console.WriteLine(“operator yyy int “ + v);
yyy z = new yyy(v);
return z;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator yyy int 10
10
A constructor has the same name as the name of the class. Thus operator yyy may double up as a constructor. When we write a = 10, C# calls this constructor and passes the parameter v a value, 10. Operator yyy has now to create an object that looks like yyy and return it. Thus it does not act like a constructor in the sense that a constructor is responsible for creating the object. In other words, writing a = 10, creates a new object that looks like yyy and initializes it to 10. It is different from what we did earlier as previously the operator did not have to create an object that looks like yyy. In this case it has to.
a.cs
public class zzz
{
public static void Main()
{
yyy a ;
a = “Hi”;
System.Console.WriteLine(a.i);
}
}
public class yyy
{
public int i;
public yyy( int j)
{
i = j;
}
static public implicit operator yyy(int v)
{
System.Console.WriteLine(“operator yyy int “ + v);
yyy z = new yyy(v);
return z;
}
static public implicit operator yyy(string v)
{
System.Console.WriteLine(“operator yyy string “ + v);
yyy z = new yyy(100);
return z;
}
public override string ToString()
{
System.Console.WriteLine(“ToString”);
return “mukhi”;
}
}
Output
operator yyy string Hi
100
We can have as many operator yyy functions as we like, provided we follow the rules of function overloading. Thus we have two of them, one that takes a string, another that takes an int. In this case as we are writing a = “hi”, the second operator that accepts a string get called. They all have to return an object that looks like yyy.
a = (short) 10;
Had we written the above line, we will not get any errors. We assumed we will get an error as we do not have an operator yyy which takes a short as a parameter. C# is highly intelligent. It first checks whether we have an operator yyy that matches what we wrote. In no case, there is a match. It will then check whether there is any other way it can prevent an error from being signaled. C# realizes that there is an operator yyy which accepts an int. Thus it converts a short to an int and then calls the operator yyy with the int parameter.
Six important concept STACK,HEAP,VALUES TYPe,REFERENCE TYPe,BOXING AND UNBOXING
Introduction
This article will explain six important concepts: stack, heap, value types, reference types, boxing, and unboxing. This article starts explaining what happens internally when you declare a variable and then it moves ahead to explain two important concepts: stack and heap. The article then talks about reference types and value types and clarifies some of the important fundamentals around them.
The article concludes by demonstrating how performance is hampered due to boxing and unboxing, with a sample code.
Watch my 500 videos on various topics like design patterns, WCF, WWF, WPF, LINQ, Silverlight, UML, SharePoint, Azure, VSTS, and a lot more: click here. You can also catch me on my trainings here.
Image taken from http://michaelbungartz.wordpress.com/.
What goes inside when you declare a variable?
When you declare a variable in a .NET application, it allocates some chunk of memory in the RAM. This memory has three things: the name of the variable, the data type of the variable, and the value of the variable.
That was a simple explanation of what happens in the memory, but depending on the data type, your variable is allocated that type of memory. There are two types of memory allocation: stack memory and heap memory. In the coming sections, we will try to understand these two types of memory in more detail.
Stack and heap
In order to understand stack and heap, let’s understand what actually happens in the below code internally.Collapse | Copy Code
Collapse | Copy Code
public void Method1()
{
// Line 1
int i=4;
// Line 2
int y=2;
//Line 3
class1 cls1 = new class1();
}
It’s a three line code, let’s understand line by line how things execute internally.
- Line 1: When this line is executed, the compiler allocates a small amount of memory in the stack. The stack is responsible for keeping track of the running memory needed in your application.
- Line 2: Now the execution moves to the next step. As the name says stack, it stacks this memory allocation on top of the first memory allocation. You can think about stack as a series of compartments or boxes put on top of each other.
Memory allocation and de-allocation is done using LIFO (Last In First Out) logic. In other words memory is allocated and de-allocated at only one end of the memory, i.e., top of the stack.
- Line 3: In line 3, we have created an object. When this line is executed it creates a pointer on the stack and the actual object is stored in a different type of memory location called ‘Heap’. ‘Heap’ does not track running memory, it’s just a pile of objects which can be reached at any moment of time. Heap is used for dynamic memory allocation.
Exiting the method (the fun): Now finally the execution control starts exiting the method. When it passes the end control, it clears all the memory variables which are assigned on stack. In other words all variables which are related to int data type are de-allocated in ‘LIFO’ fashion from the stack.
The big catch – It did not de-allocate the heap memory. This memory will be later de-allocated by the garbage collector.
Now many of our developer friends must be wondering why two types of memory, can’t we just allocate everything on just one memory type and we are done?
If you look closely, primitive data types are not complex, they hold single values like ‘int i = 0’. Object data types are complex, they reference other objects or other primitive data types. In other words, they hold reference to other multiple values and each one of them must be stored in memory. Object types need dynamic memory while primitive ones needs static type memory. If the requirement is of dynamic memory, it’s allocated on the heap or else it goes on a stack.
Image taken from http://michaelbungartz.wordpress.com/
Value types and reference types
Now that we have understood the concept of Stack and Heap, it’s time to understand the concept of value types and reference types. Value types are types which hold both data and memory on the same location. A reference type has a pointer which points to the memory location.
Below is a simple integer data type with name i whose value is assigned to another integer data type with name j. Both these memory values are allocated on the stack.
When we assign the int value to the other int value, it creates a completely different copy. In other words, if you change either of them, the other does not change. These kinds of data types are called as ‘Value types’.
When we create an object and when we assign an object to another object, they both point to the same memory location as shown in the below code snippet. So when we assign obj to obj1, they both point to the same memory location.
In other words if we change one of them, the other object is also affected; this is termed as ‘Reference types’.
So which data types are ref types and which are value types?
In .NET depending on the data type, the variable is either assigned on the stack or on the heap. ‘String’ and ‘Objects’ are reference types, and any other .NET primitive data types are assigned on the stack. The figure below explains the same in a more detail manner.
Boxing and unboxing
Wow, you have given so much knowledge, so what’s the use of it in actual programming? One of the biggest implications is to understand the performance hit which is incurred due to data moving from stack to heap and vice versa.
Consider the below code snippet. When we move a value type to reference type, data is moved from the stack to the heap. When we move a reference type to a value type, the data is moved from the heap to the stack.
This movement of data from the heap to stack and vice-versa creates a performance hit.
When the data moves from value types to reference types, it is termed ‘Boxing’ and the reverse is termed ‘UnBoxing’.
If you compile the above code and see the same in ILDASM, you can see in the IL code how ‘boxing’ and ‘unboxing’ looks. The figure below demonstrates the same.
Performance implication of boxing and unboxing
In order to see how the performance is impacted, we ran the below two functions 10,000 times. One function has boxing and the other function is simple. We used a stop watch object to monitor the time taken.
The boxing function was executed in 3542 ms while without boxing, the code was executed in 2477 ms. In other words try to avoid boxing and unboxing. In a project where you need boxing and unboxing, use it when it’s absolutely necessary.
With this article, sample code is attached which demonstrates this performance implication.
Currently I have not included source code for unboxing but the same holds true for it. You can write code and experiment it using the stopwatch class.
Understanding Delegates
The C# Column - Yashawant Kanetkar
A delegate is an important element of C# and is extensively used in every type of .NET application. A delegate is a class whose object (delegate object) can store a set of references to methods. This delegate object is used to invoke the methods. Many developers find delegates complicated. But believe me, it’s a simple concept to understand. In this article we will see how delegates work and in what situations they are used.
Let’s start with a simple program that shows how to declare and use a delegate.
class sample
{
delegate void del1();
delegate void del2 (int i);
public void fun()
{
del1 d1 = new del1 (f1);
d1();
del2 d2 = new del2 (f2) ;
d2 ( 5 ) ;
}
public void f1()
{
Console.WriteLine (“Reached in f1”) ;
}
public void f2 (int i)
{
Console.WriteLine (“Reached in f2”) ;
}
}
In the sample class we have declared two delegates—del1 and del2. The statement delegate void del1( ) ;
indicates that the delegate del1 is going to encapsulate methods, which takes no parameter and returns void. When this statement is encountered, a class del1 derived from a pre-defined class MultiCastDelegate gets created. Similarly, the statement delegate void del2 ( int i ) ; indicates that the delegate del2 will be used for methods taking one integer and returning a void. This statement would create another class del2 derived from the MultiCastDelegate class. The classes del1 and del2 are called ‘delegate classes’. To use the delegate class, like any other class, we have to declare its reference. We have declared the reference to delegate class del1 in the fun( ) method through the statement del1 d1 = new del1 ( f1 ) ;
This would create a delegate object d1. To the constructor of the delegate class we have passed the address of the method f1( ). C++ programmers may know that mentioning a method name without parentheses represents its address. The delegate object would now hold an address of the method f1( ). Next, we have called the f1( ) method using the delegate object d1. This is achieved using the statement d1( ) ;
If d1 is an object, how can we use it as if it is a method? Actually, the call d1( ) gets converted into a call to the d1.Invoke( ) method. The Invoke( ) method calls the f1( ) method using its address stored in delegate object. A delegate can contain references to multiple methods. In this case a single call to Invoke( ) calls all the methods.
Similar to d1 we have instantiated another delegate object d2 and stored in it an address of the method f2( ). As the method f2( ) takes an integer as a parameter we pave passed 5 to d2( ). The value 5 would get passed to all the methods whose references are stored in this delegate object. This makes it obvious that the signature of the delegate and that of the methods to be invoked using the delegate must be identical.
If we create an object of sample class and call the fun( ) method both the f1( ) and f2( ) methods would get called through d1 and d2 respectively.
Delegates make possible calling of methods using reference to methods the object oriented way. This avoids using any complex technique like pointers to functions.
Delegates in Inheritance
Suppose there is a base class and a class derived from this class. A method is invoked from a base class method using a delegate. We can initialise this delegate in derived class so that when the method is invoked from the base class it is the derived class’s method that would get called. Here is the program that works similar to this situation.
using System;
namespace delegateinherit
{
public delegate void del1();
class mybase
{
public del1 d;
public void fun()
{
d();
}
}
class der : mybase
{
public der()
{
d = new del1 (f1);
fun();
d = new del1 (f2);
fun();
}
public void f1()
{
Console.WriteLine (“Reached in f1”) ;
}
public void f2()
{
Console.WriteLine (“Reached in f2”) ;
}
}
class Class1
{
static void Main (string[] args)
{
der d = new der();
}
}
}
Here, from the fun( ) method of the mybase class we have used the delegate object d to invoke a method. The fun( ) method is called twice from the constructor of the derived class der. Before calling fun( ) method, we have associated the delegate d, first with method f1( ) and then with f2( ). Thus, if we create an object of the der class, first the f1( ) and then f2( ) method get called. We can invoke both the methods in a single call to fun( ) as shown below.
d = new del1 ( f1 ) ;
d += new del1 ( f2 ) ;
fun( ) ;
Where Delegates are useful
In a general WinForm application, a class Form1 gets created, which is derived from the Form class. If we want to handle mouse click messages, we override the OnMouseDown( ) message handler in the Form1 class. When we click the mouse button, control reaches to the OnMouseDown( ) of the derived class i.e Form1 class because of the simple rule of inheritance. But if we click on a push button on the form, the OnMouseDown( ) of the Form1 class does not get called. Because Form1 class is not derived from the class that creates button. In such a situation, delegates prove useful. Calling methods using delegate require only that the signature of methods and that of the delegate should match. It does not require any inheritance chain to call the appropriate method. So, in .NET, all the event handlers are called through delegates, instead of relying on the inheritance chain.
Delegate at work
As said earlier, all the event handlers are called using delegates. We will now see a dummy program to explain how the Paint event handler must be getting called using a delegate.
using System;
namespace delegateatwork
{
public delegate void PaintHandler();
class Form
{
public PaintHandler Paint ;
public void OnPaint()
{
Paint();
}
}
class form1 : Form
{
public form1()
{
Paint += new PaintHandler (form1_Paint);
OnPaint() ;
}
public void form1_Paint()
{
Console.WriteLine (“form1_Paint”);
}
}
class Class1
{
static void Main (string[] args)
{
form1 f = new form1();
}
}
}
We have designed a class Form1 that contains a method called Form1_Paint( ). The Form1 class is derived from the Form class. In the Form class we have declared an object Paint of the delegate class PaintHandler. In Main( ) we have instantiated an object of the Form1 class. This results in its constructor being called. In the constructor of the Form1 class we have initialised the Paint object and encapsulated in it the Form1_Paint( ) method. Next we have called the OnPaint( ) method of the Form class (in WinForm application Paint event gets generated automatically), which in turn calls the Form1_Paint( ) method via Paint.
Datalist
Datalist
DataList is a data bound list control that displays items using certain templates defined at the design time. The content of the DataList control is manipulated by using templates sections such as AlternatingItemTemplate, EditItemTemplate, FooterTemplate, HeaderTemplate, ItemTemplate, SelectedItemTemplate and SeparatorTemplate. Each of these sections has its own characteristics to be defined but at a very minimum, the ItemTemplate needs to be defined to display the items in the DataList control. Other sections can be used to provide additional look and feel to the DataList control.
The contents of the DataList control can be manipulated by using templates. The following table lists the supported templates.
The DataList control displays data items in a repeating list, and optionally supports selecting and editing the items. The content and layout of list items in DataList is defined using templates. At a minimum, every DataList must define an ItemTemplate; however, several optional templates can be used to customize the appearance of the list.
AlternatingItemTemplate: If defined, provides the content and layout for alternating items in the DataList. If not defined, ItemTemplate is used.
EditItemTemplate: If defined, provides the content and layout for the item currently being edited in the DataList. If not defined, ItemTemplate is used.
FooterTemplate: If defined, provides the content and layout for the footer section of the DataList. If not defined, a footer section will not be displayed.
HeaderTemplate: If defined, provides the content and layout for the header section of the DataList. If not defined, a header section will not be displayed.
ItemTemplate: Required template that provides the content and layout for items in the DataList.
SelectedItemTemplate: If defined, provides the content and layout for the currently selected item in the DataList. If not defined, ItemTemplate is used.
SeparatorTemplate: If defined, provides the content and layout for the separator between items in the DataList. If not defined, a separator will not be displayed.
At the very minimum, the ItemTemplate needs to be defined to display the items in the DataList control. Additional templates can be used to provide a custom look to the DataList control.
1.1 What is C#?
C# is a general-purpose object-oriented programming language designed by Microsoft. It is loosely based on C/C++, and is very similar to Java. You can download the C# 3.0 spec here.1.2 How do I develop C# apps?
Visual C# Express is the easiest way to get started. On Linux you can use Mono.1.3 Does C# replace C++?
There are three options open to the Windows developer from a C++ background:- Stick with standard C++. Don't use .NET at all.
- Use C++ with .NET. Microsoft supply a .NET C++ compiler that produces IL rather than machine code. (To make full use of the .NET environment (e.g. garbage collection), a set of extensions are required to standard C++, called C++/CLI.)
- Forget C++ and use C#.
1.4 Does C# have its own class library?
Not exactly. The .NET Framework has a comprehensive class library, which C# can make use of. C# does not have its own class library.2. Types
2.1 What standard types does C# use?
C# supports a very similar range of basic types to C++, including int, long, float, double, char, string, arrays, structs and classes. However, don't assume too much. The names may be familiar, but many of the details are different. For example, a long is 64 bits in C#, whereas in C++ the size of a long depends on the platform (typically 32 bits on a 32-bit platform, 64 bits on a 64-bit platform). Also classes and structs are almost the same in C++ - this is not true for C#. Finally, chars and strings in .NET are 16-bit (Unicode/UTF-16), not 8-bit like C++.2.2 Is it true that all C# types derive from a common base class?
Yes and no. All types can be treated as if they derive from object (System.Object), but in order to treat an instance of a value type (e.g. int, float) as object-derived, the instance must be converted to a reference type using a process called 'boxing'. In theory a developer can forget about this and let the run-time worry about when the conversion is necessary, but in reality this implicit conversion can have side-effects that may trip up the unwary.2.3 So I can pass an instance of a value type to a method that takes an object as a parameter?
Yes. For example:class CApplication
{
public static void Main()
{
int x = 25;
string s = "fred";
DisplayMe( x );
DisplayMe( s );
}
static void DisplayMe( object o )
{
System.Console.WriteLine( "You are {0}", o );
}
}
This would display:
You are 25
You are fred
2.4 What are the fundamental differences between value types and reference types?
C# divides types into two categories - value types and reference types. Most of the intrinsic types (e.g. int, char) are value types. Structs are also value types. Reference types include classes, arrays and strings. The basic idea is straightforward - an instance of a value type represents the actual data, whereas an instance of a reference type represents a pointer or reference to the data.The most confusing aspect of this for C++ developers is that C# has predetermined which types are represented as values, and which are represented as references. A C++ developer expects to take responsibility for this decision.
For example, in C++ we can do this:
int x1 = 3; // x1 is a value on the stack
int *x2 = new int(3) // x2 is a pointer to a value on the heap
but in C# there is no control:
int x1 = 3; // x1 is a value on the stack
int x2 = new int();
x2 = 3; // x2 is also a value on the stack!
2.5 Okay, so an int is a value type, and a class is a reference type. How can int be derived from object?
It isn't, really. When an int is being used as an int, it is a value. However, when it is being used as an object, it is a reference to an integer value (on the managed heap). In other words, when you treat an int as an object, the runtime automatically converts the int value to an object reference. This process is called boxing. The conversion involves copying the int to the heap, and creating an object instance which refers to it. Unboxing is the reverse process - the object is converted back to a value.int x = 3; // new int value 3 on the stack
object objx = x; // new int on heap, set to value 3 - still have x=3 on stack
int y = (int)objx; // new value 3 on stack, still got x=3 on stack and objx=3 on heap
2.6 Are C# references the same as C++ references?
Not quite. The basic idea is the same, but one significant difference is that C# references can be null . So you cannot rely on a C# reference pointing to a valid object. In that respect a C# reference is more like a C++ pointer than a C++ reference. If you try to use a null reference, a NullReferenceException is thrown.For example, look at the following method:
void displayStringLength( string s )
{
Console.WriteLine( "String is length {0}", s.Length );
}
The problem with this method is that it will throw a NullReferenceException if called like this:
string s = null;
displayStringLength( s );
Of course for some situations you may deem a NullReferenceException to be a perfectly acceptable outcome, but in this case it might be better to re-write the method like this:
void displayStringLength( string s )
{
if( s == null )
Console.WriteLine( "String is null" );
else
Console.WriteLine( "String is length {0}", s.Length );
}
2.7 Can I use typedefs in C#?
No, C# has no direct equivalent of the C++ typedef. C# does allow an alias to be specified via the using keyword:using IntList = System.Collections.Generic.List<int>;
but the alias only applies in the file in which it is declared. A workaround in some cases is to use inheritance:
public class IntList : List<int> { }
The pros and cons of this approach are discussed here.
3. Classes and Structs
3.1 Structs are largely redundant in C++. Why does C# have them?
In C++, a struct and a class are pretty much the same thing. The only difference is the default visibility level (public for structs, private for classes). However, in C# structs and classes are very different. In C#, structs are value types (instances stored directly on the stack, or inline within heap-based objects), whereas classes are reference types (instances stored on the heap, accessed indirectly via a reference). Also structs cannot inherit from structs or classes, though they can implement interfaces. Structs cannot have destructors. A C# struct is much more like a C struct than a C++ struct.3.2 Does C# support multiple inheritance (MI)?
No, though it does support implementation of multiple interfaces on a single class or struct.3.3 Is a C# interface the same as a C++ abstract class?
No, not quite. An abstract class in C++ cannot be instantiated, but it can (and often does) contain implementation code and/or data members. A C# interface cannot contain any implementation code or data members - it is simply a group of method names & signatures. A C# interface is more like a COM interface than a C++ abstract class.3.4 Are C# constructors the same as C++ constructors?
Very similar, but there are some significant differences. First, C# supports constructor chaining. This means one constructor can call another:class Person
{
public Person( string name, int age ) { ... }
public Person( string name ) : this( name, 0 ) {}
public Person() : this( "", 0 ) {}
}
Another difference is that virtual method calls within a constructor are routed to the most derived implementation - see Can I Call a virtual method from a constructor.
Error handling is also somewhat different. If an exception occurs during construction of a C# object, the destuctor (finalizer) will still be called. This is unlike C++ where the destructor is not called if construction is not completed. (Thanks to Jon Jagger for pointing this out.)
Finally, C# has static constructors. The static constructor for a class runs before the first instance of the class is created.
Also note that (like C++) some C# developers prefer the factory method pattern over constructors. See Brad Wilson's article.
3.5 Are C# destructors the same as C++ destructors?
No. They look the same but they are very different. The C# destructor syntax (with the familiar ~ character) is just syntactic sugar for an override of the System.Object Finalize method. This Finalize method is called by the garbage collector when it determines that an object is no longer referenced, before it frees the memory associated with the object. So far this sounds like a C++ destructor. The difference is that the garbage collector makes no guarantees about when this procedure happens. Indeed, the algorithm employed by the CLR garbage collector means that it may be a long time after the application has finished with the object. This lack of certainty is often termed 'non-deterministic finalization', and it means that C# destructors are not suitable for releasing scarce resources such as database connections, file handles etc.To achieve deterministic destruction, a class must offer a method to be used for the purpose. The standard approach is for the class to implement the IDisposable interface. The user of the object must call the Dispose() method when it has finished with the object. C# offers the 'using' construct to make this easier.
Note that it's rarely necessary to define a destructor for a C# class - it only makes sense where the class holds direct references to unmanaged resources, which is very unusual. Implementing IDisposable is somewhat more commonly required, but still only necessary for a small minority of classes.
3.6 If C# destructors are so different to C++ destructors, why did MS use the same syntax?
Presumably they wanted C++ programmers to feel at home. I think they made a mistake.3.7 Are all methods virtual in C#?
No. Like C++, methods are non-virtual by default, but can be marked as virtual.3.8 How do I declare a pure virtual function in C#?
Use the abstract modifier on the method. The class must also be marked as abstract. Note that abstract methods cannot have an implementation (unlike pure virtual C++ methods).3.9 Can I call a virtual method from a constructor/destructor?
Yes, but it's generally not a good idea. The mechanics of object construction in .NET are quite different from C++, and this affects virtual method calls in constructors.C++ constructs objects from base to derived, so when the base constructor is executing the object is effectively a base object, and virtual method calls are routed to the base class implementation. By contrast, in .NET the derived constructor is executed first, which means the object is always a derived object and virtual method calls are always routed to the derived implementation. (Note that the C# compiler inserts a call to the base class constructor at the start of the derived constructor, thus preserving standard OO semantics by creating the illusion that the base constructor is executed first.)
The same issue arises when calling virtual methods from C# destructors. A virtual method call in a base destructor will be routed to the derived implementation.
3.10 Should I make my destructor virtual?
A C# destructor is really just an override of the System.Object Finalize method, and so is virtual by definition.4. Exceptions
4.1 Can I use exceptions in C#?
Yes, in fact exceptions are the recommended error-handling mechanism in C# (and in .NET in general). Most of the .NET framework classes use exceptions to signal errors.4.2 What types of object can I throw as exceptions?
Only instances of the System.Exception classes, or classes derived from System.Exception. This is in sharp contrast with C++ where instances of almost any type can be thrown.4.3 Can I define my own exceptions?
Yes, just derive your exception class from System.Exception.Note that if you want your exception to cross remoting boundaries you'll need to do some extra work - see http://www.thinktecture.com/Resources/RemotingFAQ/CustomExceptions.html for details.
4.4 Does the System.Exception class have any cool features?
Yes - the feature which stands out is the StackTrace property. This provides a call stack which records where the exception was thrown from. For example, the following code:using System;
class CApp
{
public static void Main()
{
try
{
f();
}
catch( Exception e )
{
Console.WriteLine( "System.Exception stack trace = \n{0}", e.StackTrace );
}
}
static void f()
{
throw new Exception( "f went pear-shaped" );
}
}
produces this output:
System.Exception stack trace =
at CApp.f()
at CApp.Main()
Note, however, that this stack trace was produced from a debug build. A release build may optimise away some of the method calls which could mean that the call stack isn't quite what you expect.
4.5 When should I throw an exception?
This is the subject of some debate, and is partly a matter of taste. However, it is accepted by most that exceptions should be thrown only when an 'unexpected' error occurs. How do you decide if an error is expected or unexpected? This is a judgement call, but a straightforward example of an expected error is failing to read from a file because the seek pointer is at the end of the file, whereas an example of an unexpected error is failing to allocate memory from the heap.4.6 Does C# have a 'throws' clause?
No, unlike Java, C# does not require (or even allow) the developer to specify the exceptions that a method can throw.5. Run-time Type Information
5.1 How can I check the type of an object at runtime?
You can use the is keyword. For example:using System;
class CApp
{
public static void Main()
{
string s = "fred";
long i = 10;
Console.WriteLine( "{0} is {1}an integer", s, (IsInteger(s) ? "" : "not ") );
Console.WriteLine( "{0} is {1}an integer", i, (IsInteger(i) ? "" : "not ") );
}
static bool IsInteger( object obj )
{
if( obj is int || obj is long )
return true;
else
return false;
}
}
produces the output:
fred is not an integer
10 is an integer
5.2 Can I get the name of a type at runtime?
Yes, use the GetType method of the object class (which all types inherit from). For example:using System;
class CTest
{
class CApp
{
public static void Main()
{
long i = 10;
CTest ctest = new CTest();
DisplayTypeInfo( ctest );
DisplayTypeInfo( i );
}
static void DisplayTypeInfo( object obj )
{
Console.WriteLine( "Type name = {0}, full type name = {1}", obj.GetType(), obj.GetType().FullName );
}
}
}
produces the following output:
Type name = CTest, full type name = CTest
Type name = Int64, full type name = System.Int64
5.3 What is the difference between typeof and GetType()?
Apart from the obvious (i.e. typeof operates on a type whereas GetType operates on an object), the main thing to watch out for is that GetType returns the underlying type of the object, which may not be the same as the type of the reference to the object. For example:class Base { }
class Derived : Base { }
class Program
{
static void Main()
{
ShowType( new Derived() );
}
static void ShowType( Base b )
{
Console.WriteLine(typeof(Base));
Console.WriteLine(b.GetType());
}
}
gives the following output:
Base
Derived
6. Miscellaneous
6.1 How do I do a case-insensitive string comparison?
Use the string.Compare method. Its third parameter specifies case sensitivity."fred" == "Fred" // false
string.Compare( "fred", "Fred", StringComparison.CurrentCultureIgnoreCase ) == 0 // true
For more control over the comparison, e.g. exotic features like width-sensitivity, consider using System.Globalization.CompareInfo.Compare(), e.g.
CultureInfo.CurrentCulture.CompareInfo.Compare(
"fred", "Fred",
CompareOptions.IgnoreCase |
CompareOptions.IgnoreKanaType |
CompareOptions.IgnoreWidth
);
6.2 Does C# support a variable number of arguments?
Yes, using the params keyword. The arguments are specified as a list of arguments of a specific type, e.g. int. For ultimate flexibility, the type can be object. The standard example of a method which uses this approach is System.Console.WriteLine().6.3 How can I process command-line arguments?
Like this:using System;
class CApp
{
public static void Main( string[] args )
{
Console.WriteLine( "You passed the following arguments:" );
foreach( string arg in args )
Console.WriteLine( arg );
}
}
(Take a look at Charles Cook's NOptFunc project for easy command-line parsing.)
6.4 Does C# do array bounds checking?
Yes. An IndexOutOfRange exception is used to signal an error.6.5 How can I make sure my C# classes will interoperate with other .NET languages?
Make sure your C# code conforms to the Common Language Subset (CLS). To help with this, add the [assembly:CLSCompliant(true)] global attribute to your C# source files. The compiler will emit an error if you use a C# feature which is not CLS-compliant.6.6 How do I use the 'using' keyword with multiple objects?
You can nest using statements, like this:using( obj1 )
{
using( obj2 )
{
...
}
}
However consider using this more aesthetically pleasing (but functionally identical) formatting:
using( obj1 )
using( obj2 )
{
...
}
6.7 What is the difference between == and object.Equals?
For value types, == and Equals() usually compare two objects by value. For example:int x = 10;
int y = 10;
Console.WriteLine( x == y );
Console.WriteLine( x.Equals(y) );
will display:
True
True
However things are more complex for reference types. Generally speaking, for reference types == is expected to perform an identity comparison, i.e. it will only return true if both references point to the same object. By contrast, Equals() is expected to perform a value comparison, i.e. it will return true if the references point to objects that are equivalent. For example:
StringBuilder s1 = new StringBuilder("fred");
StringBuilder s2 = new StringBuilder("fred");
Console.WriteLine( s1 == s2 );
Console.WriteLine( s1.Equals(s2) );
will display:
False
True
s1 and s2 are different objects (hence == returns false), but they are equivalent (hence Equals() returns true).
Unfortunately there are exceptions to these rules. The implementation of Equals() in System.Object (the one your class inherits by default) compares identity, i.e. it's the same as operator==. So Equals() only tests for equivalence if the class author overrides the method (and implements it correctly). Another exception is the string class - its operator== compares value rather than identity.
Bottom line: If you want to perform an identity comparison use the ReferenceEquals() method. If you want to perform a value comparison, use Equals() but be aware that it will only work if the type has overridden the default implementation. Avoid operator== with reference types (except perhaps strings), as it's simply too ambiguous.
6.8 How do I enforce const correctness in C#?
You can't - at least not in the same way you do in C++. C# (actually, the CLI) has no real concept of const correctness, For example, there's no way to specify that a method should not modify an argument passed in to it. And there's no way to specify that a method does not modify the object on which it is acting.To get a feel for the angst this causes among some C++ programmers, read the feedback on this post from Raymond Chen.
There are of course ways of addressing this issue. For example, see Brad Abram's post (and associated feedback) for some ideas on adding optional read-only behaviour to collection classes.
7. C# 2.0
7.1 What are the new features in C# 2.0?
Support for all of the new framework features such as generics, anonymous methods, partial classes, iterators and static classes. See the .NET FAQ for more on these features.Delegate inference is a new feature of the C# compiler which makes delegate usage a little simpler. It allows you to write this:
Thread t = new Thread(ThreadFunc);
instead of this:
Thread t = new Thread( new ThreadStart(ThreadFunc) );
Another minor but welcome addition is the explicit global namespace, which fixes a hole in namespace usage in C# 1.x. You can prefix a type name with global:: to indicate that the type belongs to the global namespace, thus avoiding problems where the compiler infers the namespace and gets it wrong.
Finally C# 2.0 includes some syntactic sugar for the new System.Nullable type. You can use T? as a synonym for System.Nullable<T>, where T is a value type. As suggested by the name, this allows values of the type to be 'null', or 'undefined'.
7.2 Are C# generics the same as C++ templates?
No, not really. There are some similarities, but there are also fundamental differences. See the .NET FAQ for more details.8. C# 3.0
8.1 What's new in C# 3.0?
Support for LINQ was the driving force behind the main enhancements in C# 3.0. Query expressions are the most obvious example, but lambda expressions, extension methods and anonymous types also fall into this category. However most of these enhancements are useful beyond LINQ.Query expressions allow a SQL-like query syntax to be used in C#, e.g.
var nameList = new List<string> { "jack", "jill", "sue" };
var results = from name in nameList
where name.StartsWith("j")
select name;
Query expressions are just syntactic sugar - they resolve to standard method calls. For example the query expression above can be rewritten as:
var results = nameList.Where(name => name.StartsWith("j"));
The argument to Where() is a lambda expression, which represents an anonymous method. However a lambda expression is not just a more concise way to represent executable code - it can also be interpreted as a data structure (known as an expression tree), which allows the expression to be easily analysed or transformed at runtime. For example, LINQ-to-SQL makes use of this feature to transform C# queries to SQL queries, which gives much better performance than a simple in-memory filtering of results (as offered by DataTable.Select(), for example).
The Where() method shown above is an example of another new C# 3.0 feature: extension methods. Extension methods allow extra methods to be 'attached' to an existing type - any type, even sealed types or types you don't have the source code for. For example, the Where() method can be applied to any type that implements IEnumerable<T>.
Another new feature of C# 3.0 is the var keyword, which allows the compiler to infer the type of a variable from context, which is required for anonymous types but can be used with standard named types too:
var list = new List<string>() { "jack", "jill", "sue" }; // optional use with named types
var person = new { name = "jack", age = 20 }; // anonymous type
These examples also demonstrate the new object initializer and collection initializer syntax.
Finally, there are implicitly typed arrays and auto-implemented properties:
var names = new [] { "jack", "jill", "sue" }; // implicitly string[]
public string Name { get; set; } // auto-implemented property - private backing field auto-generated
Bottom of Form
Comments
Post a Comment