Академический Документы
Профессиональный Документы
Культура Документы
C#.NET
BCCA – III
Sem - VI
By
Paper - I: C#.Net
UNIT - I
Introducing C# - What is C#? Evaluation of C#, Characteristics of C#, Application of C#, how does C# differ
from C++? How does C# differ from C#? Understanding .NET: The C# Environment – The .NET
Strategy, The Origin of .NET Technology, The .NET Framework, The Common Langue Runtime, Framework
Base Class, User and Program Interface, Visual Studio .NET, .NET Languages, Benefits of the .NET
Approach, C# and .NET. Overview of C# - Introduction, A Simple C# Program, Namespaces, Adding
Comments, Main Running Value, Using Aliases for Namespaces Classes, Passing String Objects to WriteLine
Method, Command Line Argument, Main with Class, Providing Interactive Input, Using Mathematical
Function, Multiple Main Methods, Compile Time Error, Program Structure, Program Coding Style. Literals,
Variables and Data Types – Introduction, Literals, Variables, Data Types, Value Types, Reference Type,
Declaration Types, Initialization of Variables, Default Value, Constant Variable, Scope of Variables, Boxing
and Unboxing. Operators and Expressions – Introduction, Arithmetic Operators, Relational Operators,
Logical Operators, Assignment Operators, Increment and Decrement Operators, Conditional Operators,
Bitwise Operators, Special Operators, Arithmetic Expressions, Evaluation of Expressions, Precedence of
Arithmetic Operators, Type Conversion, Operator Precedence and Associativity, Mathematical Function.
UNIT - II
Decision Making and Branching – Introduction, Decision Making with if Statement, Simple if Statement,
The if…else Statement, The else if Ladder, The Switch Statement, The ? : Operator, Decision Making and
Looping – Introduction, The while Statement, The do Statement, The for Statement, The foreach Statement,
Jumps in Loops. Methods in C# - Introduction, Declaring Methods, The Main Method, Invoking Methods,
Nesting of Methods, Method Parameters, Pass by Value, Pass by Reference, The Output Parameters,
Variables Argument List, Methods Overloading. Handling Arrays – Introduction, One-Dimensional Array,
Creating an Array, Two-Dimensional Array, Variable-Size Arrays, TheSystem.Array Class, ArrayList Class.
Manipulating Strings – Introduction, Creating String, String Methods, Inserting String, Comparing String,
Finding String, Mutable String Arrays of String, Regular Expressions.
UNIT - III
Structures and Enumerations – Introduction, Structure, Structs with Methods, Nested Structs, Difference
between Classes and Structs, Enumerations, Enumerator Base Type, Enumerator type Conversion. Classes
and Objects - Introduction, Basic Principle of OOP, Defining a Class, Adding Variables, Adding Methods,
Member Access Modifiers, Creating Objects, Accessing Class Members, Constructors, Overloaded
Constructors, Static Members, Static Constructors, Private Constructors, Copy Constructors, Destructors,
Member Initialization, The This Reference, Nesting of Members, Constant Members, Read-only Members,
Properties, Indexers. Inheritance and Polymorphism – Introduction, Classical Inheritance, Containment
Inheritance, Defining a Subclass, Visibility Control, Defining Subclass Constructors, Multilevel Inheritance,
Hierarchical Inheritance, Overriding Methods, Hiding Methods, Abstract method, Sealed Class: Preventing
Inheritance, Sealed Methods, Polymorphism.
UNIT - IV
Interface: Multiple Inheritances – Introduction, Defining an Interface, Extending Interface, Implementing
Interface, Interface and Inheritance, Explicit Interface Implementation, Abstract Class and Interface.
Operator Overloading – Introduction, Overloadable Operators, Need for Operator Overloading, Defining
Operator Overloading, Overloading Unary Operator, Overloading Binary Operator, Overloading Comparison
Operator. Managing Errors and Exceptions – Introduction, What is Debugging?, Types of Errors,
Exceptions, Syntax of Exception Handling Code, Multiple Catch Statements, The Exception Hierarchy,
General Catch Handler, Using Finally Statement, Nested Try Blocks, Throwing Our Own Exceptions,
Checked and Unchecked Operators, Using Exceptions for Debugging.
Text Book:
1. E. Balagurusamy, Programming in C#, McGraw-Hill.
UNIT – III
Structures and Enumerations
Introduction
C# supports two kinds of value types, namely, predefined types and user-defined types. we have
defined and used the predefined data types such as int and double throughout. C# allows us to define
our own complex value types(known as user-defined value types) based on these simple data types.
There are two sorts of value types we can define in C#:
1. Structures
2. Enumerations
Structures
Structures are similar to classes in C#. Although classes will be used to implement most objects. It is
desirable to use structs where simple composite data types are required. Because they are value types
stored on the stack, they have the following advantages compared to class objects stored on the heap:
1. They are created much more quickly than heap allocated types.
2. They are instantly and automatically deallocated once they go out of scope.
3. It is easy to copy value type variables on the stack.
The performance of programs may be enhanced by judicious use of structs.
Defining a Struct
A struct in C# provides a unique way of packing together data of different types. It is a convenient
tool for handling a group of logically related data items. It creates a template that may be used to
define its data properties. Once the structure type has been defined, we can create variables of that
type using declarations that are similar to the built-in type declarations.
Structs are declared using the struct keyword. The simple form of a struct definition is as follows:
struct struct-name
{
data member1;
data member2;
}
Example:
struct Student
{
public string Name;
public int RollNumber;
public double TotalMarks;
}
The keyword struct declares Student as a new data type that can hold three variables of different
data types. These variables are known as members or fields or elements. The identifier Student can
now be used to create variables of type Student. Example:
Student s1; //declare a student
s1 is a variable of type Student and has three member variables are defined by the template.
Copying Structs
We can also copy values from one struct to another. Example:
Student s2; //s2 is declared
s2 = s1;
This will copy all those values from s1 to s2.
Note that we can also use the operator new to create struct variables.
Student s3 = new Student();
A struct variable is initialized to the default values of its members as soon as it is declared.
Example
The constructor method has the same name as struct and declared as public. The constructor is
invoked as follows:
Number n1 = new Number(100);
This statement creates a struct object n1 and assigns the value 100 to its only data member number.
C# does not support default(i.e. paramenterless) constructors.
Example
Nested Structs
C# permits declaration of structs nested inside other structs. The following code is valid:
struct Employee
{
public string name;
public int code;
public struct Salary
{
public double basic;
public double allowance;
}
}
We can also use struct variables as members of another struct. This implies nesting of references to
structs.
struct M
{
Public int x;
}
struct N
{
public M m; //object of M
public int y;
}
…
…
N n;
n.m.x = 100; //x is a member of m, a member of n
n.y = 200; // y is a member of n
Example:
Enumerations
An enumeration is a user-defined integer type which provides a way for attaching names to numbers,
thereby increasing the comprehensibility of the code. The enum keyword automatically enumerates
a list of words by assigning them values 0, 1, 2 and so on. This facility provides an alternative means
of creating „constant‟ variable names. The syntax of an enum statement is illustrated below:
enum Shape
{
Circle, //ends with comma
Square, //ends with comma
Triangle //no comma
}
This can be written in one line as follows:
enum Shap {Circle, Square, Triangle}
Here, Circle has the value 0, Square has the value 1 and Triangle has the value 2. Other examples
of enum are:
enum Color {Red, Blue, Green, Yellow}
enum Position {Off, On}
enum Day {Mon, Tue, Wed, Thu, Fri, Sat, Sun}
Example:
using System;
class Area
{
public enum Shape
{
Circle,
Square
}
public void AreaShape(int x, Shape shape)
{
double area;
switch(shape)
{
Case Shape.Circle:
area = Math.PI * x * x;
Console.WriteLine(“Circle Area = ” + area);
break;
case Shape.Square:
area = x*x;
Console.WriteLine(“Square Area = ” + area);
break;
default:
Console.WriteLine(“Invalid Input”);
break;
}
}
}
class EnumTest:
{
public static void Main()
{
Area area = new Area();
area.AreaShape(15, Area.Shape.Circle);
area.AreaShape(15, Area.Shape.Square);
area.AreaShape(15,(Area.Shape)1);
area.AreaShape(15,(Area.Shape)10);
}
}
Enumerator Initialization
As mentioned earlier, by default, the value of the first enum member is set to 0, and that of each
subsequent member is incremented by one. However, we may assign specific values for different
members, if we so desire.
Example:
enum Color
{
Red = 1,
Blue = 3,
Green = 7,
Yellow = 5
}
We can also have expressions, as long as they use the already defined enum members.
Example:
enum Color
{
Red = 1,
Blue = Red + 2,
Green = Red + Blue + 3,
Yellow = Blue + 2
}
If the declaration of an enum member has no initialize, then its value is set implicitly as follows:
If it is the first member, its value is zero.
Otherwise, its value is obtained by adding one to the value of the previous member.
Consider the following enum declaration:
enum Alphabet
{
A,
B = 5,
C,
D = 20,
E
}
The member A is set to zero. Since the member B is explicitly given the value 5, the value of C is set
to 6. Similarly, E is set to 21.
Console.WriteLine(“d1 = ” + d1);
Console.WriteLine(“d2 = ” + (int) d2);
Console.WriteLine(“d3 = ” + d3);
Console.WriteLine(“d4 = ” + d4);
}
}
Defining a Class
A class is a user-defined data type with a template that servers to define its properties. Once the class
type has been defined, we can create “variable” of that type using declarations that are similar to the
basic type declaration. In C#, these variables are termed as instances of classes, which are the actual
objects. The basic form of a class definition is:
class classname
{
[variables declaration;]
[methods declaration;]
}
class is a keyword and classname is any valid C# identifier. Everything inside the square brackets is
optional. This means that the following would be a valid class definition:
class Empty
{
}
Because the body is empty, this class does not contain any properties and therefore cannot be
anything. We can, however, compile it and even create objects using it. C++ programmers may note
that there is no semicolon after closing brace.
Adding Variables
Data is encapsulated in a class by placing data fields inside the body of the class definition. These
variables are called instance variables because they are created whenever an object of the class is
instantiated. We can declare the instance variables exactly the same way as we declare local
variables. Example:
class Rectangle
{
int length;
int width;
}
The class Rectangle contains two integer type instance variables. it is allowed to declare them in one
line as
int length, width;
Remember these variables are only declared and therefore no storage space has been created in the
memory. Instance variables are also known as member variables.
Adding Methods
A class with only data fields(and without methods that operate on that data) has no life. The objects
created by such a class cannot respond to any messages. We must therefore and methods that are
necessary for manipulating the data contained in the class. Methods are declared inside the body of
the class but immediately after the declaration of instance variables. The general form of a method
declaration is
type methodname (parameter-list)
{
Method-body;
}
The body actually describes the operations to be performed on the data. Let us consider the
Rectangle class again and add a method getData() to it.
class Rectangle
{
int length;
int width;
void getData(int x,int y) //Method declaration
{
length = x;
width = y;
}
}
Note that the method has a return type of void because it does not return any value. we pass two
integer values to the method which are then assigned to the instance variable length and width. The
getData method is basically added to provide values to the instance variables. Notice that we are
able to use directly length and width inside the method.
Creating Objects
An object in C# is essentially a block of memory that contains space to store all the instance
variables. creating an object is also referred to as instantiating an object.
Obejects in are created using the new operator. The new operator creates an object of the specified
class and return a reference to that object. Here is an example of creating an object of type
Rectangle.
Rectangle rect1; //declare the object
rect1 = new Rectangle(); //instantiate the object
The first statement declares a variable to hold the object deference and the second one actually
assigns the object reference to the variable. the variable react1 is now an object ot the Rectangle
class.
Both statements can be combined into one as shown below:
Rectangle rect1 = new Rectangle();
The method Rectangle() is the default constructor of the class. We can create any number of objects
of Rectangle. Example:
Rectangle rect1 = new Rectangle();
Rectangle rect2 = new Rectangle();
and so on.
Here objectname is the name of the object, variable name is the name of the instance variable inside
the object that we wish to access, methodname is the method that we wish to call, and parameter-list
is a comma separated list of “actual values” (or expressions) that must math in type and number with
the parameter list of the methodname declare in the class. the instance variables of the Rectangle
calss may be accessed and assigned values as follows:
rect1.length = 15;
rect1.widht = 10;
rect2.length = 20;
rect2.width = 12;
Note that the two objects rect1 and rect2 store different values as shown below:
This is one way of assigning values to the variables in the objects. Another way and more convenient
way of assigning values to the instance variables is to use a method that is declared inside the class.
In our case, the method getData can be used to do this work. We can call the getData method on any
Rectangle object to set the values of both length and width. Here is the code segment to achieve
this.
Rectangle rect1 = new Rectangle(); //Creating an
Object
rect1.getData(15,10); //Calling the method using the object
This code creates rect1 object and then passes in the values 15 and 10 for the x and y parameters of
the method getData. This method then assigns these values to length and width variables
respectively. For the sake of convenience, the method is again shown below:
void getData(int x, int y)
{
length = x;
width = y;
}
Now that the object rect1 contains values for its variables, we can compute the area of the rectangle
represented by rect1. This again can be done in two ways.
The first approach is to access the instance variable using the dot operator and compute the
are. That is,
int area1 = rect1.length * rect1.width;
The second approach is to call the method rectArea declared inside the class. That is,
int area1 = rect1.rectArea(); //Calling the method
Constructors
We know that all objects that are created must be given initial values. We have done this earliear
using two approaches. The first approach uses the dot operator to access the instance variables and
then assign values to them individually. It can be tedious approach to initialize all the variables of all
the objects.
The second approach take the help of a method like getData to initialize each object individually
using statement like,
rect1.getData(15,10);
It would be simpler and more concise to initialize an object when it is first created. C# supports a
special type of method, called a constructor, that enables an object to initialize itself when it is
created.
Constructors have the same name as the class itself. Secondly, they do not specify a return type, not
even void. This is because they return the instance of the class itself.
Let us consider our Rectangle class again. We can now replace the getData method by a constructor
method as shown below:
class Rectangle
{
int length;
int width;
Rectangle(int x, int y) //Constructor method
{
length = x;
width = y;
}
int rectArea()
{
return(length * width);
}
}
Overloaded Constructors
In C#, it is possible to create methods that have the same name, but different parameter lists and
different definitions. This is called method overloading. Method overloading is used when objects
are requireto perform similar tasks but using different input parameters. When we call a method in an
object, C# matches up the method name first and then the number of type of parameters do decide
which one of the diefinitions to execute. This process is known as polymorphism. We can extend the
concept of method overloading to provide more than one constructor to a class.
To create an overloaded method, all we have to do is provide several different method definitions in
the class, all with the same name, but with different parameter lists. The difference may either be in
the number or type of arguments. That is, each parameter list should be unique. Note that the
method‟s return type does not play any role in this. Here is an example of creating an overloaded
constructor:
class Room
{
float length;
float breadth;
Room(float x, float y) //constructor1
{
length = x;
breadth = y;
}
Room(float x) //constructor2
{
length = breadth = x;
}
int area()
{
return(length * breadth);
}
}
Here, we are overloading the constructor method Room(). An object representing a rectangular room
will be created as:
Room room1 = new Room(25.0, 15.0); //using constructor1
On the other hand, if the room is square, then we may create the corresponding object as:
Room room2 = new Room(20.0); //using constructor2
Static Members
We have seen that a class basically contains two sections. One declares variables and the other
declares methods. These variables and methods are called instance variables and instance methods.
This is because every time the class is instantiated, a new copy of each of them is created. They are
accessed using the objects (with dot operator).
Let us assume that we want to define a member that is common to all the objects and accessed
without using a particular object. That is, the member belongs to the class as a whole rather than the
objects created from the class. Such members can be defined as follows:
static int count;
Static Constructors
Like any other static members, we can also have static constructors. A static constructor is called
before any object of the class is created. This is useful to do any housekeeping work that needs to be
done once. It is usually used to assign initial values to static data members.
A static constructor is declared by prefixing a a static keyword to the constructor definition. It
cannot have any parameters.
Example:
class Abc
{
static Abc() //No parameters
{
… //set values for static members here
}
}
Note that there is no access modifier on static constructors. It cannot take any. A class can have only
one static constructor.
Private Constructors
C# does not have global variables or constants. All declarations must be contained in a class. In
many situations, we may wish to define some utility classes that contain only static members. Such
classes are never required to instantiate objects. Creating objects using such classes may be
prevented by adding a private constructor to the class.
Copy Constructors
A copy constructor creates an object by copying variables from another object. For example, we may
wish to pass an Item object to the Item constructor so that the new Item object has the same values
as the old one.
Since C# does not provide a copy constructor, we must provide it ourselves if we wish to add this
feature to the class. A copy constructor is defined as follows:
public Item(Item item)
{
code = item.code;
price = item.price;
}
The copy constructor is invoked by instantiating an object of type Item and passing it the object to
be copied.
Example:
Item item2 = new Item(item1);
Now, item2 is a copy of item1.
Destructors
A destructor is opposite to a constructor. It is a method called when an object is no more required.
The name of the destructor is the same as the class name and is preceded by a tilde(~). Like
constructors, a destructor has no return type.
Example:
class Fun
{
…
…
~Fun() //No arguments
{
}
}
Note that the destructor takes no arguments.
C# manages the memory dynamically and uses a garbage collector, running on a separate thread, to
execute all destructors on exit. The process of calling a destructor when an object is reclaimed by the
garbage collector is called finalization.
Memer Initialization
In addition to using constructors and methods to provide initial values to the objects, C# also allows
us to assign initial values to individual data members at the time of declaration.
Example:
class Initialization
{
int number = 100;
static double x = 1.0;
string name = “John”;
Vehicle car = new Vehicle(800, “maruti”);
…
…
}
Note that other object-oriented languages like C++ and Java do not support this feature. When the
variables are provided with the initial values at the time of declaration, the values are assigned as
follows:
This Reference
C# supports the keyword this which is a reference to the object that called the method. The this
reference is available within all the member methods and always refers to the current instance. It is
normally used to distinguish between local and instance variables that have the same name. Consider
the code segment shown below:
class Integers
{
int x;
int y;
public void SetXY(int x,int y)
{
this.x = x;
this.y = y;
}
…
…
}
In the assignment statements, this,x and this.y refer to the class members named x and y whereas
simple x and y refer to the parameters of the SetXY() method.
Nesting of Classes
In C#, it is possible to define a type within the scope of another type. C# allows classes, structs,
interfaces and enums to nest others.
Example:
public class Outer
{
… //members of outer class
…
public class Inner
{
Constant Members
C# permits declaration of data fields of a class as constants. This can be done using the modifier
const.
Example:
public const int size = 100;
The member size is assigned the value 100 at compile time and cannot be changed later. Any attempt
to assign a value to it will result in compilation error. It also means its value must be set when it is
defined. For instance,
public const int size;
is wrong and will cause a compilation error. The const members are implicitly static. The value is by
definition constant and therefore only one copy of it is stored which is common for all objects of the
class. This implies that we must access the const members using the class name as we do with the
static members.
Although const members are implicitly static, we cannot declare them so explicitly using static. For
example, the statement
public static const int size = 100;
is wrong and will produce compile-time error.
When they are declared as instance fields, they can take different values with different objects.
Consider the code below.
class Numbers
{
public readonly int m;
public static readonly int n;
public Numbers(int x)
{
m = x;
}
static Numbers()
{
n = 100;
}
}
The value for m is provided at the time of creation of an object using the constructor with parameter
x. This value will remain constant for that object. Remember, the variable n is assigned a value of
100, even before the creation of any object of Numbers.
Properties
One of the design goals of object-oriented systems is not to permit any direct access to data
members, because of the implications of integrity. It is normal practice to provide special methods
known as accessor methods to have access to data members. We must use only these methods to set
or retrieve the values of these members.
Example: Accessing private data using accessor methods
using System;
class Number
{
private int number
public void SetNumber(int x) //accessor method
{
number = x; //private number accesser
}
public int GetNumber() //accessor method
{
return number;
}
}
class NumberTest
{
public static void Main()
{
Number n = new Number();
n.SetNumber(100); //set value
Console.WriteLine(“Number = ” + n.GetNumber()); //get value
//n.number; //Error ! Cannot access private data
}
}
Example: Implementing a property
using System;
class Number
{
private int number;
public int Anumber //property
{
get
{
return number;
}
set
{
number = value;
}
}
}
class PropertyTest
{
public void static Main()
{
Number n = new Number();
n.Anumber = 100;
int m = n.Anumber;
Console.WriteLine(“Number = ” + m);
}
}
The class now declares a property call Anumber of type int and defines a get accessor method and a
set accessor method. The getter method used the keyword return to return the filed‟s value to the
caller. The setter method uses the keyword value to receive the value being passed in form the user.
The type of value is determined by the type of property.
Indexers
Indexers are location indicators and are used to access class objects, just like accessing elements in
an array. They are useful in cases where a class is a container for other objects.
An indexer looks like a property and is written the same way a property is written, but with two
differences:
The indexer takes an index argument and looks like an array.
The indexer is declared using the name this.
The indexer is implemented through get and set accessors for the [] operator.
Example:
public double this[int idx]
{
get
{
//Return desired data
}
set
{
//Set desired data
}
}
The implementation rules for get and set accessors are the same as for properties. The return type
determines what will be returned, in this case a double. The parameter inside the square brackets is
used as the index. In this example, we have used an int, but it case be any object type.
Example: Implementation of an Indexer
using System;
using System.Collections;
class List
{
ArrayList array = new ArrayList();
public object this[int index]
{
get
{
if(index <0 || index >= array.Count)
{
return null;
}
else
{
return(array[index]);
}
}
set
{
array[index] = value;
}
}
}
class InexerTest
{
public static void Main()
{
List list = new List();
list[0] = “123”;
list[1] = “abc”;
list[2] = “xyz”
for(int i=0;i<=list.Count;i++)
console.WriteLine(list[i]);
}
}
Indexers are sometimes referred to as „smart arrays‟. As pointed out earlier, indexers and properties
are very similar in concept, but differ in the following ways:
A property can be static member, whereas an indexer is always an instance member.
A get accessor of a property corresponds to an method with no parameters, whereas a get
accessor of an indexer corresponds to a method with the same formal parameter list as the
indexer.
A set accessor of a property corresponds to a method with a single parameter named value,
whereas a set accessor of an indexer corresponds to a method with the same formal parameter
list as the indexer, plus the parameter named value.
It is an error for an indexer to declare a local variable with the same name as an indexer
parameter.
Classical Inheritance
Inheritance represents a kind of relationship between two classes. Let us consider two classes A and
B. We can create a class hierarchy such that B is derived from A.
Class A, the initial class that is used as the basis for the derived class is referred to as the base class,
parent class or superclass. Class B, the derived class, is referred to as derived class, child class or sub
class. A derived is a completely new class that incorporates all the data and methods of its base class.
It can also have its own data and method members that are unique to itself. That is, it can enhance the
content and behavior of the base class.
We can now create objects of classes A and B independently. Example:
A a; //a is object of A
B b; //b is object of B
In such cases, we say that the object b is a type of a. Such relationship between a and b is referred to
as „is-a‟ relationship. Examples of is-a relationship are:
Dog is-a type of animal
Manager is-a type of employee
Ford is-a type of car.
The classical inheritance allows subclasses to inherit all the variables and methods of their parent
classes. inheritance may take different forms:
Single Inheritance (only one super class)
Multiple Inheritance (several super classes)
Hierarchical Inheritance ( one super class, many subclasses)
Multilevel Inheritance (Derived from a derived class)
Containment Inheritance
We can also define another form of inheritance relationship known as containership between class A
and B. Example:
class A
{
…
}
class B
{
…
A a; //a is contained in b
}
B b;
…
In such cases, we say that the object a is contained in the object b. This relationship between a and b
is referred to as „has-a‟ relationship. The outer class B which contains the inner class A is termed the
„parent‟ class and the contained class A is termed as „child‟ class. Examples are
Car has-a radio
House has-a store room
City has-a road
Define a Subclass
A subclass is defined as follows:
class subclassname : baseclassname
{
Variables declaration;
Methods declaration;
}
The symbol : signifies that the porpoerties of the superclassname are derived in subclassname. The
subclass will now contains its own variables and methods as well as those of the superclass. This
kind of situation occurs when we want to add some more properties to an existing class without
actually modifying it.
Example: Illustration of a simple inheritance
using System;
class Item //base class
{
public void Company()
{
Console.WriteLine(“Item Code = XXX”);
}
}
class Fan : Item
{
public void Model()
{
Console.WriteLine(“Fan Model : Classic”);
}
}
class SimpleInheritance
{
public static void Main()
{
Item item = new Item();
Fan fan = new Fan();
item.Company();
fan.Company();
fan.Model();
}
}
Characteristics of Inheritance
A derived class extends its direct base class. It can add new members to those it inherits.
However, it cannot change or remove the definition of an inherited member.
Constructors and destructors are not inherited. All other members, regardless of their declared
accessibility in base class, are inherited. However, their accessibility in the derived class
depends on their declared accessibility in the base class.
An instance of a class contains a copy of all instance fields declared in the class and its base
classes.
A derived class can hide an inherited member.
A derived class can override an inherited member.
Visibility Control
When implementing inheritance, it is important to understand how to establish visibility levels for
our classes and their members. C# has four types of accessibility modifiers which may be applied to
classes and members to specify their level of visibility. They include public, private, protected or
internal.
Class Visibility
Each class needs to specify its level of visibility. Class visibility is used to decide which parts of the
system can create class objects.
A C# class can have one of the two visibility modifiers: public or internal. If we do not explicitly
mark the visibility modifier of a class, it is implicitly set to „internal‟ that is, b default all classes are
internal. Internal classes are accessible within the same program assembly and are not accessible
from outside the assembly.
Classes marked public are accessible everywhere, both within and outside the program assembly.
All the classes contained in the .NET Class Framework are marked public so as to enable all
developers to have access to them and use them for configuring applications and services.
Accessibility Constraints
C# imposes certain constraints on the accessibility of members and classes when they are used in the
process of inheritance.
The direct base class of a derived class must be at least as accessible as the derived class
itself.
Accessibility domain ofa member is never larger than that of the class containing it.
The return type of method must be at least as accessible as the method itself.
For example, the inheritance relationship
class A
{
…
}
public class B : A
{
…
}
Is illegal because A is „internal‟ by default and B is public. A should be at least as accessible as B.
Consider another example
class A
{
private class B
{
public int x;
}
}
Here, the public data x is not accessible outside the class B. It is due to the constraint imposed by the
accessibility of class B. Because B is private, the public on x is reduced to private.
{
height = z;
}
public int Volume()
{
return(length*breadth*height);
}
}
class InherTest
{
public static void Main()
{
BedRoom room1 = new BedRoom(14,12,10);
int area1 = room1.Area(); //superclass method
int volume1 = room1.Volume(); //subclass method
Console.WriteLine(“Area1 = ” + area1);
Console.WriteLine(“Volume1 = ” + volume1);
}
}
Subclass Constructor
A subclass constructor is used to construct the instance variables of both the subclass and the
superclass. The subclass constructor uses the keyword base to invoke the constructor method of the
superclass.
public BedRoom(int x,int y,int z):base(x,y)
{
height = z;
}
Multilevel Inheritance
A common requirement in object-oriented programming is the use of a derieved class as a super
class. C# supports this concept and uses it extensively in building its class library. This concept
allows us to build a chain of classes.
The class A serves as a base class for the derived class B which in turn serves as a base class for the
derived class C. The chain ABC is known as inheritance path.
A derived class with multilevel base classes is declared as follows:
class A
{
….
….
}
class B : A //First Level
{
….
….
}
class C : B //Second Level
{
….
….
}
Hierarchical Inheritance
Another interesting application of inheritance is to use it as a support to the hierarchical design of a
program. Many programming problems can be cast into a hierarchy where certain features of one
level are shared by many others below the level. As an example, Fig 8.6 shows a hierarchical
classification of accounts in a commercial bank. This is possible because all the accounts passes
certain common features.
Overriding Methods
We known that a method defined in a super class is inherited by its subclass and is used by the
objects created by the subclass. Method inheritance enables us to define and use methods repeatedly
in subclasses without having to define the methods again in subclass.
However, there may be occasions when we want an object to responds to the same method but have
different behavior when that method is called. That means, we should override the method defined in
the superclass. This is possible by defineing a method in the subclass that has the same name, same
arguments and same return type as a method in the superclass. Then, when that methods is called, the
method defined in the subclass is invoked and executed instead of the one in the superclass, provided
that:
We specify the method of base class as virtual.
Implement the method in subclass using the keyword overrirde.
Example : Illustration of method overriding
using System;
class Super
{
protected int x;
public Super(int x)
{
this.x = x;
}
public virtual void Display() //method defined
{
System.out.println(“Super x = “ + x);
}
}
class Sub : Super //derived class
{
int y;
public Sub(int x,int y): base(x)
{
this.y = y;
}
public override void Display() //method defined again with override
{
Console.WriteLine(“Super x = ” + x);
Console.WriteLine(“Sub y = ” + y);
}
}
class OverrideTest
{
public static void Main()
{
Sub s1 = new Sub(100,200);
s1.Display();
}
}
Output
Super x = 100
Sub y = 200
Hiding Methods
When we were overriding a base class method, we decalred the base class method as virtual and the
subclass method with the keyword override. This resulted in „hiding‟ the base class method from the
subclass.
Now, let us assume that we wish to derive from a class provided by someone else and we also want
to redefine some methods contained in it. Here, we cannot declare the base class methods as virtual.
Then, how do we override a method declaring it virtual? This is possible in C#. We can use the
modifier new to tell the compiler that the derived class method „hides‟ the base class method.
Example: Hiding a base class method
using System;
class Base
{
public void Display()
{
Console.WriteLine(“Base Method”);
}
}
Class Derived :Base
{
public new void Display() //hides base method
{
Console.WriteLine(“Derived Method”);
}
}
class HideText
{
public static void Main()
{
Derived d = new Derived();
d.Display();
}
}
Abstract Classes
In a number of hierarchical applications, we would have one base class and a number of different
derived classes. The top-most base class simply acts as a base for others and is not useful on its own.
In such situations, we might not want any one to create its objects. We can do this by making the
base class abstract.
The abstract is a modifier and when used to declare a class indicates that the class cannot be
instantiated. Only its derived classes can be instantiated.
Example
abstract class Base
{
---
}
class Derived : Base
{
…
}
…
…
We cannot create object of Base type but we can derive its subclasses which can be instantiated.
Some characteristics of an abstract class are the following:
It cannot be instantiated directly.
It can have abstract medhod.
We cannot apply a sealed modify to it.
Abstract Methods
Similar to abstract classes, we can also crete abstract methods. When an instance method declaration
includes the modifier abstract, the method is said to be an abstract method.
An abstract method is implicitly a virtual method and does not provide any implementation.
Therefore, an abstract method does not have method body.
Example:
public abstract void Draw(int x,int y);
Note that the method body simply consists of a semicolon. Some characteristics of an abstract
method are the following:
1. It cannot have implementation.
2. Its implementation must be provided in non-abstract derived classes by overriding the method.
3. It can be declared only in abstract classes.
4. It cannot take either static or virtual modifiers.
5. An abstract declaration is permitted to override a virtual method.
Sealed Methods
When an instance method declaration includes the sealed modifier, the method is said to be a sealed
method. It means a derived class cannot override this method.
A sealed method is used to override an inherited virtual method with the same signature. That means,
the sealed modifier is always used in combination with the override modifier.
Example:
class A
{
public virtual void Fun()
{
…
}
}
class B : A
{
public sealed overrirde void Fun()
{
…
}
}
The sealed method Fun() overrirdes the virtual method Fun() define in a Class A. Any derived class
of B cannot further override the method Fun().
Polymorphism
Polymorphism means „one name, many forms‟. Essentially, polymorphism is the capability of one
object to behave in multiple ways. Polymorphism can be achieved in two ways:
Operation Polymorphism
Inclusion Polymorphism
Operation Polymorphism
Operation polymorphism is implemented using overloaded method and operators. We have already
used the concept of overloading. The overloaded methods are „selected‟ for invoking by matching
arguments, in terms of number, type and order. This information is known to the compiler at the time
of compilation and therefore, the compiler is able to select and bind the appropriate method to the
object for a particular call at compile time itself. This process is called early binding, or static
binding, or static linking. It is also known as compiler time polymorphism.
Early binding simply means that an object is bound to its method call at compile time.
Inclusion Polymorphism
Inclusion polymorphism is achieved through the use of virutual functions. Assume that the class A
implements a virtual method M and classes B and C that are derived from A override the virtual
method M. When B is cast to A, a call to the method M from A is dispatched to B. Similarly, when
C is cast to A, a call to M is dispatched to C. The decision on exactly which method to call is
delayed until runtime and, therefore, it is also known as runtime polymorphism. Since the method is
linked with a particular class much later after compilation, this process is termed late binding. It is
also known as dynamic binding because the selection of the appropriate method is done dynamically
at runtime.
Example : Inclusion Polymorphism
using System;
class Maruthi
{
public virtual void Display() //virtual method
{
Console.WriteLine(“Maruthi car”);
}
}
class Esteem : Maruthi
{
public override void Display()
{
Console.WriteLine(“Maruthi Esteem”);
}
}
class Zen :Maruthi
{
public override void Display()
{
Console.WriteLine(“Maruthi Zen”);
}
}
class inclusion
{
public static void Main()
{
Maruthi m = new Maruthi();
m = new Esteem(); //upcasting
m.Display();
m = new Zen(); //upcasting
m.Display();
}
}
Extension Methods
Consider a situation where you want to extend the functionality of an existing class by adding a new
method to it. A simple way of doing this is to create a derived class and add the new method to it. C#
and later versions support another feature called extension methods that allow you to extend an
existing type without modifying the original type or creating a new derived type.
Extension method are defined as static methods but are called using the same syntax as that of
instance methods.
Example: Use of extension methods
namespace Extension
{
class App
{
static void Main(String[] args)
{
int x = 3;
Console.WriteLine(x.fact());
Console.ReadLine();
}
}
public static class MyMathExtension
{
public static int fact(this int x)
{
if(x<=1) return 1;
if(x==2) return 2;
else
return x*fact(x-1)
}
}
}