Você está na página 1de 82

11

Interfaces and Structures


Constructors Revisited

A constructor is used to initialize the instance of a class as explained earlier.

a.cs

public class zzz

public static void Main()

System.Console.WriteLine("in main");

bb a = new bb();

bb b = new bb(10);

public class aa

public aa()

System.Console.WriteLine("in const aa");

}
public aa(int i)

System.Console.WriteLine("in const aa" + i);

public class bb : aa

public bb()

System.Console.WriteLine("in const bb");

public bb(int i)

System.Console.WriteLine("in const bb" + 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

public class zzz

public static void Main()

System.Console.WriteLine("in main");

bb a = new bb();

bb b = new bb(10);

public class aa

public aa()

System.Console.WriteLine("in const aa");

public aa(int i)

System.Console.WriteLine("in const aa" + i);


}

public class bb : aa

public bb() : base()

System.Console.WriteLine("in const bb");

public bb(int i) : base(i)

System.Console.WriteLine("in const bb" + i);

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

public class zzz

public static void Main()

System.Console.WriteLine("in main");

bb a = new bb();

public class aa

public aa()

System.Console.WriteLine("in const aa");

public aa(int i)

System.Console.WriteLine("in const aa" + i);

public class bb : aa

public bb() : this(20)


{

System.Console.WriteLine("in const bb");

public bb(int i) : base(i)

System.Console.WriteLine("in const bb" + i); } }

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

public class zzz

public static void Main()

System.Console.WriteLine("in main");

aa a = new aa();

}
}

public class aa

private aa()

Compiler Error

a.cs(6,8): error CS0122: 'aa.aa()' is inaccessible due to its protection level

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 zzz

public static void Main()

public class aa

private aa()

}
public class bb : aa

Compiler Error

a.cs(13,14): error CS0122: 'aa.aa()' is inaccessible due to its protection level

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

public class zzz

public static void Main()

System.Console.WriteLine(aa.i);

public class aa

private aa()

static public int i = 20;

Output

20
You can however use all the static variables in aa

a.cs

public class zzz

public static void Main()

class yyy

public yyy()

class xxx : yyy

public int i;

xxx() : base( this.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

public class zzz

public static void Main()

yyy a = new yyy();

class yyy

public int i;

public bool j;

public yyy()

System.Console.WriteLine(i+" " + j);

Output

0 False
Here as before, the first line of code in the constructor gets executed.

a.cs

public class zzz

public static void Main()

xxx a = new xxx();

class yyy

public int i = 10;

public yyy(int j)

System.Console.WriteLine(i);

i = j;

class xxx : yyy

public xxx() : base(100)

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

public class zzz

public static void Main()

xxx a = new xxx();

class yyy

public yyy()

abc();

public virtual void abc()

{
}

class xxx : yyy

public int x = 10;

public xxx()

System.Console.WriteLine(x);

x = 100;

System.Console.WriteLine(x);

public override void abc()

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

public class zzz

static zzz()

System.Console.WriteLine("zzz");

public static void Main()

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 static constructor gets called before any other constructors.

a.cs

public class zzz

static zzz()

System.Console.WriteLine("zzz");

public static void Main()

{
System.Console.WriteLine("main");

aa.a();

public class aa

public aa()

System.Console.WriteLine("aa");

public static void a()

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

public class zzz

public static void Main()

xxx.pqr();

yyy.abc();

class yyy {

static yyy()

System.Console.WriteLine("static yyy");

public static void abc()

System.Console.WriteLine("abc yyy");

class xxx {

static xxx()
{

System.Console.WriteLine("static xxx");

public static void pqr()

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

public class zzz

public static void Main()

yyy.abc();

xxx.pqr();

}
}

class xxx

static xxx()

System.Console.WriteLine("static xxx");

public static void pqr()

System.Console.WriteLine("pqr xxx");

class yyy : xxx

static yyy()

System.Console.WriteLine("static yyy");

public static void abc()

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

public class zzz

public static int x = yyy.y + 2;

static zzz()

System.Console.WriteLine("static zzz " + zzz.x + " " + yyy.y);

x = 500;

yyy.y = 600;

System.Console.WriteLine("static zzz " + zzz.x + " " + yyy.y);

public static void Main()

System.Console.WriteLine("main "+ zzz.x + " " + yyy.y);

}
}

class yyy

static yyy()

System.Console.WriteLine("static yyy " + zzz.x + " " + yyy.y);

y = 10;

zzz.x = 200;

System.Console.WriteLine("static yyy " + zzz.x + " " + yyy.y);

public static int y = zzz.x + 3; }

Output

static yyy 0 3

static yyy 200 10

static zzz 12 10

static zzz 500 600

main 500 600

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

public class zzz

public static int x = yyy.y + 2;

static zzz()

System.Console.WriteLine("static zzz " + zzz.x + " " + yyy.y);

x = 500;

yyy.y = 600;

System.Console.WriteLine("static zzz " + zzz.x + " " + yyy.y);

class yyy

static yyy()

System.Console.WriteLine("static yyy " + zzz.x + " " + yyy.y);

y = 10;

zzz.x = 200;
System.Console.WriteLine("static yyy " + zzz.x + " " + yyy.y);

public static int y = zzz.x + 3;

public static void Main()

System.Console.WriteLine("main "+ zzz.x + " " + yyy.y);

Output

static zzz 2 0

static zzz 500 600

static yyy 500 503

static yyy 200 10

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
{

public static void Main()

interface ddd

void a1();

void a2();

class yyy : ddd

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

public static void Main()


{

yyy a = new yyy();

a.a1();

ddd d = new yyy();

d.a2();

interface ddd

void a1();

void a2();

class yyy : ddd

public void a1()

System.Console.WriteLine("yyy a1");

public void a2() {

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

public static void Main()

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

a.cs(9,6): error CS0531: 'aaa.a1()': interface members cannot have a definition

Reiterating, an interface can only contain function prototypes, no code at all. The functions
cannot have a definition.

a.cs

class zzz

public static void Main()

class xxx

}
class vvv

class yyy : xxx,vvv

Compiler Error

a.cs(13,17): error CS0527: 'vvv' : type in interface list is not an interface

C# does not support multiple inheritance. We can derive from a single class only at one point in
time.

a.cs

class zzz

public static void Main()

yyy a = new yyy();

ddd d = new yyy();

d.a1(); d.a2();

a.a1();

a.a2();

interface ddd

{
void a1();

void a2();

class yyy : ddd

public void ddd.a1()

System.Console.WriteLine("a1");

public void a2()

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

public static void Main()

}
}

interface aaa

public void a1();

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

public static void Main()

yyy a = new yyy();

ddd d = new yyy();

d.a1(); d.a2();

a.a1();

a.a2();

interface ddd

{
void a1();

void a2();

class yyy : ddd

void ddd.a1()

System.Console.WriteLine("a1");

public void a2()

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

public static void Main()

yyy a = new yyy();

ddd d = new yyy();

eee e = new yyy();

a.a1(); a.a2();

d.a1();

e.a2();

interface ddd

void a1();

interface eee

void a2();

class yyy : ddd , eee

public void a1()


{

System.Console.WriteLine("a1");

public void a2()

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

public static void Main()

yyy a = new yyy();

ddd d = new yyy();

eee e = new yyy();


a.a1();

d.a1();

e.a1();

interface ddd

void a1();

interface eee

void a1();

class yyy : ddd , eee

public 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

public static void Main()

ddd d = new yyy();

eee e = new yyy();

d.a1();

e.a1();

interface ddd

void a1();

interface eee

void a1();

class yyy : ddd , eee


{

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

public static void Main()

yyy a = new yyy();

a.a1();

}
}

interface ddd

void a1();

interface eee

void a1();

class yyy : ddd , eee

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

public static void Main()

interface ddd

void a1();

interface eee

void a1();

class yyy : ddd

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

public static void Main()

interface ddd

void a1();

class yyy : ddd

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

public static void Main()

public delegate void d1();

public interface aaa


{

void a1(string s);

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

public static void Main()

ccc c = new ccc();

aaa a = c;

bbb b = c;

c.a1();c.a2();

a.a1();

b.a1();b.a2();
}

interface aaa

void a1();

interface bbb : aaa

void a2();

class ccc : bbb

public void a1()

System.Console.WriteLine("a1");

public void a2()

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

public static void Main()

interface aaa

void a1();

interface bbb : aaa

{
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.

interface bbb : aaa

new void a1();

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

public static void Main()

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

void aa(int i);

interface ccc : aaa , bbb

Compiler Error

a.cs(8,1): error CS0229: Ambiguity between 'aaa.aa' and 'bbb.aa(int)'

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)'

a.cs(13,10): error CS0654: Method 'bbb.aa(int)' referenced without parentheses

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

public static void Main()

void abc(ccc c)

c.aa(1);

c.aa((byte)1);

((aaa)c).aa(1);

((bbb)c).aa(1);
}

interface aaa

void aa(byte i);

interface bbb

void aa(short i);

interface ccc : aaa , 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();

interface bbb : aaa

new void aa();

interface ccc : aaa

void cc();

interface ddd : bbb , ccc

class eee : ddd

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

public static void Main()

aaa a = new eee();

a.aa();

bbb b = new eee();

b.aa();

ccc c = new eee();

c.aa();

ddd d = new eee();

d.aa();

eee e = new eee();

//e.aa();
((aaa)d).aa();

((bbb)d).aa();

((ccc)d).aa();

((ddd)d).aa();

interface aaa

void aa();

interface bbb : aaa

new void aa();

interface ccc : aaa

void cc();

interface ddd : bbb , ccc

class eee : ddd

{
void aaa.aa()

System.Console.WriteLine("aa aaa");

void bbb.aa()

System.Console.WriteLine("aa bbb");

public void cc()

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

public static void Main()

interface aaa

void a1();
}

interface bbb : aaa

new int a1

set;

class ccc : bbb

void aaa.a1()

int bbb.a1 {

set

class ddd: bbb

public void a1() {}

int bbb.a1
{

set

class eee: bbb

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
{

public static void Main()

interface aaa

void a1();

interface bbb : aaa

void a2();

interface ccc : aaa

void a3();

class ddd : aaa,bbb,ccc

void bbb.a1()

public void a2()


{

public void a3()

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

public static void Main()

aaa a = new ccc();

a.a1();

interface aaa
{

void a1();

class bbb

public void a1()

System.Console.WriteLine("bbb a1");

class ccc : bbb , aaa

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

public static void Main()

bbb b = new ccc();


b.a1();

ccc c = new ccc();

c.a1();

aaa a = new ccc();

a.a1();

aaa aa = new bbb();

aa.a1();

interface aaa

void a1();

class bbb : aaa

public void a1()

System.Console.WriteLine("bbb a1");

class ccc : bbb

new public void a1() {


System.Console.WriteLine("ccc 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

public static void Main()

bbb b = new ccc();

b.a1();

bbb b1 = new bbb();


b1.a1();

ccc c = new ccc();

c.a1();

aaa a = new ccc();

a.a1();

aaa aa = new bbb();

aa.a1();

interface aaa

void a1();

class bbb : aaa

public virtual void a1()

System.Console.WriteLine("bbb a1");

class ccc : bbb

public override void 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

public static void Main()


{

interface ppp

void a1();

interface aaa

void a1();

class bbb : aaa , ppp

public virtual void aaa.a1()

System.Console.WriteLine("bbb a1");

class ccc : bbb

public override void 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

public static void Main()

aaa a = new ccc();

a.a1();

aaa aa = new bbb();

aa.a1();

interface ppp

void a1();

interface aaa

{
void a1();

class bbb : aaa , ppp

void aaa.a1()

aa1();

void ppp.a1()

public virtual void aa1()

System.Console.WriteLine("aa1");

class ccc : bbb

public override void 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

public static void Main()

interface aaa

void a1();

void a2();

abstract class bbb : aaa

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

public static void Main()

interface aaa

void a1();

void a2();

abstract class bbb : aaa

public void a1()

public abstract 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

public static void Main()

xxx x = new xxx(10);

System.Console.WriteLine(x.i);

x.abc();

struct xxx

public int i;

public xxx( int j)

i = j;

public void abc()

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

public static void Main()

struct xxx

public int i = 10;

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()

xxx a = new xxx();

struct xxx

public int i;

public xxx()

Compiler Error

a.cs(11,8): error CS0568: Structs cannot contain explicit parameterless constructors

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

public static void Main() {

xxx a = new xxx(10);

}
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

public static void Main()

xxx a = new xxx(10);

struct xxx

public int i,j;

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

The keyword shown in all the above errors is fields.

a.cs

class zzz

public static void Main()

xxx a = new xxx(10);

struct xxx

public int i,j;

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

public static void Main()

xxx a = new xxx();

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

public static void Main()


{

xxx a = new xxx();

System.Console.WriteLine(a.i);

struct xxx

public int i;

struct yyy : xxx

Compiler Error

a.cs(13,14): error CS0527: 'xxx' : type in interface list is not an interface

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

public static void Main()

xxx a = new yyy();

}
}

interface xxx

struct yyy : 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

public static void Main()

xxx a = new yyy();

struct yyy

class xxx : 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

public static void Main()

sealed struct yyy

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

public static void Main()

{
}

abstract struct yyy

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

public static void Main()

protected struct xxx { }

Compiler Error

a.cs(7,1): error CS1527: Namespace elements cannot be explicitly declared as private or


protected

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

public static void Main()

yyy a = new yyy();

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

public static void Main()

yyy a = new yyy();

System.Console.WriteLine(a.ToString());
}

struct yyy : System.Object

Compiler Error

a.cs(9,14): error CS0527: 'System.Object' : type in interface list is not an interface

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

public static void Main()

xxx x,y;

yyy a,b;

x = new xxx(1); y = new xxx(2);

a = new yyy(1); b = new yyy(2);


System.Console.WriteLine(x.i + " " + y.i + " " + a.i + " " + b.i);

x = y; a = b;

System.Console.WriteLine(x.i + " " + y.i + " " + a.i + " " + b.i);

x.i = 100; a.i = 200;

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

100 2 200 200

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

public static void Main()

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

public static void Main()

struct xxx

public ~xxx()

}
Compiler Error

a.cs(9,9): error CS0575: Only class types can contain destructors

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.

Você também pode gostar