Beruflich Dokumente
Kultur Dokumente
a.cs
System.Console.WriteLine("in main");
bb a = new bb();
bb b = new bb(10);
public class aa
public aa()
}
public aa(int i)
public class bb : aa
public bb()
public bb(int i)
Output
in main
in const aa
in const bb
in const aa
in const bb10
Class aa is the base class. It consists of two constructors. One that takes no parameters and the
other that takes an int as a parameter. Class bb is derived from class aa, i.e. aa is the base class,
bb the derived class. When we create an object like bb, the compiler does not execute the code
for the constructor but instead asks the constructor which constructor of the base class to execute
first. As we haven't stated this, by default, the constructor with no parameters get executed.
Remember it is the base class constructor which gets executed first and the derived class
constructor specifies which base class constructor to call first. In the second case, even though
we are calling the constructor with a parameter, the constructor with no parameters in the base
class gets called and not the one with one int as a parameter.
a.cs
System.Console.WriteLine("in main");
bb a = new bb();
bb b = new bb(10);
public class aa
public aa()
public aa(int i)
public class bb : aa
Output
in main
in const aa
in const bb
in const aa10
in const bb10
If we do not specify which constructor of the base class to call, C# by default calls the
constructor with no parameters. Which means that C# rewrites our code . When we write bb(), it
gets rewritten as bb() : base(). Base is a reserved word. It means call the constructor of the base
class with no parameters. For the second constructor, bb(int i), the line gets rewritten to bb(int i) :
base(). We now want to call the constructor with one int and hence we write bb(int i) : base(i).
That is why the constructor with one int gets called. We have the option to decide which
constructor of the base class we would like to call.
a.cs
System.Console.WriteLine("in main");
bb a = new bb();
public class aa
public aa()
public aa(int i)
public class bb : aa
Output
in main
in const aa20
in const bb20
in const bb
A constructor gets called at the time of creation of the object. At the line, new bb(), the compiler
asks the constructor of bb as to which constructor of the base class aa to call. Here he was told
that the answer lies with this(20). this, like base, is a reserved word. It means call a constructor of
the same class and not the base class. Therefore the compiler now asks the one constructor of the
derived class bb which constructor of the base class to call. bb(int i) : base(i) tells the compiler to
execute the one int constructor of aa. This is the first constructor that gets called. Then the one
int constructor of bb gets called and finally the one who started it all, the no parameter
constructor of bb. Thus, two derived class constructors get called instead of one.
a.cs
System.Console.WriteLine("in main");
aa a = new aa();
}
}
public class aa
private aa()
Compiler Error
When you create a constructor which is private, you cannot create an object that looks like aa.
Thus aa should only contain static members.
a.cs
public class aa
private aa()
}
public class bb : aa
Compiler Error
Nor can any class derive from aa. Thus no one can instantiate an object that looks like aa or
derive from it as the constructor has been made private.
a.cs
System.Console.WriteLine(aa.i);
public class aa
private aa()
Output
20
You can however use all the static variables in aa
a.cs
class yyy
public yyy()
public int i;
Compiler Error
a.cs(16,15): error CS0027: Keyword this is not available in the current context
Base is called a constructor initializer. When base gets called, the instance or the object has not
yet been created. Ergo, this is not available here as this refers to the current object. In the
constructor, however, this can be freely used.
The values of variables in a class are initialized to their default values as per their data types
before the constructor gets called. Thus, in the constructor they have their default values as
shown below.
a.cs
class yyy
public int i;
public bool j;
public yyy()
Output
0 False
Here as before, the first line of code in the constructor gets executed.
a.cs
class yyy
public yyy(int j)
System.Console.WriteLine(i);
i = j;
System.Console.WriteLine(base.i);
}
Output
10
100
Calling the base class constructor is like inserting all the code of the one int constructor i.e.
yyy(int j), in the constructor of class xxx. We are also allowed to access members of the base
class after the constructor gets called. Also, first the variable i gets initialized to 10 or the default
value of int. Then we change it to 100 and in the constructor of xxx, we will see a value of 100.
a.cs
class yyy
public yyy()
abc();
{
}
public xxx()
System.Console.WriteLine(x);
x = 100;
System.Console.WriteLine(x);
System.Console.WriteLine(x);
Output
10
10
100
We have already confessed a million times in the past that we have copied ideas from anyone
and everyone, specially from the documentation. In this specific case, we wanted to demonstrate
that first the variables are initialized. Thus in class xxx, the int x is initialized to 10. Then the
base class constructor of yyy gets called. The value of x in class yyy should be 10. But what
guarantee can we give you as we are not able to print the value of x in an object of a class
derived from the base class. Very simple. We call a virtual function abc from class yyy and
override it in class xxx. The abc of class xxx prints the value of x as they belong to the same
class and the output is 10. Viola and thank you Mr. Documentation for the above thought and
many more such ideas. Once all code in the yyy constructor is executed, the first line in xxx
constructor will get executed which will print the value of x as 10. x is then initialized to 100,
hence we see 100 as the new value of x, displayed on the screen.
a.cs
static zzz()
System.Console.WriteLine("zzz");
System.Console.WriteLine("main");
new aa();
public class aa
public aa()
System.Console.WriteLine("aa");
static aa()
{
System.Console.WriteLine("static aa");
Output
zzz
main
static aa
aa
and if we comment new aa() then the resulting output reads as follows.
Output
zzz
main
a.cs
static zzz()
System.Console.WriteLine("zzz");
{
System.Console.WriteLine("main");
aa.a();
public class aa
public aa()
System.Console.WriteLine("aa");
static aa()
System.Console.WriteLine("static aa");
Output
zzz
main
static aa
If you try to access any static member of a class or whenever you instantiate an object, the static
constructor gets called. A constructor is not inherited by the derived class.
A class is loaded in memory before any instance of the class is created or its static members
accessed. A class can only be loaded once and that too before its derived class is loaded. The
static constructor is called at the time of loading the class. Like other constructors, a static
constructor cannot be explicitly called.
a.cs
xxx.pqr();
yyy.abc();
class yyy {
static yyy()
System.Console.WriteLine("static yyy");
System.Console.WriteLine("abc yyy");
class xxx {
static xxx()
{
System.Console.WriteLine("static xxx");
System.Console.WriteLine("pqr xxx");
Output
static xxx
pqr xxx
static yyy
abc yyy
Do not believe the above results as if you run them on your machine, your mileage may wary.
This is because C# does mandate the order of loading of classes and thus the order of execution
of the static constructors. On your machine if the yyy constructor gets executed first, do not
panic. Blame it on your destiny.
a.cs
yyy.abc();
xxx.pqr();
}
}
class xxx
static xxx()
System.Console.WriteLine("static xxx");
System.Console.WriteLine("pqr xxx");
static yyy()
System.Console.WriteLine("static yyy");
System.Console.WriteLine("abc yyy");
}
Output
static yyy
abc yyy
static xxx
pqr xxx
We have made only one small change in the above program. We have derived the class yyy from
xxx. Since the functions in each class are marked static, the program behaves in the same manner
as before.The above order of calls remains the same. If an object of the type is created, then the
output will change. The reason being that before the object of type yyy is created, xxx must be
loaded. Hence the constructors will be called first.
a.cs
static zzz()
x = 500;
yyy.y = 600;
}
}
class yyy
static yyy()
y = 10;
zzz.x = 200;
Output
static yyy 0 3
static zzz 12 10
Difficult code to understand and follow. C# first tries to load class zzz in memory as it contains
the function Main. Unfortunately it realizes that it has to first initialize the variable x before
calling the static constructor of zzz. It first initializes x to 0. Now note that this initialization of x
to zero is extremely significant for our understanding. To get the new value of x, C# now needs
the value of the variable y from the class yyy. Before it can call the static constructor of yyy it
must initialize the variable y. It makes sure that y's value is first set to zero. It then computes the
value of zzz.x which is zero as stated above. We are yet left hanging in class zzz at the line x = .
As zzz.x is zero, the value of y is 0 + 3 i.e. 3. This completes the initialization of all the variables
in the class. All this happens first. Thus the static constructor of class yyy shows the value of the
variable x as 0 and that of variable y as 3.
But hold on, the fun is yet to begin. In the static constructor, we now initialize y to 10 and the x
of zzz to 200. The next WriteLine confirms that our initializations actually were carried out.
Then we go back to class zzz. Here we come back to the initialization of the static variable x. As
yyy.y is now 10 since we changed it in the static constructor of yyy, the value of x is 10 + 2 i.e.
12. This overrides the value of x which we changed to 200 in the static constructor yyy. Now C#
calls the static constructor of zzz as it has finished all the variable initializations. Thus the first
WriteLine displays 12 and 10. We are now changing both x and y and they display the same
values in the constructor and in Main.
a.cs
static zzz()
x = 500;
yyy.y = 600;
class yyy
static yyy()
y = 10;
zzz.x = 200;
System.Console.WriteLine("static yyy " + zzz.x + " " + yyy.y);
Output
static zzz 2 0
main 200 10
The above program adds a small twist. It bowls what in cricket parlance is called a googly. We
simply bring Main from the class zzz to the class yyy. Now C# as usual first starts at the class
containing Main which now happens to be yyy and not zzz. Here it has to first initialize all the
variables in class yyy. We have only one. It starts by setting y to zero and runs to the class zzz to
fetch the value of x. x now become 0 + 2 i.e. 2. Then in the static constructor, we are displaying
the relevant values of x and y. In the static constructor of class zzz, we are changing x and y to
500 and 600 respectively and displaying the values. When we move back to class yyy, however,
y gets a new value of 503 as x is 500. y loses its value of 600 that was initialized in zzz, hence
you see 500 and 503. The rest remains the same as explained in the earlier example.
Interfaces
An interface is simply a collection of function prototypes. Like we derive a class from another,
so also we could derive from an interface.
a.cs
class zzz
{
interface ddd
void a1();
void a2();
Compiler Error
a.cs(12,7): error CS0535: 'yyy' does not implement interface member 'ddd.a1()'
a.cs(12,7): error CS0535: 'yyy' does not implement interface member 'ddd.a2()'
We have just created an interface called ddd by using a new keyword interface in place of a
class. Our interface ddd has two function prototypes, a1 and a2. We can derive from our
interface ddd like we derived from a class. The difference is that an interface has no code, only
function prototypes. Whenever we derive from an interface, we have to implement the code or
body of the function. A class gives you lots of free code, an interface does not. The error is
generated as we have not given the code for a1 and a2 in yyy
a.cs
class zzz
a.a1();
d.a2();
interface ddd
void a1();
void a2();
System.Console.WriteLine("yyy a1");
System.Console.WriteLine("yyy a2");
Output
yyy a1
yyy a2
We get no errors because we have now implemented the code of a1 and a2. Looks wise we do no
know whether ddd is a class or an interface as the syntax at the time of derivation is the same. d
is an object that looks like an interface which is syntactically correct. d can be equated to a yyy
as a yyy is a yyy + a ddd. We can, by only using d, call members of a ddd.
a.cs
class zzz
aaa a ;
a = new aaa();
interface aaa
Compiler Error
a.cs(6,5): error CS0144: Cannot create an instance of the abstract class or interface 'aaa'
Even though an interface aaa is empty, we cannot write the keyword new in front of it. An
interface contains no code and thus cannot be instantiated. However we are allowed to declare
objects that look like an interface. Therefore, in this case, the line aaa a, does not flag an error.
a.cs
class zzz
{
public static void Main()
interface aaa
void a1()
Compiler Error
Reiterating, an interface can only contain function prototypes, no code at all. The functions
cannot have a definition.
a.cs
class zzz
class xxx
}
class vvv
Compiler Error
C# does not support multiple inheritance. We can derive from a single class only at one point in
time.
a.cs
class zzz
d.a1(); d.a2();
a.a1();
a.a2();
interface ddd
{
void a1();
void a2();
System.Console.WriteLine("a1");
System.Console.WriteLine("a2");
Compiler Error
a.cs(19,13): error CS0106: The modifier 'public' is not valid for this item
You are not allowed to use the modifier public for a function which has qualified its name with
that of the interface.
a.cs
class zzz
}
}
interface aaa
Compiler Error
a.cs(9,13): error CS0106: The modifier 'public' is not valid for this item
Interface members are public by default. The access modifiers are not allowed here. All the other
access modifier rules remain the same as that from classes. The rules in classes stated that the
base class must be at least as accessible as the derived class. Replace the word class with
interface and you will not be sorry.
a.cs
class zzz
d.a1(); d.a2();
a.a1();
a.a2();
interface ddd
{
void a1();
void a2();
void ddd.a1()
System.Console.WriteLine("a1");
System.Console.WriteLine("a2");
Compiler Error
a.cs(8,1): error CS0117: 'yyy' does not contain a definition for 'a1'
The reason we get an error is because we created the function a1 in yyy as ddd.a1 and not a1. By
doing this, we were telling C# that only objects that look like ddd are allowed access to a1. Even
an object that looks like yyy is not allowed to access a1. Comment out line number 8 i.e. a.a1
and all works fine as follows
Output
a1
a2
a2
a.cs
class zzz
a.a1(); a.a2();
d.a1();
e.a2();
interface ddd
void a1();
interface eee
void a2();
System.Console.WriteLine("a1");
System.Console.WriteLine("a2");
Output
a1
a2
a1
a2
Here we are doing something that just cannot be done with classes. We are deriving from two
interfaces ddd and eee at the same time. Each has one function prototype a1 and a2 respectively.
Using a which looks like yyy we can call both a1 and a2 but with d that looks like ddd we can
only call a1. Similarly, with e only a2 can be called.
a.cs
class zzz
d.a1();
e.a1();
interface ddd
void a1();
interface eee
void a1();
System.Console.WriteLine("a1");
Output
a1
a1
a1
The two interfaces share the same function name a1. We do not get an error but yet things do not
seem right. Both d and e call the same a1 and there is only one implementation of the function
a1. We would like to have two a1's but we cannot have the same function defined twice in a
class.
a.cs
class zzz
d.a1();
e.a1();
interface ddd
void a1();
interface eee
void a1();
void ddd.a1()
System.Console.WriteLine("ddd a1");
void eee.a1()
System.Console.WriteLine("eee a1");
Output
ddd a1
eee a1
We did what we had explained earlier. We prefaced the name of the function with the name of
the interface. Then we removed the modifier public and the object a which looked like yyy. Now
each interface has its own copy of a1 to be called. ddd.a1 is called the explicit interface member
name.
a.cs
class zzz
a.a1();
}
}
interface ddd
void a1();
interface eee
void a1();
void ddd.a1()
System.Console.WriteLine("ddd a1");
void eee.a1()
System.Console.WriteLine("eee a1");
Compiler Error
a.cs(6,1): error CS0117: 'yyy' does not contain a definition for 'a1'
The reason we removed a was that once we have an explicit interface member, we cannot access
it through the class, it is done only through the interface. This make a lot of sense as there are
two functions of the same name, and C# does not know which one it should call. By prefacing
the functions with the names of the interface, we are making them part of the interface and not
the class. In a sense they are private to the class. As there is no function by the name of a1 in
class yyy, we see the above error.
a.cs
class zzz
interface ddd
void a1();
interface eee
void a1();
void ddd.a1()
void eee.a1()
{
Compiler Error
a.cs(21,6): error CS0540: 'yyy.eee.a1()': containing class does not implement interface 'eee'
We get an error as class yyy is derived only from interface ddd. Thus we cannot use eee.a1() as
interface eee is not a base interface for class yyy.
a.cs
class zzz
interface ddd
void a1();
void ddd.a1()
}
class xxx : yyy
void ddd.a1()
Compiler Error
a.cs(19,6): error CS0540: 'xxx.ddd.a1()': containing class does not implement interface 'ddd'
The key concept earlier was that we could only use the name of an interface explicitly if it was
categorically stated as a base class. Anything indirect would not do. Here class yyy is derived
from interface ddd and thus we can use the form ddd.a1. However even though class xxx is
derived from class yyy and thus also from interface ddd, we are not allowed to write ddd.a1 as
interface ddd is not explicitly stated in the derivation list of class xxx.
An interface defines a contract and can only contain four entities viz methods, properties, events
and indexers. An interface thus cannot contain constants, fields, operators, constructors,
destructors, static constructors, or types. Also an interface cannot contain static members of any
kind. The modifiers abstract, public, protected, internal, private, virtual, override are disallowed
as they make no sense in this context.
a.cs
class zzz
int a2
get; set ;
event d1 ddd;
string this[int i]
get; set;
}}
The above example demonstrates the four entities an interface can contain. Anything else will
flag an error.
a.cs
class zzz
aaa a = c;
bbb b = c;
c.a1();c.a2();
a.a1();
b.a1();b.a2();
}
interface aaa
void a1();
void a2();
System.Console.WriteLine("a1");
System.Console.WriteLine("a2");
Output
a1
a2
a1
a1
a2
An interface can also, like a class, inherit from one or more interfaces. In this case bbb as an
interface, can inherit from aaa. The class ccc inherits from interface bbb and and thus interface
aaa has to implement functions a1 and a2. The object c not only looks like a ccc but also looks
like an aaa and bbb. Thus equating them does not give an error. The reverse, however, is not
true. It will obviously flag an error. However a can only access functions from the interface it
belongs to, in this case a1 and b can access a1 and a2. b cannot access members from class ccc
even though a, b, and c have the same values. Whenever an interface derives from another it is
called an explicit base interface. Like classes, circular definitions are not permitted. In fact
nowhere in the C# programming language are we permitted to have circular definitions.
An interface also creates a new type and as in classes, methods must have their own unique
signatures. Properties and methods cannot have similar names.
a.cs
class zzz
interface aaa
void a1();
{
void a1();
Compiler Warning
a.cs(13,6): warning CS0108: The keyword new is required on 'bbb.a1()' because it hides
inherited member 'aaa.a1()'
Like classes if interfaces derive from each other, there is a possibility that they may contain the
same function signatures. Thus we get a warning which can be removed by adding the keyword
new as follows.
The point to be stressed here is that the keyword new really does not do much, other than remove
the warning. This is because the implementation of the interface is done in the class. There, we
will have only one implementation of function a1 and not two, one for aaa and the other for bbb.
At one level, from the point of view of the class which derives from interface bbb, it will see
only one function in it, not two. All that we are doing is hiding the base interface member.
a.cs
class zzz
void abc(ccc c)
c.aa(1);
((bbb)c).aa(1);
((aaa)c).aa(1);
c.aa = 2;
((aaa)c).aa = 3;
((bbb)c).aa = 3;
interface aaa
int aa
get; set;
interface bbb
Compiler Error
a.cs(10,10): error CS0118: 'aaa.aa' denotes a 'property' where a 'method' was expected
a.cs(11,1): error CS0229: Ambiguity between 'aaa.aa' and 'bbb.aa(int)'
Interface aaa has only one member, a property called aa, whereas interface bbb has one function
called aa. The interface ccc does not give us an error in spite of the fact that we have a property
and a function with the same name. In the function abc, we are passing c, an object that looks
like ccc. The line c.aa(1) gives us an error as we have a property and a function called aa. C#
gets confused whether it is the property or the function we are referring to. In our humble
opinion, we could only be referring to the function as per the syntax, but you don't argue with a
compiler.
In the second case c.aa = 2 also flags an error due to the name confusion. In this case also, we
could only be referring to a property. The only way out is to cast. The second cast in each case
gives an error as the syntax for calling a function and property is different. Normally, to cast, we
need to give two sets of brackets.
A cast incurs no run time costs i.e., it does not slow down the program. All that a cast does in
the above case is lowers the pointer from a ccc to aaa or bbb at compile time. In an earlier
example, we spoke of functions from two interfaces having similar names. The same rules stated
there apply here also.
a.cs
class zzz
void abc(ccc c)
c.aa(1);
c.aa((byte)1);
((aaa)c).aa(1);
((bbb)c).aa(1);
}
interface aaa
interface bbb
Compiler Error
a.cs(8,1): error CS0121: The call is ambiguous between the following methods or properties:
'bbb.aa(short)' and 'aaa.aa(byte)'
a.cs(9,1): error CS0121: The call is ambiguous between the following methods or properties:
'bbb.aa(short)' and 'aaa.aa(byte)'
We have a similar problem again. c.aa(1) does not know which function aa to call. C# could
convert the 1 an int, either to a short or a byte. Thus the ambiguity. Even if we cast the 1 to a
byte, for some reason, C# yet gives us an error. The only way out is like what we did earlier,
explicitly cast your way out of trouble. When we cast, we are restricting ourselves to only one
method and thus no ambiguity.
a.cs
class zzz
{
public static void Main()
interface aaa
void aa();
void cc();
Compiler Error
a.cs(22,7): error CS0535: 'eee' does not implement interface member 'bbb.aa()'
a.cs(22,7): error CS0535: 'eee' does not implement interface member 'ccc.cc()'
a.cs(22,7): error CS0535: 'eee' does not implement interface member 'aaa.aa()'
The interface aaa has one function aa. The interface bbb is derived from aaa and also has one
function called aa. The keyword new informs the C# compiler that, it has hidden or has nothing
to do with the function aa in interface aaa. Remember in interfaces, we cannot write any code.
The interface ccc also derives from aaa but does not have a function called aa. Then we are
creating another interface ddd which derives from both bbb and ccc. The class eee is then
derived from interface ddd. We get three errors as we have to implement three functions in class
eee. The interface ccc brings in two functions. One cc and the other aa from interface aa. The
interface bbb has only one function, aa which is different from the aa which is present in
interface aaa, thanks to the keyword new which is optional.
a.cs
class zzz
a.aa();
b.aa();
c.aa();
d.aa();
//e.aa();
((aaa)d).aa();
((bbb)d).aa();
((ccc)d).aa();
((ddd)d).aa();
interface aaa
void aa();
void cc();
{
void aaa.aa()
System.Console.WriteLine("aa aaa");
void bbb.aa()
System.Console.WriteLine("aa bbb");
System.Console.WriteLine("cc");
Output
aa aaa
aa bbb
aa aaa
aa bbb
aa aaa
aa bbb
aa aaa
aa bbb
With or without the keyword new, the output remains the same. By adding the keyword new, all
that we have achieved is removal of the warning. Lets explain the above program step by step.
We have implemented the three functions that class eee needed. We could have implemented
only one aa, and then in every case that one aa, would have been called. In this case we need two
aa functions. One for the interface aaa and the other for the interface bbb. As we need a separate
function aa for each interface we will land up having two of them. Thus we need to preface them
with the name of the interface.
We are creating objects that look like all our interfaces and initializing them to an object that
looks like class eee. The object a that looks like interface aaa, will obviously call the aa of
interface aaa. The object b that looks like interface bbb will call the aa of interface aaa
implemented in class eee. The object c, that looks like ccc is derived from interface aaa and thus
it will call the function aa of interface aaa. All of this is obvious. Now d looks like ddd which is
derived from ccc and bbb. The reason it will call the aa of bbb and not of aaa is because we have
asked it to hide the function aa of interface aaa. Once a function is hidden, it will remain hidden
forever in all the access paths. Thus function aa of interface bbb hides the function aa of interface
aaa even in interface ccc.
The casting gives us the same answer as above. In the first case, cast d, a ddd looks alike to an
aaa. Thus the aa from aaa gets called. In the second case it calls the aa of bbb. Just like before,
when we cast c to a ccc, it calls the aa form aaa . Now we cast c to a ddd, it can call either the
function aa from bbb or function aa from aaa. In this case it chooses to call the aa from bbb as its
aa hides the aa of interface aaa.
To sum up, if a function is hidden from one access path, it is hidden from all.
A little later in this chapter, we will show you that structures can also implement from an
interface.This process of implementing all the functions is called interface mapping.
a.cs
class zzz
interface aaa
void a1();
}
new int a1
set;
void aaa.a1()
int bbb.a1 {
set
int bbb.a1
{
set
void aaa.a1()
public int a1
set
The interface aaa has one function a1 which clashes with the name of the property in interface
bbb. We have three ways to create a class which is derived from bbb. In the first case ccc, we are
explicitly qualifying with the name of interface. In the second case of ddd, we are qualifying
only the property and not the function. In the third case i.e. class eee, we do the reverse. Thus
one of the a1or both must be qualified or else it will result in an error.
a.cs
class zzz
{
interface aaa
void a1();
void a2();
void a3();
void bbb.a1()
Compiler Error
a.cs(21,6): error CS0539: 'bbb.a1' in explicit interface declaration is not a member of interface
a.cs(19,7): error CS0535: 'ddd' does not implement interface member 'aaa.a1()'
Both interfaces bbb and ccc derive from interface aaa. Class ddd derives from three interfaces
aaa and bbb and ccc. In class ddd, we have only 3 functions, a1, a2 and a3 that come from aaa,
bbb and ccc respectively. Even though interface bbb derives from aaa, it does not carry a1 into
class ccc. So, we cannot write bbb.a1 in class ccc. Hence, we have only one a1 from interface
aaa in class ccc and none from interfaces bbb and ccc. This proves that C# forgets the interfaces
bbb and ccc are derived from. It also means that bbb and ccc cannot have their own
implementations of a1.
a.cs
class zzz
a.a1();
interface aaa
{
void a1();
class bbb
System.Console.WriteLine("bbb a1");
Output
bbb a1
The class ccc derives from bbb and aaa. The function a1 from interface aaa is implemented by
class bbb and not by ccc. No one cares as long as there is a function a1 somewhere. The function
a1, in this case, can be in the actual class or in the base class.
a.cs
class zzz
c.a1();
a.a1();
aa.a1();
interface aaa
void a1();
System.Console.WriteLine("bbb a1");
Output
bbb a1
ccc a1
bbb a1
bbb a1
In this case, class ccc is derived from class bbb, which in turn is derived from interface aaa. Both
the classes implement the function a1. The question on our minds is from which class will the
function a1 be called. Both b and c are initialized to an object that looks like ccc. b.a1() will
obviously call the function a1 from bbb and c.a1() will call it from ccc. Saying the same thing
over and over again like a malfunctioning record disk is trying but essential.
Objects a and aa look like aaa but are initialized to objects that look like ccc and bbb
respectively. It does not seem to make any difference as each time the function a1 gets called
from the base class bbb and not from the derived class ccc or the class that we have initialized
the object to.
This means that the derived class cannot alter the interface mappings it receives from the base
class. The mapping of function a1 is to the class bbb as bbb was derived from the interface. Class
ccc cannot change this fact.
a.cs
class zzz
b.a1();
c.a1();
a.a1();
aa.a1();
interface aaa
void a1();
System.Console.WriteLine("bbb a1");
System.Console.WriteLine("ccc a1");
Output
ccc a1
bbb a1
ccc a1
ccc a1
bbb a1
We have made two changes in our program. We made the function a1 virtual in the class bbb and
also, in the class ccc, we declared a1 with the override modifier. Whenever we declare a function
to be virtual, the derived classes will and can override it. The modifier override has the opposite
meaning over new. It means do not create a new function but override the base class definition.
Objects b and b1 both look like bbb but are initialized to objects that look like ccc and bbb
respectively. When we write b.a1(), C# first looks into the class bbb as that is the data type of b.
Here the function a1 is marked virtual, so C# now asks ‘what was b initialized by’? As the
answer is an object that looks like ccc, C# now looks at the class ccc for the function a1. As it is
marked override, C# will execute the function a1 from class ccc and not bbb. If the override was
missing, the default is new, and the function will be called from the data type of the object i.e.
bbb.
As object b1 has been initialized by an object that looks like bbb, C# will call a1 from class bbb
only. The object c follows the earlier specified rules. As for objects a and aa, both look like
interface aaa which has no code for the function aaa. Here the object used to initialize will decide
the class a1 will be called from. This is due to the explanation above as a1 is marked virtual in
class bbb and override in class ccc.
a.cs
class zzz
interface ppp
void a1();
interface aaa
void a1();
System.Console.WriteLine("bbb a1");
System.Console.WriteLine("ccc a1");
}
}
Compiler Error
a.cs(17,21): error CS0106: The modifier 'public' is not valid for this item
a.cs(17,21): error CS0106: The modifier 'virtual' is not valid for this item
Lets make matters worse. We have an interface ppp which also brings in a function called a1.
The class bbb also derives from ppp. Thus we have two a1 functions and we have to explicitly
qualify them. Unfortunately we cannot add the qualifier virtual here. The only way out is as
follows.
a.cs
class zzz
a.a1();
aa.a1();
interface ppp
void a1();
interface aaa
{
void a1();
void aaa.a1()
aa1();
void ppp.a1()
System.Console.WriteLine("aa1");
System.Console.WriteLine("aa1 ccc");
}
Output
aa1 ccc
aa1
What we have done here is that in the a1 function of aaa we have called the function aa1. So in
other words, a1 simply calls aa1. We have made aa1 virtual such that each time aa1 is called, the
question asked will be - which object was used at the time of initialization? Depending upon the
type of object, the relevant function aa1 would be executed. Thus we get the same answer as
earlier. If we have to reimplement an interface, you can look at the example earlier. C# forgets
about the initial derivation.
a.cs
class zzz
interface aaa
void a1();
void a2();
Compiler Error
a.cs(12,16): error CS0535: 'bbb' does not implement interface member 'aaa.a1()'
a.cs(12,16): error CS0535: 'bbb' does not implement interface member 'aaa.a2()'
Whenever we have a abstract class deriving from an interface, the class must implement all the
methods of the interface as follows.
a.cs
class zzz
interface aaa
void a1();
void a2();
If the abstract class does not want to implement all the members of the interface, it has to mark
the functions as abstract and public. The class deriving from bbb will now have to supply the
code of the class bbb
Structures
a.cs
class zzz
System.Console.WriteLine(x.i);
x.abc();
struct xxx
public int i;
i = j;
System.Console.WriteLine("abc");
}
Output
10
abc
A structure or struct to be precise is similar to a class in many ways. A struct can contain fields,
methods etc. If a struct and class were 100 per cent similar, then why have both? We will now
explain the differences between a struct and a class. Unless otherwise stated, they share the same
features.
a.cs
class zzz
struct xxx
Compiler Error
a.cs(9,12): error CS0573: 'xxx.i': cannot have instance field initializers in structs
In a class we are allowed to create a field/variable and initialize it at the same time. A structure
cannot contain such initializations. Thus these fields must be initialized either through functions
or by using the object itself. Fields cannot be given initial values at the time of creation.
a.cs
class zzz
{
public static void Main()
struct xxx
public int i;
public xxx()
Compiler Error
A class can contain many constructors. And even if we do not have any, C# supplies a free
constructor with no parameters. It's very different with structures. You cannot have a constructor
with no parameters. If you do, you will get the above error. Thus C# lets you have as many
constructors as you like but none without parameters.
a.cs
class zzz
}
struct xxx
public int i;
public xxx(int p) { }
Compiler Error
a.cs(10,8): error CS0171: Field 'xxx.i' must be fully assigned before control leaves the
constructor
A small problem here. As mentioned earlier we cannot initialize a field like we do in a class.
Hence C# insists on constructors that accept parameters to initialize fields; at the end of the
constructor if you have not initialized the fields in the structure, we get the above error. Thus C#
actually reads our code and makes sure that the constructor initializes all the fields in the
structure.
a.cs
class zzz
struct xxx
public xxx(int p) {
i = p;
}
Compiler Error
a.cs(11,8): error CS0171: Field 'xxx.j' must be fully assigned before control leaves the
constructor
a.cs
class zzz
struct xxx
public xxx(int p)
i = p;
j = 0;
We get no error as the structure has two fields and we have now initialized both of them.
a.cs
class zzz
System.Console.WriteLine(a.i);
struct xxx
public int i;
Compiler Warning
a.cs(11,12): warning CS0649: Field 'xxx.i' is never assigned to, and will always have its default
value 0
Output
If we do not have any constructors, we get no error. As we have not initialized the field i, in the
constructor, we have none. C# gives you a warning and for the sake of your sanity, initializes i to
0.
a.cs
class zzz
System.Console.WriteLine(a.i);
struct xxx
public int i;
Compiler Error
A structure yyy cannot be derived from another structure. A useful feature of a class was the fact
that we could share/use code from other classes. A structure does not support the concept of
inheritance. Had xxx been a class we would have received the same error.
a.cs
class zzz
}
}
interface xxx
The previous error message gave us a hint . It expected xxx to be a interface. Thus we can derive
a structure from an interface. As xxx has no members we do not have to implement any code in
our structure.
a.cs
class zzz
struct yyy
}
Compiler Error
a.cs(11,7): error CS0509: 'xxx' : cannot inherit from sealed class 'yyy'
As a structure could not inherit from a class, the reverse is also true. xxx cannot inherit from a
structure yyy. Internally a structure behaves as a sealed class as the error message reads. For
those who came in late, a sealed class cannot be used a base class.
a.cs
class zzz
Compiler Error
a.cs(7,15): error CS0106: The modifier 'sealed' is not valid for this item
You cannot declare a structure as sealed as they are by definition sealed. If you add the word
sealed as we have done, C# complains about the fact that we are repeating the same modifier
again and nobody likes repetition.
a.cs
class zzz
{
}
Compiler Error
a.cs(7,17): error CS0106: The modifier 'abstract' is not valid for this item
As C# does not like repetition, we have to bow to its wishes. But you do not have an option. We
are free to repeat ourselves with you as many times as we like. So let us indulge ourselves. A
structure as mentioned earlier cannot be used as a base class i.e. be used in a derivation. An
abstract modifier, means an incomplete entity which cannot be used directly but only as a base
class. It makes no sense for a structure to use the modifier abstract.
In the same vein, function in a structure cannot be marked abstract or virtual as these are
concepts, which apply to derived classes only.
a.cs
class zzz
Compiler Error
A structure cannot be derived from and the modifier protected deals with the visibility of
members from derived classes. Replacing protected with private results in the same error.
a.cs
class zzz
System.Console.WriteLine(a.ToString());
struct yyy
Output
yyy
However every structure like a class is implicitly derived from the class Object and thus has the
functions Object contains. In this case ToString returns the name of the derived class.
a.cs
class zzz
System.Console.WriteLine(a.ToString());
}
Compiler Error
How do we explain the above error? We just mentioned earlier that as a structure inherits from
the class Object and we called a function called ToString from the class Object. However we
cannot derive from Object explicitly as the compiler insists on the name of an interface and
Object is a name of a class. These little quirks make learning C# difficult. If you replace the
word struct with class in the above example, you will not get an error.
A computer has lots of memory. We logically divide this memory into two, the stack and the
heap. Memory denoted as the stack lives as long as the function lives and heap memory lives as
long as your program runs. Objects, instances of a class are allocated on the heap. They will live
for a long time. They are also called reference objects. Structures are allocated on the stack by
new and live for a shorter duration. We call them value objects. This means that a structure
directly represents the data where as a object contains a reference to the data. Structures thus
offer a more efficient access to variables than classes. Int, bool and all the other basic data types
are implemented as structures.
a.cs
class zzz
xxx x,y;
yyy a,b;
x = y; a = b;
System.Console.WriteLine(x.i + " " + y.i + " " + a.i + " " + b.i);
System.Console.WriteLine(x.i + " " + y.i + " " + a.i + " " + b.i);
class yyy
public int i;
public yyy(int j)
i = j;
struct xxx
public int i;
public xxx(int j)
i = j;
}
Output
1212
2222
We have created two objects a and b which look like a class yyy and two structures x and y
which look like xxx. In the constructors of each, we are initializing the field i to 1 and 2
respectively. Then we are equating the object a to b and the structure x to y. This will set the i of
x to 2 from 1 and also the i of a to 2. Thus the second WriteLine displays all two's. We are now
changing the i of x, which is a structure to 100 and we realize that the i of y, the structure it was
initialized to remains the same. Thus x.i is 100 and y.i remains at 2.
For classes it does not work the same way. Changing a.i to 200, somehow changes the i of b
which a was initialized to, also to 200. This could only be possible if when we equate structures,
each has its own copy of the data. When we equate objects, no copying takes place and now
object a refers to object b in memory. Both a and b represent the same object. Changing a
changes b. A little later, we dwell on this concept further.
The same rules of passing parameters to a function i.e. out and ref that apply to an int also apply
to a structure as int is also a structure internally.
a.cs
class zzz
xxx x;
yyy a;
x=null;
a=null;
}
class yyy
struct xxx
Compiler Error
a.cs(7,3): error CS0037: Cannot convert null to 'xxx' because it is a value type
In computer programming, a large number of times we do not know the value of a variable at a
point in time. These variables are given a value of null. Null can be only applied to objects of
reference types and not value types.
a.cs
class zzz
struct xxx
public ~xxx()
}
Compiler Error
After a long time, we get an error message that is readable. Structures are created on the stack
and die when we reach the closing brace. There is thus no memory management to be done from
the point of view of the programmer. The structure life cycle is very deterministic and hence no
destructors are permitted.