C#.NET-UNIT2
C#.NET-UNIT2
C# FUNDAMENTALS
using System;
class Test
{
public static int Main(string[] args)
{
Console.WriteLine("Hello World!");
return 0;
}
}
• Every executable C# application must contain a class defining a Main() method, which is used to signify the entry
point of the application.
• Main() is used with the public and static keywords.
• The public members are accessible from other types, while static members are scoped at the class level (rather
than the object level) and can thus be invoked without the need to first create a new class instance (or object).
• In addition to the public and static keywords, this Main() method has a single parameter, which is an array of
strings (string[] args).
• This parameter may contain any number of incoming command-line arguments.
• The program Test.cs makes use of the Console class, which is defined within the System namespace.
NOTE: We can use Console.ReadLine() to ensure the command prompt launched by Visual Studio 2005 remains
visible during a debugging session until we press the Enter key.
NOTE: The Main() method may also be defined as private. Doing so ensures other assemblies cannot directly
invoke an application’s entry point. Visual Studio 2005 automatically defines a program’s Main() method as
private. Obviously, your choice of how to construct Main() will be based on two questions. First, do you need
to process any user-supplied command-line parameters? If so, they will be stored in the array of strings.
Second, do you want to return a value to the system when Main() has completed? If so, you need to return
an integer data type rather than void.
using System;
class Test
{
public static int Main(string[] args)
{
Test c1;
c1.SomeMethod(); //error!! Must use “new”
...
}
}
Object creation:
To illustrate the proper procedures for object creation, consider the following code:
using System;
class Test
{
public static int Main(string[] args)
{
/ / You can declare and create a new object in a single line...
Test c1 = new Test();
/ / ...or break declaration and creation into two lines.
Test c2;
• The new keyword will calculate the correct number of bytes for the specified object and acquires sufficient
memory from the managed heap.
• Here, we have allocated two objects c1 and c2, each of which points to a unique instance of Test type.
Note that C# object variables are really a reference to the object in memory, not the actual object itself.
• Thus, c1 and c2 each reference a distinct Test object allocated on the managed heap.
• In the previous program, the objects have been constructed using the default constructor, which by
definition never takes arguments.
• Every C# class is automatically provided with a free default constructor, which you may redefine if needed.
• The default constructor ensures that all member data is set to an appropriate default value. But in C++,
un-initialized data gets garbage value.
Usually, classes provide additional constructors also. Using this, we can initialize the object variables at the time
of object creation. Like in Java and C++, in C# constructors are name
identically to the class they are constructing, and they never provide a return value (not even void).
Program 3.3
using System;
class Test
{
public string userMessage;
userMessage = msg;
}
2. As soon as we define a custom constructor for a class type, the free default constructor is removed. If
we want to create an object using the default constructor, we need to explicitly redefine it as in the
preceding example.
Program 3.5
class Test
{
public int a; //default value is 0
public byte b; //default value is 0
public char c; //default value is null
public string s; //default value is nu ll
public static void Main()
{
Test t=new Test();
Console.WriteLine(“{0}, {1}, {2}, {3}”, a, b, c, s);
}
}
All the variables will be initialized to their default values when we start debugging. However, we can not
expect the same within method scope. For example, the following program will generate an error.
class Test
{
public static void Main()
{
int a; //need to assign some value to ‘a’
Console.WriteLine(“{0}”, a); //Error: Unassigned local variable ‘a’
}
}
NOTE: There is an exception for the mandatory assignment of a local variable. If the local variable is used as
an output parameter, then it need not be initialized before use. However, note that, they are used to receive
the value from a function.
class Test {
private int a;
Test()
{ a=5;
}
Test(int k)
{
a=5; …….
}
Test(string s)
{
a=5; …….
}
}
Though the above code is valid, there is redundancy in code. We can write a function for such initialization
like –
Test()
{
init();
}
Test(int k)
{ init()
…….
}
Test(string s)
{
init()
…….
}
}
Here we have function call instead of assignment. Thus, redundancy still exists. To avoid such situation, C#
provides the initialization of member variables directly within a class as shown –
class Test {
private int a =5; private
string s= “Hello”;
…………..
}
This facility was not available in C++. Note that, such an initialization will happen before the constructor gets
called. Hence, if we provide any other value to a variable through constructor, the previous member
assignment will be overwritten.
Member Meaning
BackgroundColor These properties set the background/foreground colors for the
ForegroundColor current output. They may be assigned any member of the
ConsoleColor enumeration.
BufferHeight These properties control the height/width of the console’s buffer
BufferWidth area.
Clear() This method clears the buffer and console display area.
Title This property sets the title of the current console.
WindowHeight These properties control the dimensions of the console in relation
WindowWidth to the established buffer.
WindowTop
WindowLeft
To illustrate the working of Console class methods, consider the following example –
Program 3.6
using System;
class BasicIO
{
public static void Main()
{
Array Manipulation in C#
• C# arrays look like that of C/C++.
• But basically, they are derived from the base class viz. System.Array.
• Array is a collection of data elements of same type, which are accessed using numerical index.
Normally, in C#, the array index starts with 0.
• But it is possible to have an array with arbitrary lower bound using the static method CreateInstance()
of System.Array.
• Arrays can be single or multi-dimensional. The declaration of array would look like –
In .NET, the members of array are automatically set to their respective default value. For example, in the
statement, int[ ] a= new int[10];
all the elements of a are set to 0. Similarly, string array elements are set to null and so on.
using System;
class Test
{
public static void disp(int[] arr) //taking array as parameter
{
for(int i=0;i<arr.Length;i++)
Console.WriteLine("{0} ", arr[i]);
1. Rectangular array:
The rectangular array is an array of multiple dimensions and each row is of same length. For example
–
Program 3.32
using System; class
Test
}
}
using System;
class J aggedArray
{
Member Meaning
BinarySearch() This static method searches a (previously sorted) array for a given item.
If the array is composed of user-defined data types, the type in question must
implement the IComparer interface to engage in a binary search.
Clear() This static method sets a range of elements in the array to empty values (0 for
value types; null for reference types).
CopyTo() This method is used to copy elements from the source array into the destination
array.
Length This read-only property is used to determine the number of elements in an array.
Rank This property returns the number of dimensions of the current array.
Sort() This method sorts a one-dimensional array of intrinsic types. If the elements in
the array implement the IComparer interface, we can also sort an array of
userdefined data type .
Test
{
public static void Main()
{
int[] arr=new int[5]{12, 0, 45, 32, 67};
i=0;i<arr.Length;i++)
Console.WriteLine("{0} \t", arr[i]);
Array.Reverse(arr);
Array.Clear(arr, 1, 3);
Contains() This method is used to determine if the current string object contains a
specified string.
Concat() This static method of the String class returns a new string that is composed of
two
discrete strings.
Format() This static method is used to format a string literal using other primitives (i.e., numerical
data and other strings) and the {0} notation examined earlier in this chapter.
Insert() This method is used to receive a copy of the current string that contains newly inserted
string data.
PadLeft() These methods return copies of the current string that has been padded with specific
PadRight() data.
Remove() Use these methods to receive a copy of a string, with modifications (characters
Replace() removed or replaced).
Substring() This method returns a string that represents a substring of the current string.
ToCharArray() This method returns a character array representing the current string.
Program 3.35
Test
{
public static void Main()
if(s1==s2)
Console.WriteLine("Same strings");
else
Console.WriteLine("Different strings"); string
s3=s1+s2;
for(int i=0;i<s1.Length;i++)
Console.WriteLine(s1.Replace('a',' '));
}
}
This is string
Encapsulation services:
C# Encapsulation:
• Specification of the accessibility of each of the members of a class to the code outside the class
It is good programming practice to make all the data members or fields of a class as private. This kind of
programming is known as black box programming.
In this example, using the public methods, we could able access private data.
}
class Test
{
public static void Main()
{
Emp p=new Emp();
p.EmpName="Ramu";
Console.WriteLine("{0}",p.EmpNam);
}
}
A C# property is composed using a get block (accessor) and set block (mutator). The value keyword
represents the right-hand side of the assignment. Though, value is an object, the underlying type of the
object depends on which kind of data it represents. For example, in the previous program, the property
EmpName is operating on a private string, which maps to System.String. Unlike traditional accessors and
mutators, the properties make our types easier to manipulate.
Properties are able to respond to the intrinsic operators in C#. For example,
int Sal;
}
}
}
class Test
{
public static void Main()
{
Emp p=new Emp();
p.Salary=12000; p.Salary++;
Console.Wr iteLine("{0}",p.Sa
lary);
//12001 p.Salary
-=400;
Console.WriteLine("{0}",p.Salary)
//11601
}
}
class Emp
{
string SSN, name; int EmpID;
class Emp
{
static string CompanyName;
When we establish is-a relationship between classes, we are building a dependency between types. The
basic idea of classical inheritance is that new classes may influence and extend the functionality of other
classes. The hierarchy may look something like –
Employee
Manager
SalesMan
Now we can say that, Manager is-a Employee and SalesMan is-a Employee.
In classical inheritance, the base classes are used to define general characteristics that are common to all
derived classes. The derived classes extend this general functionality while adding more specific behaviors
to the class.
Consider an example –
class Test
{
public static void Main()
}
}
}
}
class Test
{
}
}
SalesMan
Part-time SalesMan
Here, a class called Part-time SalesMan is derived from SalesMan class which in-turn is derived from
Employee class as shown in the diagram. Now, we don’t want any more classes to be derived from Part-time
SalesMan class. To prevent such inheritance, C# provides a keyword sealed. The usage is depicted hereunder:
Now any attempt made to derive a class from Part_TimeSalesMan class will generate an error:
public class Test: Part_TimeSalesMan //compile -time error!!!
{
…………..
}
class Radio
{
public void TurnOn(bool on)
{ if(on)
Console.WriteLine(“Radio is on”); Console.WriteLine(“Radio is
else
off”);
}
}
class Car
{
int CurrSpeed, MaxSpeed; string
name;
bool carIsDead=false;
{
CurrSpeed+=a;
}
}
}
Now, we have two classes viz. Radio and Car. But, we can not say, “Car is a Radio” or “Radio is a Car”. Rather,
we can say, “Car has a Radio”. Now, the Car is called containing Class and Radio is called contained class.
class Car
{ ………..
private Radio rd=new Radio();
}
To expose the functionality of the inner class to the outside world requires delegation. Delegation is the act
of adding members to the containing class that make use of the functionality of contained class.
class Car
{ ……….
public void Tune(bool s)
{
rd.TurnOn(s); //delegate request to inner object
}
}
Thus by making one class to be a member of other class, we can establish has-a relationship. But it is always
the job of outer class to define a member function which activates the inner class objects.
Assume we have a base class Employee and two derived classes Manager and SalesMan.
class Employee
{
…….
public void Bonus(float b)
{ basicSal+=b;
}
}
class Manager:Employee
{
………..
}
class SalesMan: Employee
{
…………
}
Now, the classes Manager and SalesMan both contains the method Bonus(float). Thus in the Main() function,
we can call Bonus() through the objects of Manger and SalesMan –
Obviously, the Bonus() method works same for both the objects. But in reality, the bonus for a SalesMan
should be calculated based on number of sales. Manager can be given bonus based on his other performance
The polymorphic technique of C# provides solution for this problem. With the help of virtual and override
keywords, we can make same function to behave differently in base-class and all the derived classes. For
example,
class Employee
{
class SalesMan:Employee
{
if(numOfSales<=100)
salesBonus=10; elseif
(numOfSales<=200)
salesBonus=20;
class Test
{
public static void Main()
{
Employee e=new Employee() ;
e.Bonus(100); //base class Bonus() is called
We can see that when the Bonus() method is invoked through base class object, the corresponding method
will be called. Whereas, when Bonus() is invoked with the object s of derived class, the overridden method
Bonus() will be called.
NOTE that any overridden method is free to call its corresponding base class method using the keyword
base. Thus, the overridden method can have its own statements and also can make use of the behaviors of
base class virtual method also.
Thus, abstract class is a class which just declares members (data and method) and no object can be created
for this class. The member methods of abstract class may be used by the objects of derived class either
directly or by overriding them in the derived class.
An abstract class can define any number of abstract methods, which will not supply any default
implementation. Abstract method is equivalent to pure virtual functions of C++. The abstract methods can
be used whenever we wish to define a method that does not supply a default implementation. To understand
the need for abstract methods, consider the following situation:
Shape
Draw()
Hexagon
Circle Draw()
Here, each derived class like Hexagon and Circle of Shape has to override Draw() method to
indicate the methodology of drawing itself. If any derived class forgets to override Draw() method, the code
may look like –
In this example, the Circle class is not overriding the Draw() method. So, when the Draw() method is invoked
through the object of Circle class, the Draw() method of Shape class itself will be called. Obviously, the Draw()
method of Shape class will not be having any information about how to draw a circle and hence it will be
meaningless. This shows that virtual methods of base class need not be overridden by derived classes.
When programmer must be forced to override Draw() method, the method of base class must be made
abstract –
Thus, by making a base class method as abstract, we are making use of run-time polymorphism or late
binding. That is, the binding between the object and the method to be invoked is decided only at runtime.
This concept is more clear when we re-design our Main() function in the following format:
}
This may seems to be quite interesting. Till now, we have heard that we can not create objects for abstract
classes. But in the above code snippet, we are creating array of objects of base-classes. How? This is very
obvious as array of objects stores references to variables but not the objects directly. Thus, in the above
example, s[0] stores reference to the object of type Circle and s[1] stores reference to the object of type
Hexagon.
The major difference comes in case of multiple inheritance. We know that we can not derive a class from
more than one base-class in C#. That is multiple inheritance is not possible. But, we may have a situation
where there is more than one base class and we need to derive a class from all those base classes and then
override the virtual methods present in all the base classes. In such a situation, instead of writing abstract
base classes, we should write interfaces. Because, a class can be derived from one base class and it can
implement many number of interfaces.