Sei sulla pagina 1di 84

Learn

C#
Get the gist of the concept Write the program See the output for yourself

The do-it-yourself way yourself

Quasar S. Chunawalla

1|Page

Learn C# - do it yourself way...

2008

For all students pursuing the Computer Science Stream

These notes were compiled by me, while serving NIIT Training Institute, Mumbai India as a faculty member. This text would facilitate the learning process of the students when they learn an Object-Oriented Programming language like C#. It starts from scratch and takes you upto the depth required at an undergraduate school. I appreciate the contribution made by my students Farzan, Mario, Swapnil, Geetashree, Swati, Pooja, Shraddha, Chaitali, Snehal, Sushil, Anand, Sadiq, Rama, Tausif, Ameya and all other students and colleagues.
2|Page

Learn C# - do it yourself way...

2008
Contents

Chapter 1 2 3 4 5 6 7 8 9 10 11 12

Name Introduction to C# C# Fundamentals Decision Making and Looping Constructs Classes, Objects and Methods Collections in C# Polymorphism, Constructors and Destructors Inheritance Our objects family tree Advanced C# Language Concepts File Input and Output Threads, Processes, AppDomains and Multi-threading Exception Handling Assembly and Reflections

Pages 1 11

3|Page

Learn C# - do it yourself way...

2008

4|Page

1
Introduction to C#
Objectives
To type a simple program in C#, and acquaint yourself with editing, compiling and running your program. d How the HelloWorld program works... Hey, Object Oriented Programming the other day I heard these words from geek next door. Familiarize yourself with the concept of Objects and Classes. Have a dim and faint idea of Object Oriented features like Abstraction, Encapsulation, Polymorphism and Inheritance

This chapter serves as a preliminary introduction to students who are new to C# paradigm. In C#, you can create two kinds of applications f Console Based Applications and Windows Applications Throughout Applications. the first half of this book, you will learn how to create a Console Application. Console Applications accept input and display output in . the form text. In console programs, generally, you will use the generally, Console window to give inputs and see the output. Windows Applications usually have a user interface(GUI) through which you user-interface(GUI) give inputs and see outputs.

1|Page

Learn C# - do it yourself way...

2008

In MS Windows 95/98, the console is called MS-DOS Prompt. In Windows XP, Vista, it is called the Command Prompt.

1.1 Simple Program to print text on the Screen


Program that prints Hello World text on screen 1 using System; 2 3 class Greeting 4 { 5 public static void Main(string[] args) 6 { 7 Console.WriteLine("Hello World"); 8 } 9 }

You begin by punching in the above program in any text editor like notepad on Microsoft Windows. You save the file in a convenient location, say C:\ drive. Lets save the file as Greetings.cs.

Once you are done with that, well go to Start => All Programs => Microsoft Visual Studio 2008 => Visual Studio Tools => Visual Studio 2008 Command Prompt. In the Command Prompt, navigate to the location, where you stored your Greetings.cs file. Once you reach there, To compile the program, type csc Greetings.cs To run the program, type Greetings
2|Page

Learn C# - do it yourself way...

2008

1.2 Dissecting the Hello World Program


1 using System;

Line 1 of the program reads using System. This is called a using Directive. It says that this program borrows some features from the System namespace. In C#, a namespace is a way to group related features together. A namespace contains some ready-made code, that is available at your disposal. You can refer to it and use it in your program, rather than re-writing it. You dont have to re-invent the wheel everytime. Hold that for a moment now, I will explain it to you at length further ahead. Line 2 of the program is a blank line. Programmers often use spaces and blank lines to separate different sections of code, just as we leave space between two paragraphs in the English language. 1.1 Good Programming Practice
You must use whitespaces, blank lines to make the program readable, so that others can easily comprehend it.
3 class Greeting

Lines 3-9 of the program consists of our first class. The dictionary meaning of the English word class is the category in which things fall. A number of things often share some common features and operations. For example, all color TV objects have features like volume, brightness, contrast, color and have operations such as increase/decrease volume, increase/decrease brightness, increase/decrease contrast etc. All such objects would fall in the
3|Page

Learn C# - do it yourself way...

2008

colorTV class. In this program, weve taken a class Greeting. To specify that Greeting is a class, we write the class keyword before it. Keywords are word that have special meaning in the C# system. Thus, class keyword tells the computer that Greeting is a class. Line 4 is an opening curly brace {. The curly brace indicates the st . start of the class. When the class ends, we have to close the class by putting the corresponding } closing curly brace. The matter enclosed in the curly braces is called the class body. In C#, when you write a . new class, you will always pack the body of the class inside a pair of curly braces{...}. 1.1 Common Programming Error
The number of opening curly braces must equal the number of closing curly braces. Many Many-atimes, naive programmers start a curly brace, but forget to close it.

1.2 Good Programming P Practice


When typing a left opening brace {, it is always better to type the right closing brace }, right , away on the spur of the moment. You can then re position your cursor between the two re-position braces and start typing. This helps to prevent missing braces.

public static void Main(string[] args)

Line 5 is present in all C# programs. The word Main() indicates this programs. is the start of the program. This is where the C# system start starts executing(running) the program. Thus, Main() is the entry point(starting point) of any program. All statements written inside Main() are executed one by one, one line and the next line and so on. The Main() block is started using a starting curly brace { and terminated using an ending curly brace }. Whatever you want to write . inside Main() must be enclosed within this pair of curly braces. Main() is called a method/operation. Every method has a method/operation. parenthesis (). Main is the name of the method. The contents written inside Main() block is called method body.

4|Page

Learn C# - do it yourself way...

2008

1.3 Good Programming Practice


The entire body of the class Greeting, that includes the Main() method is at the first level of indentation. Indentation makes your program tidy and readable.

In the above program, we have written just one command/statement Console.WriteLine().This command is used display text on the VDU This screen. Whatever you put inside Console.WriteLine() in the double quotes gets printed on the screen, when you run the program. In this case, it is Hello World. At the end of the statement, there is a sem semi-colon. Just as every English sentence ends with a full stop, every statement in C# ends full-stop, with a semi-colon;. 1.2 Common Programming Error
Forgetting to put the delimiter ; after every statement is a committed quite often. As a rule, every C# statement must end with a semi colon. If you miss out any, your program will not semi-colon. compile successfully. The C Sharp Compiler csc will prompt you about the point, where it expects a semi-colon.

1.3 Common Programming Error


C# is a case-sensitive language. Hence writing class as Class is an error. All keywords like sensitive writing using, class, public, static, void, string are always in lowercase. The name of class, methods methods, and namespace should always begin with a capital letter like Greeting, System, Main, WriteLine. In case of a multi-word name like WriteLine, each letter of successive words like word Write and Line must be capitalized.

1.4 Good Programming Practice


The program written above is shown in an indented fashion. Although it is not necessary to give indents, it is a clean and neat way of writing a program. Giving indentation or tabs, also n gives an insight into which block the statement belongs to inner block or outer block. And the icing on the cake is, you can make sure that you have closed all the curly braces and , nothing is amiss. Indents enhance the readability of the program.

5|Page

Learn C# - do it yourself way...

2008

1.3 What is Object Oriented Programming (OOPS)?


C# is an Object-Oriented Programming Language. In early days of programming, programs were designed using flowcharts and a sort of top-down design. With this type of design, a large problem was solved step-by-step. Thus, the solution to a problem was visualised as a series of steps or operations. To arrive at the solution, you follow the sequence of steps or procedure. This form of programming is called Procedural Programming. Programming languages such as C, Pascal, Basic, Fortran follow this approach. However, as problems grew large and complex, even the procedural programming approach gave way. It was not strong and robust enough to analyse large and complicated problems. The new approach to programming is Object-Oriented Programming. Object Oriented Programming (OOPs) helps us to better model real world entities in the problem domain. In Object-Oriented Programming, to find the solution, we decompose a large problem in terms of objects. Object Oriented programming languages are Simula, Java, Smalltalk, C++, C# and many more.

1.4 What is an Object?


So, what really are objects? Any real world entity or thing, say for example a car, a person, a flight, a ticket-booking, an employee, a college can be an object in C#. To model real world things, in C# we create objects. Just like in the real world, each object has some features or characteristics that describe the object, our C# objects also have features that describe the object. For example, every car has some
6|Page

Learn C# - do it yourself way...

2008

name, brand, year of manufacture, price, color which describe it. In C#, to model this concept, C# car object will also have attributes name, brand, yearOfManufacture, price, color etc. For example, my car might have the name Maruti, brand as Swift, yearOfManufacture as 2008, price as 3.5 Lac, color as Blue. An object primarily contains two things data in the form of attributes and methods things that operate on this data. We now know what attributes mean. What are methods? Well, in Object-Oriented Programming, we often like to change the values of the attributes. For example, 3 years down the lane, you would like to refurbish your car with a fresh new paint, make it waterrepellant using a good old teflon coating. Also, as years pass by the price of your car changes due to depreciation. The true price of your car is the depreciated value. Thus, we often need to change the attributes(data) inside the object. There are two ways to do this. First is, we go in and modify each value directly. However, this is not a good practice in Object Oriented Programming. It is not a good practice to modify/access the attributes of an object directly. Instead, we access the attributes/data of an object through the methods in an object. Anything we would like to do, on an objects data, we must do it through the methods. Methods act as an interface between the object (its data) and the outside world user.
To model real-world things or entities, in C# we create Objects. Capsule of Data(Attributes) and Methods(Operations on Data) is an Object. Attributes are the characteristics of features that describe the object. Methods are used to manipulate the data/attributes of an Object. Not a good practice to access the attributes of an object directly. Do it through methods. Methods act as a broker, they have the license to access the attributes.

7|Page

Learn C# - do it yourself way...

2008

1.5 What are Classes?


A class acts a blue-print, design or a layout for an object. When an print, architect wants to build houses, he does not directly build the house haphazardly. Instead, he first creates a basic plan or design. It could be an architectural drawing showing, what the houses w look like, will how much carpet area they will have, dimensions, color etc. He then uses this design or plan as a blue print or basis for constructing the blue-print actual houses.

On the same lines, in C#, we first create a design or a plan called Class. Using this class/plan as a blue print or base, we construct s blue-print actual objects. The class/plan tells us how the objects are going to look like.. A class must specify what attributes and methods will be there in an object. For example, before creating the different car objects, we must car specify in the plan(class), what attributes and methods every car object would have. We then construct Car objects, by assigning values to each of the Cars attributes.

8|Page

Learn C# - do it yourself way...

2008

Thus, in C#, we must create a class(plan) and then use it a guideline(blue-print) to create objects. You cannot create objects without a class. Also, merely defining a class is not enough. To be able to use it, we must create objects of the class. Just as having a drawing on paper is just a plan. To materialise this plan, we must utilize it to construct a building.

1.6 Abstraction
Abstraction is the process of stripping down an onion, peeling off all the inessential layers, until you are left with the bare minimum essentialities, the kernel or core. Abstraction steers clear of all unimportant details and allows you to pay more emphasis on the important details. Abstraction is an important software design principle. A good class always exposes a minimal set of functionalities that allow you to manipulate the objects in an easy-to-use fashion. Let me cite to you an example of abstraction which you might already know. To transfer a file from your desktop PC to a USB flash drive, you would have to specify, where from to lift the file on the hard-disk, the track, the sector, the cluster, how many bytes to transfer, the destination location etc. With the help of an Operating System like Microsoft Windows, we just have to copy the file and paste it where we would like to. What an Operating System does is, it frees us from all the unessential details of hardware. Thus, it provides a higher level abstraction, and hides all the unnecessary details. Why abstraction is so important? Computer applications or software are generally made of components or layers. As time progresses, new functionalities and features are added to them. When new layers are added, we would want that their impact on the older layers should be minimal. Minimal dependency is an absolute must. This is why abstraction is necessary.
9|Page

Learn C# - do it yourself way...

2008

1.7 Principle of Encapsulation


In procedural programs, there are lots of data and functions. All the functions have access to all the data. The functions and data are separated/segregated from each other. In simple programs, this idea works well. However, with complex programs, this approach breaks down. When we make changes to the data, as a consequence all the functions that access this data will break down and give wrong results. So, we need change all the affected functions. So, in Object-Oriented Programming, we put data and its related functions into a single module. This process is called Encapsulation.

1.8 Inheritance
In a family, a child inherits the features and traits of his parent, and parents inherit their features and characteristics from grand-parents. This way, certain features or attributes are passed on from generationto-generation. A similar tool is present in C# as well. An object can inherit attributes and methods from another object. The former is called the parent, and the latter is called the child. The child object has features and attributes of the parent. In addition to this, the child object can have some of its own features and attributes. Thus, a child is a specialised kind of a parent. They share a kind-of relationship.

1.9 Polymorphism
Poly means many, morphos means form. Polymorphism means one thing exhibiting many forms. In polymorphism, an object behaves differently in different situations. Depending upon the context and environment, it changes its behaviour.
10 | P a g e

Learn C# - do it yourself way...

2008

2
C# Fundamentals
Objectives
Learn how to store data in computer memory use variables and constants Rules to be followed while you assign a valid variable name Declaring Variables in C# Data-types in C# - They come in various sizes, and store different types of types data Assigning values to variables Learn with a simple program to store and retrieve values of variables Operators in C# Get your hands wet with learning how to use arithmetic operators wherever you want. Study a simple program that calculates the Simple Intere Interest

2.1 Variables and Constants


A computer takes data as input, performs operations on the input, and produces an output. We would like to store the input data and output results in computer memory, so that we can retrieve it for later purposes.
11 | P a g e

Learn C# - do it yourself way...

2008

Before you get to know, how this is done, lets take brief look at how Computer memory looks. Just like in a street, people live in houses, computer memory is organised as a series of cells. The cells do not house people, instead they house data. We can visualise the pic picture of computer memory like the one below :

Suppose we store the number 2 in some memory location. Next time, suppose, we would like to retrieve the contents of this cell. Then how to do that? How do we refer to this cell? The houses in a street have different names. In a similar fashion, what we do is, we give a name to the memory location, say a. And then, we can access the contents of this memory location using the name a. Next time, I simply have to say, Give me the contents of the memory location whose name is location a.. and Ill get the output = 2. Thus, one of the ways to access and manipulate the values(data) of a memory location is to give it a name. If the data stored in a memory location is allowed to change, for example if value in a can be changed to 3, such a memory location is called a Variable We use the Variable. word Variable, because, the contents of such a cell can vary vary. On the other hand, at times, we would like to contents of a cell to remain fixed or constant, not allowing it to change. For example, if a For
12 | P a g e

Learn C# - do it yourself way...

2008

stores 3.14 the value of Pi, we would like it to be fixed. Such a memory location is called Constant. The name given to a Variable is called a Variable name. The name given to a constant is called Constant Name. In a nutshell, variables and constants provide named access to memory location.

2.2 Rules for naming a Variable


Unlike babies, we dont have full liberty while naming a variable. A valid variable name must satisfy the following rules. 1. Name of a variable must begin with an alphabet[A-Z,a-z] or underscore_. 2. The successive characters of a variable can consist of alphabets[AZ][a-z], digits[0-9] or underscore sign _. 3. The name of variable must not be a reserved keyword (like int, char, float, double etc.)

2.3 Variables Declaration


The Operating System is a miser. The OS does not lend any bytes for free. Even if you want a single byte of memory, you must first ask the OS for it. Hence, the OS protects the computer memory. Its job is to act as a Memory manager. When you want some memory space to store data, you must first ask the operating system for it. If the OS grants your request, you can go ahead and store data in that memory location. You must tell the OS how much memory(in bytes) you need for doing your work(like storing data in variables). Once the OS agrees to your request, it reserves memory space for you. This memory space is then reserved for you, and no other program can access it.
13 | P a g e

Learn C# - do it yourself way...

2008

Telling the OS how many bytes of memory you need is called Declaration. While making this declaration/announcement you must specify two important things 1. How many bytes of memory you would need to store your data? 2. What name you would give to this newly reserved memory location, so that you can refer to it, the next time round by this name. As far as the former is concerned, the bytes of memory you would need to store the data really depends on the type of data that you are going to store. A number like 3.14159 needs more memory that just a 3. What type of data you intend to store, can be indicated by specifying the data-type.

2.4 Data-types in C#
Some of the primitive data-types in C# are shown in the table. bool is used to store boolean values just two possibilities 0 or 1 that is true or false. char is used to store single characters like A, B, C, ..., a, b, c,.., 1,2,.. and also, , $, _ and all the letters you would find on the keyboard that have an ASCII value. In C#, char stores the data in Unicode Text Format(UTF). To store integers or numbers without a decimal point, we have four data-types available byte, short, int, long. byte as the name suggests is 1 byte long. So, it can store numbers from 0 to 255. But, what if we wanted to store a larger number like 256. We would then require more than 1 byte of memory space; 2 bytes. So, we use the short data-type. short data-type can store number ranging from -32,768 to +32,767. What if we want to store a still larger number like 50,000? We can then use the int data type(4 bytes) which allows us to store numbers upto 2 billion. If we would like to store a number like a googol, (which is one followed by 100 zeroes), what do you do? You can use a data-type long 8 bytes. To store decimal(real) numbers like 2.5, -3.821 etc. we can use the float and double data-types.
14 | P a g e

Learn C# - do it yourself way...

2008

Data-type Storage Space Bool 2 bytes Char 1byte Byte 2 bytes Short 4 bytes Int Long Float Double Decimal 8 bytes 4 bytes 8 bytes 8 bytes

Range of Values true,false \u0000 to \uFFFF 0 to 255 -32,768 to +32,767 -2,147,483,648 to +2,147,483,647 -9.22e18 to +9.22e18

Example bool b = true; char ch = A; byte b = 10; short s = 1000; int i = 500; long l = 1000; float f = 3.14F; double d = 25.583

Apart from these, we have sbyte(signed-byte), ushort(unsigned short), uint(unsigned int) and ulong(unsigned long).

2.5 Filling values in a variable


We first declare the variables we want. To declare a variable, we use the following syntax : <data-type> <variable-name>; int myVariable; In the above example, we declared a variable having data-type int(4 bytes) and we named the variable myVariable. To begin with, myVariable is right now empty. In other word, myVariable contains 0. To use myVariable, we must put meaningful data in it. Lets store the number 5 in the integer variable called myVariable. myVariable = 5; Thus, it is a two-step process :

15 | P a g e

Learn C# - do it yourself way...

2008

Declare a variable with the desired data data-type(depending on what data you would like to store)

Assign value to the variable, by using =(equal to) sign.

2.6 Code Snippet How to store and retrieve values from variable
Heres a simple program that illustrates how to declare a variable, assign values to it, and later retrieve the contents of the var variable.
Program that stores and displays the value in a variable 1 using System; 2 3 class VariablesDemo 4 { 5 public static void Main() 6 { 7 /*Declare a bool variable*/ 8 bool b; 9 /*Store a value in it*/ 10 11 b = true; 12 13 /*Display the value in b*/ 14 Console.WriteLine("b = {0}", b); Console.WriteLine( 15 16 /*Declare a character variable*/ 17 char c; 18 19 /*Store a single character in it*/ 20 c = 'M'; 21 /*Display the character stored in c*/ y 22 23 Console.WriteLine("c = {0}", c); Console.WriteLine( 24 25 /*Declare an integer variable*/ 26 int i; 27 28 /*Store an integer number in it*/ 29 i = 10;

16 | P a g e

Learn C# - do it yourself way...


30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 }

2008

/*Display the integer value stored in the variable*/ Console.WriteLine("i = {0}", i); /*Declare a float variable*/ float f; /*Store a real number in it*/ f = -0.0125f; /*Display the value of f*/ Console.WriteLine("f = {0}", f); /*Declare a double variable*/ double d; /*Store a large real number in it*/ d = 254.1459; /*Display the value of d*/ Console.WriteLine("d = {0}", d); }

Upon running this program, we get the following output

You need to understand, how Console.WriteLine() function works. WriteLine() function is used to display text on the console (command prompt). Whatever is given to WriteLine() in double quotes --- is displayed on the command prompt. The second aspect is the use of placeholders. Notice that weve put {0}s in the WriteLine() function in the above program. {0} is called a place-holder. How it works?
int a = 2, b = 3, c = 4; Console.WriteLine("a = {0},b = {1}, c = {2}", a, b, c);

17 | P a g e

Learn C# - do it yourself way...

2008

Assume that we take three integer variables a,b and c. Weve put the values 2,3 and 4 in the variables a, b and c respectively. To display their values, we use the WriteLine() function. In the Write WriteLine(), we give a,b and c as arguments without the double quotes. This means . that we want to display the contents of a,b and c. So, the values 2,3 and 4 will be displayed. {0} gets substituted by the value of a 2, {1} by the value of b 3, and the placeholder {2} by the value of the placeholder variable c 4. Output of the above code snippet :

2.6 Operators
In our school and pre-school, we have studied math. Operations like school, adding, subtracting, multiplying, dividing are pretty common. Like in algebra, we have many different operators in C#. ave Class of Operators Binary Arithmetic Operators Unary Arithmetic Operators Logical Operators Relational Operators Bitwise Logical Operators Shift Operators Assignment Operators

+, - ,*,/,% + , - , ++ , -&&, || , ! , ^ <,<=,>,>=,==,!= &,|,~ <<, >> = Shorthand Assignment +=, -= , *= , /= , %= , &=, |= , ^=, <<= , >>=

18 | P a g e

Learn C# - do it yourself way...

2008

2.7 Binary Arithmetic Operators


Binary operators are the ones which operate on two operands. Binary Arithmetic operators are plus +, minus - , multiplication *,division / , and Modulo %. Just as we write expressions in algebra, we can form arithmetic expressions in C#. Lets begin with a few simple examples.
int a = 5, b = 10; int res; res = a + b; Console.WriteLine(" a + b = {0}", res);

The result of adding a + b, should be 5+10 = 15. So, res contains the value 15. Similarly,
res = b - a; Console.WriteLine("b - a = {0}", res);

To subtract b a and store the result in res, we write the above lines. The effect of this statement would be, 10-5 = 5, and hence res = 5.
res = a * b; //res = 5*10 = 50 Console.WriteLine("a * b = {0}", res); res = b / a; //res = 10/5 = 2 Console.WriteLine("b / a = {0}", res);

Thus, we could write any complex instruction like res = a + b * c d / e. Lets write a simple program that calculates the simple interest.
Program to calculate Simple Interest 01 using System; 02 03 class SimpleInterestDemo 04 { 05 public static void Main()

19 | P a g e

Learn C# - do it yourself way...


06 07 08 09 10 11 12 13 14 } { int principal = 10000; int noOfYears = 5; int rateOfInterest = 10;

2008

int SimpleInterest = (principal*noOfYears*rateOfInterest)/ 100; Console.WriteLine("Simple Interest = {0}", SimpleInterest); }

This simple program takes three variables principal, noOfYears, and rateOfInterest, and computes the simple interest by using the formula PNR/100. Upon running the program, we get the following output.

When we divide two numbers, the divide operator / is used to find the answer(quotient) of division. For example, when we divide 11 by 3, we get quotient 1 and remainder 2. Thus, 11/3 = 1(quotient) and 11 modulo 3 = 2(remainder). Modulo operator is used to find the remainder of the division operation.
Program that shows the use of % operator 01 02 03 04 05 06 07 08 09 10 11 12 13 using System; class ModuloDemo { public static void Main() { int a = 11; int b = 3; int remainder = a % b; Console.WriteLine(" 11 % 3 = {0}", remainder); } }

Upon running the program, we get the following output.

20 | P a g e

Learn C# - do it yourself way...

2008

Lets study a simple program, that uses the modulo operator % to reverse a four-digit number. For example, if the input number is 1234, the output should be the number 4321.
Program to reverse a 4-digit number 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 using System; class ReverseDemo { public static void Main() { int number = 1234; int int int int u = number % 10; t = (number / 10) % 10; h = (number / 100) % 10; th = (number / 1000) % 10;

int reverse = u * 1000 + t * 100 + h * 10 + th; Console.WriteLine("Original = {0}", number); Console.WriteLine("Reverse = {0}", reverse); } }

The line 5 in the Main() program declares a variable called number, and we store in it the value 1234. To calculate the reverse of a number, the algorithm is as follows a. Input number n b. Extract various digits of the number n. c. Form the reverse number as (Units-digit x 1000) + (Tens-digit x 100) + (Hundreds-digit x 10) + (Thousands-digit x 1) So, we must extract the various digits from one thousand, two hundred and thirty four as 1, 2, 3 and 4. We then form the reverse of this number as 4 x1000 + 3 x 100 + 2 x 10 + 1 x = 4321. Line 14 in the program corresponds to this step.
21 | P a g e

Learn C# - do it yourself way...

2008

Lines 9 12 are used to extract out the individual digits from the 4digit number. How do you that? Well, it seems weird at first sight. But, here goes. You divide a number like 1234 by 10, and find the remainder. In that case, 1234 modulo 10 = 4. (as 1230 is perfectly divisible by 10; 1234 is 1230 + 4 left over) Thus, number % 10 gives the units digit. Now, to extract the tens digit, we would use the same technique number % 10. However, to extract 3 from 1234, we first divide 1234 by 10. 1234 / 10 = 123 (Truncating 123.4 to 123...) Now, this number 123 % 10 = 3. Thus, we pulled out the tens digit. To pull out hundreds digit(2), 1234 / 100 = 12 12 % 10 = 2. To pull out thousands digit(1), 1234 / 1000 = 1 1 % 10 = 1. Upon running the above program, I get the following output.

2.9 Precedence and Associativity of Arithmetic Operators


When an arithmetic expression is evaluated in C#, there is an ambiguity in how the result of the expression is calculated. For example, the statement :
22 | P a g e

Learn C# - do it yourself way...

2008

result = 2 * 3 + 4; It may be evaluated as result = 2 * 3 + 4 =6+4 = 10 result = 2 * 3 + 4 =2*7 = 14 To resolve the ambiguity, C# assigns a priority to all the operators. (This does not only apply to arithmetic operators, but all kinds operators, however in this book, our discussion is restricted to arithmetic operators) Operators with higher priority are evaluated first and are preferred over operators of lower priority. The priorities of different operators is shown in the table below. This is also called precedence of operators. Priority 1st Priority 2nd Priority 3rd Priority Thus, in the expression result = 2 * 3 + 4 We first evaluate Multiplication *, because it has the highest priority. So, result = 6 + 4 Operators */% += Description Multiplication, Division, Modulo Addition, Subtraction Assignment

23 | P a g e

Learn C# - do it yourself way...

2008

Next, we evaluate addition +, because + has higher priority over =, and hence + operator precedes over =. result = 10. Lastly, we evaluate the = equals operator. In other words, the value 10 is now stored in the variable result. Now, consider the following expression result = 5 * 4 / 2 ; In this case, * and / have the same priority level. When two operators have the same priority, which operator should be evaluated first? The answer to this question lies in a concept called associativity. Associativity indicated the direction in which the expression is scanned to evaluate the operators. The associativity of arithmetic operators is given in the table below Operators +-*/% = In the expression, result = 5 * 4 / 2 ; Since, = equals operator has R to L associativity, we will first evaluate the right hand side(RHS) and then assign the result to the LHS. The RHS is 5 * 4 / 2. Since, * and / have the same priority, we shall have to consider their associativity. Both * and / have L to R associativity, we start scanning the expression in left to right direction and evaluate the answer. In left to right order, we first encounter *, so 5 * 4 = 20. Associativity Left to Right Associativity Right to Left Associaitivity

24 | P a g e

Learn C# - do it yourself way...

2008

Then we encounter /. So we evaluate it as, RHS = 5 * 4 / 2 = 20 / 2 = 10. Finally, the result of the expression on the RHS is assigned to the variable result on the LHS. Thus, the value 10 is stored in result.

2.10 The arithmetic expression a = a + b


You are familiar with most of the algebraic expressions like : = + = 3.14 = = + 2 + + + + 4 8 /

They all have, some algebraic variables on the RHS, whose result of computation is the LHS. But, you may not see in algebra, an expression like : = +1 =2 = + This might be absurd in terms of algebraic expression, but they are perfectly valid C# arithmetic expressions. In C#, you can have the same variables on the left hand side and right hand side of an arithmetic expression. How to decipher the meaning of the above expression? In an arithmetic expression, as a rule, we always first evaluate the RHS, and the result of the expression on the RHS is assigned to the LHS. Consider = + 1. Initially, suppose the variable a contains 2. 1 + 1 = 2 + 1 = 3.
25 | P a g e

Learn C# - do it yourself way...

2008

This value 3 is now stored back in the variable a(LHS). Note that, one variable can contain hold one value at a time. So, the old value 2 is lost and it is over-written with the value 3. Thus, this expression increases the value of a by 1. In other word, it increments the value of 1. Similarly, if we would like to decrease the value of a by 1, we would have to write = 1. The expression = 2 doubles the value of a and stores the result in a. For example, to begin with if a = 5, after this statement executes a will hold the value 10.

2.11 Unary Arithmetic Operators


Unary operators are the ones that operate only one operand at a time. The different arithmetic unary operators are unary plus +, unary minus -, increment ++ and decrement -- operators. Unary plus and minus are easy to understand. If a = 2, if we write a = +a ; a would hold the answer 2. a = -a ; a would hold the answer -2. Unary plus really has no meaning. It is there only for the purpose of symmetry. The increment operator ++ is a shortcut way to increase the value of a variable by 1. In other words, = + 1 can be simply written as + +. Similarly, to decrement the value of a by 1, we simply write . Given below is simple program that illustrates how increment ++ and decrement -- operators work.

26 | P a g e

Learn C# - do it yourself way...


Program to show the working of ++ and -- operator 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 using System; class IncrementDecrementDemo { public static void Main() { int a = 2; Console.WriteLine("Initially a = {0}", a); //Increment the value of a a++; Console.WriteLine("After incrementing a = {0}", a); //Increment the value of a a++; Console.WriteLine("After incrementing a = {0}", a); //Decrement the value of a a--; Console.WriteLine("After decrementing a = {0}", a); //Decrement the value of a a--; Console.WriteLine("After decrementing a = {0}", a); } }

2008

This program takes a variable called a. The variable a is initialised to 2. We increment the value of twice. We then decrement it twice. In each step, we print the result of increment/ decrement to the screen. The output appears as follows :

2.12 Relational(Comparision) Operators


Relational (comparision) operators are simple to use. They always return a bool true or false value. Relational operators operate on simple variables as well as they can operate on complex expressions. The different relational operators are < , > , <= , >= , == , != .
27 | P a g e

Learn C# - do it yourself way...

2008

Lets take simple examples and try to understand the above operators. x = 10 x=8 x=-5 x = 4, y = 3 x=9 x=5 x>5 2*x < 20 -x >= 10 x + y <=9 x + 1 == 10 x!=5 true true false true true false

2.13 Logical Operators


Just as we have plenty of arithmetic operators, we have yet another important class of operators called Logical Operators. Logical operators are also called Conditional Operators. The various logical operators are Logical AND && , Logical OR || , Logical Exclusive OR ^ , Logical NOT ! . Logical operators are very useful in everyday situations. They can be used to combine two or more conditions. Say for example, we have a variable x initialised to 10. X 10 x >5 true x<15 True x>5 AND x<15 true since x lies in the range {5,15}.

The Logical AND operator returns a bool value true or false. If both the conditions(operands) are true, the answer is true. The logical AND operator in C# is written as &&. A true true false false B True false true false A && B true false false false

28 | P a g e

Learn C# - do it yourself way...

2008

The Logical OR operator returns a bool value true or false. Logical OR in C# is written as || (Two vertical bars). The logical OR || returns true even if any one of the condition holds true. A true true false false B True False True False A || B true true true false

The Logical XOR(Exclusive OR) operator also returns a bool value true or false. The logical XOR is a special case of the logical OR operator and is written in C# as ^. Logical XOR returns true only if the conditions(operands) are dissimilar. If they are similar, it returns false. A true true false false B True False True False A^B false true true false

Logical NOT ! operator negates or complements the condition. If the condition evaluates to true, !(condition) would be false. On the other hand, if the condition evaluates to false, !(condition) would be true. Given below is a program that shows how to work with all the logical operators.
Program to show the working of && , || , ^ and ! operators 01 using System; 02 03 class LogicalDemo 04 { 05 public static void Main() 06 { 07 int x = 10; 08 Console.WriteLine("x = {0}", x); 09 10 bool ans = (x > 5) && (x < 15); 11 Console.WriteLine("x > 5 && x < 15 = {0}", ans);

29 | P a g e

Learn C# - do it yourself way...


12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 }

2008

ans = (x > 5) && (x > 15); Console.WriteLine("x > 5 && x > 15 = {0}", ans); ans = (x > 5) || (x > 15); Console.WriteLine("x > 5 || x > 15 = {0}", ans); ans = (x == 5) || (x < 0); Console.WriteLine("x == 5 || x < 0 = {0}", ans); ans = (x == 5) ^ (x > 0); Console.WriteLine("x == 5 ^ x > 0 = {0}", ans); ans = (x == 10) ^ (x > 0); Console.WriteLine("x == 10 ^ x > 0 = {0}", ans); ans = !(x > 10); Console.WriteLine("!(x > 10) = {0}", ans); }

Lines 10 and 13 show the && operator. x = 10. So, x>5 = true (as 10 > 5). x < 15 = true (as 10<15) (x > 5) && (x < 15) = true && true = true On the other hand, x > 5 && x > 15 = true && false = false However, Line 16 shows the same two conditions with || operator. x > 5 || x > 15 = true || false = true Line 19 also uses the || operator. This time round, x == 5 is false, since x = 10, and 105. Also, x < 0 is false, since 10 > 0. Thus, x == 5 || x<0 = false || false = false. Lines 22 and 25 show how the exor ^ operator works. In case of line 22, x == 5 is false, x>0 is true and false ^ true = true. In case of line 25, x == 10 is true, x>0 is true and true ^ true = false. Line 27 shows the use of ! operator. Since x > 10 is false (as 10 10), !(x>10) must be true. Upon running the above program, we get the following output.
30 | P a g e

Learn C# - do it yourself way...

2008

2.14 Bitwise Logical Operators

31 | P a g e

Learn C# - do it yourself way...

2008

6
Polymorphism, Constructors and Destructors
6.1 Function Overloading
There are 6 different versions of the Multiply() method in the Test class. st The 1 version multiplies two ints and returns an int as the answer. nd The 2 version accepts 2 doubles as input parameters and returns a rd double result as the answer. The 3 version accepts an integer and a double number as an argument, and returns their product as the answer. Every time, we are assigning a new extra meaning to the Multiply() function. Thus, we have overloaded the Multiply() method.

class Test { public int Multiply(int a, int b) { return a * b; } public double Multiply(double a, double b) { return a * b; } public double Multiply(int a, double b) { return a * b; } public double Multiply(double a, int b) { return a * b; } public int Multiply(int a, int b, int c) { return a * b * c; } } class OverloadDemo { public static void Main() { Test t = new Test(); double res1 = t.Multiply(4.2, 5.5); int res2 = t.Multiply(3, 5); double res3 = t.Multiply(4.2, 5);

32 | P a g e

Learn C# - do it yourself way...


double res4 = t.Multiply(5, 3.8); int res5 = t.Multiply(3, 4, 5); }

2008

In method overloading, we assign a new extra meaning to the method. For example suppose, we have written the Multiply() method as follows : public int Multiply(int x, int y) { int result = x * y; return result; } The Multiply() method is designed to accept 2 integers as input parameters. It multiplies the two integers x and y, and returns an integer result as the answer. Suppose, we now define one more Multiply() method as follows public double Multiple(double x, double y) { double result = x * y; return result; } This Multiply() method multiplies two double numbers and returns a double result as the answer. Thus, the Multiply() method now has two different versions. The first version can multiply two integers, whereas the second version can multiply 2 doubles. Thus, we have assigned a new extra meaning to the Multiply() method, so that it can now no longer multiply just two ints, but it can as well multiply two doubles.Hence, we have overloaded the Multiply() method. Thus, this is method overloading. Let us define one more Multiply() method as follows 33 | P a g e

Learn C# - do it yourself way...

2008

public double Multiply(int x, double y){ double result; result = x * y; return result; } This time round, the Multiply() method can multiply one int with one double value, and returns a double result as the answer. Thus, we are again assigning a new extra meaning to the Multiply() method. So, once again we have overloaded the Multiply() function. If we define one more Multiply() method as : public double Multiply(double x, int y) { double result; result = x * y; return result; } This new version of the Multiply() method can now multiply a double with an integer. Mutiplying a double with an int, is different from multiplying an int with a double. Thus, we are again assigining a new meaning to the Multiply() method. Hence, we have again overloaded the Multiply() method. Consider another version of the Multiply method public int Multiply(int x, int y, int z){ return x * y * z; } This version of the Multiply() method computes the product of 3 ints instead of 2. Once again we have assigned extra meaning to Multiply(). So, it is an overloaded function. A function is said to be overloaded if 34 | P a g e

Learn C# - do it yourself way...

2008

1. When two or more methods in the same class have the same name 2. They have different Parameter Lists Parameter list is different if - Type of parameters differs. - No of parameters is different. - Order of parameters is different.

6.2 Operator Overloading


A Date class is used to represent the date in the form of days, months and years.

class Date { public int day; public int month; public int year; public static Date operator +(Date d1, Date d2) { Date result = new Date(); result.day = d1.day + d2.day; result.month = d1.month + d2.month; result.year = d1.year + d2.year; if(result.day>30){ result.day -= 30; result.month++; } if (result.month > 12) { result.month -= 12; result.year++; } return result; } public static bool operator <(Date d1, Date d2) { bool ans; int days1 = d1.day + d1.month * 30 + d1.year * 365; int days2 = d2.day + d2.month * 30 + d2.year * 365; if (days1 < days2) ans = true; else ans = false; return ans; } public static bool operator >(Date d1, Date d2)

The + operator is overloaded, so that it can add two Date class objects. The two Date objects are passed as arguments into d1 and d2. To store the sum of Date objects, we take a result Date object. We set the day, month and year of the result Date object as the sum of the corresponding day, month and year of d1 and d2.

We also need to check for overflow. Overflow happens when the no of resulting days exceeds 30. For example, we treat 35 days as 1 month and 5 days. So, when an overflow occurs we add 1 to the months, and the balance days are 35 30 = 5.

The < operator is overloaded, so that it can compare 2 Date objects and find out which is smaller. Comparing 2 Date objects for the no. Of days, months and years can be tricky, so a simple way would be to find the total no of days of each Date object and then just compare them. If days1 turns out to be less than days2 as assumed, return true else return false. We also overload > operator, since they must be overloaded in pairs.

35 | P a g e

Learn C# - do it yourself way...


{ bool ans; int days1 = d1.day + d1.month * 30 + d1.year * 365; int days2 = d2.day + d2.month * 30 + d2.year * 365; if (days1 > days2) ans = true; else ans = false; ; return ans; } public void GetDate() { Console.WriteLine( .WriteLine("Day : " + day); Console.WriteLine( .WriteLine("Month : " + month); Console.WriteLine( .WriteLine("Year : " + year); Console.WriteLine(); .WriteLine(); } } class DateDemo { public static void Main() { Date d1 = new Date Date(); Date d2 = new Date Date(); Date result; bool ans; d1.day = 2; d1.month = 7; d1.year = 5; d2.day = 29; d2.month = 6; d2.year = 4; result = d1 + d2; d1.GetDate(); d2.GetDate(); result.GetDate(); ans = (d1 > d2); Console.WriteLine( .WriteLine("d1 > d2 : " + ans); } }

2008

Suppose we write the instruction 2 + 3.

36 | P a g e

Learn C# - do it yourself way...

2008

When the C# system encounters this line, it does not directly add the 2 + 3. Instead, the C# system calls a function with the name + and passes 2 and 3 as the arguments. +(2,3) When this function is called, the control jumps to the function definition. The + function looks like this public int operator +(int a, int b) { ___________________; ___________________; ___________________; } Since, the computer gives us the answer of 2 + 3 = 5, this function + is already defined in C#. Now, suppose we would like to assign extra meaning to the + operator. Let's say we have the following objects MyClass obj1 = new MyClass(); MyClass obj2 = new MyClass(); Suppose, we now write obj1 + obj2 Thus, the following function is called +(obj1,obj2) But, since these our own objects, we have created them, we have made their class design, the + operator does not know how to add these custom made objects. To be able to add them, we need to define the following function -

37 | P a g e

Learn C# - do it yourself way...

2008

public MyClass operator + (MyClass obj1, MyClass obj2){ MyClass result; //Code for adding the 2 objects.. _______________________________; _______________________________; return result; } By defining this function, the + operator will also be able to add objects. Hence, we are assigning extra meaning to the + operator, so that it is able to add our own objects. Hence, it is called Operator Overloading. Syntax for Overloading Binary Arithmetic Operator public static MyClass operator + (MyClass obj1, MyClass obj2) { MyClass result; ______________ ______________ return result; } Syntax for Overloading Unary Arithmetic Operator public static MyClass operator -(MyClass obj) { MyClass result; ______________ ______________ return result; }

38 | P a g e

Learn C# - do it yourself way...

2008

Syntax for Overloading Relational Operators public static bool operator <(MyClass obj1, MyClass obj2){ bool ans; //Compare the two objects ______________ ______________ return ans; } Note : Relational operators are always overloaded in pairs. If we overload < operator, then we must also overload > operator. Similarly, if we overload <= or == operator, we must also overload their corresponding complementary operators >= and !=.

6.3 Constructors
class Box { double width; double height; double depth; public Box() { width = height = depth = 1; } public Box(int l) { width = height = depth = l; } public Box(int w, int h, int d) { width = w; height = h; depth = d; } public void GetBox() { Console.WriteLine("w : " + width + " h : " + height + " d : "+depth); }

39 | P a g e

Learn C# - do it yourself way...


public void Volume() { Console.WriteLine( .WriteLine("Volume : " + width * height * depth); } } class BoxDemo { public static void Main() { Box myBox1 = new Box(); Box myBox2 = new Box(5); Box myBox3 = new Box(10, 20, 30); myBox1.GetBox(); myBox2.GetBox(); myBox3.GetBox(); myBox1.Volume(); myBox2.Volume(); myBox3.Volume(); } }

2008

A constructor is a special method that is called automatically, when an object is created.

Why Constructors?
When we first create an object, all its fields are initialised to 0. In fields other words, the memory is zeroed out.

Box myBox; myBox = new Box();

To be able to use this Box object, we must put in meaningful values in the width, height and depth of myBox. Thus, we must assign values to myBoxs instance variables. ance To do so, we must manually go in and initialise all the fields of the myBox object.
40 | P a g e

Learn C# - do it yourself way...

2008

myBox.width = 10; myBox.height = 20; myBox.depth = 30; -rosy All of this seems rosy-rosy till we have to work with just 1 Box object. But, consider a real time shipping application, where we to real-time keep track of thousands of orders and consignments. Each consignment is shipped in Box object. So, if we typically have 1000 Box objects; myBox1, myBox2, myBox3,... this process of manually initialising all the fields becomes very tedious and cumbersome. fields

Well, you can use convenience methods like SetBox(). But, when you have a thousand objects, you have explicitly call/invoke SetBox() method on each Box object. Once again, it calls for a lot of work.

How can Constructors help me? onstructors

41 | P a g e

Learn C# - do it yourself way...

2008

Constructor is a special method that is invoked automatically, when an object is created. So, you dont have to call a constructor method explicitly. Thus, constructor can be used to automatically initialise an object, right at the time when the object is born/created. 1. A constructor has the same name as the class. 2. Like methods, constructors can also accept input parameters. 3. Unlike methods, constructors do not have a return type, not even void. 4. Like methods, constructors can also be overloaded. Depending upon the call, different versions of the constructor will be invoked. Note Adding constructors to a class is compulsory. Q. But, the classes that we have written till now seemed to work fine without a constructor. A. If you do not write your own constructor, the C# Compiler adds a constructor method for you for free. Such a constructor is called the default constructor. Q. But how does the default constructor know, what I want it to do? A. It does not! Thats why, it does not accept any parameters and has empty body. It looks like this public Box() { } Thus, the free constructor that C# compiler adds for you, is a donothing constructor.

42 | P a g e

Learn C# - do it yourself way...

2008

6.4 Destructors, Finalize() and Dispose()


We know that when, objects are created, constructors are called, but when objects are destroyed what happens? Unlike C C++, in C# you dont have to manually destroy objects. Objects which are no longer needed are automatically destroyed by the Garbage Collector(GC). In C#, you can have two kinds of resources in the programs you write. The Objects of a class, primitive data-types etc. are supported by C#, and the space occupied by them is automatically release by the GC, when it finds they are no longer in use. Such resources are called Managed Resources. But, there are other resources, like a Database Connection, a File Stream, a Network Stream, a pipe etc. which are not supported by C#. This means, when they are no longer in use, the responsibility of their clean-up does not lie with the GC. You have to make sure, you clean up these resources. Such resources are called unmanaged resources. If your program/class uses unmanaged resources, you can clean up these resources in two ways 1)Write a destructor or finalizer method. 2)Override the Dispose() method. If you write a destructor in the class, it is called automatically, just before the objects of this class are destroyed by GC. There are two ways to write a destructor
class MyClass { ~MyClass() { Console.WriteLine("You can free up an unmanaged resources here."); } }

43 | P a g e

Learn C# - do it yourself way...


class DestroyDemo { public static void Main() { MyClass obj = new MyClass(); obj = null; } }

2008

A destructor has the same name as the class, but prefixed with a ~ tilde sign. Internally, this Destructor is translated to a call to the Finalize() method
class MyClass { protected override void Finalize() { try { Console.WriteLine("You can free up any unmanaged resources here"); } finally { base.Finalize(); } } }

Now, when you have a number of objects, how does GC keep track of which objects to finalize? The GC maintains a queue of all the objects that are to be finalized. This is called Finalization Queue. However, we never know for sure, when the GC kicks in and calls the finalizer(destructor) method. If there is an unmanaged resource that needs to be released promptly on time, this approach is not helpful. In other words, finalization is non-deterministic(random). When we want to exercise control over the finalization process, we can override the Dispose() method (whose interface is IDisposable). The Dispose() method differs from the Finalize() method, in that, we need to explicitly call the Dispose() method. A finalizer is implicitly called, and cannot be explicitly called, even if you wanted to. Implicit Resource Cleanup Explicit Resource Cleanup
44 | P a g e

Destructor or Finalize() method Dispose()

Learn C# - do it yourself way...

2008

7
Inheritance Our objects family tree
7.1 Overview of Inheritance
Kathy is assigned the task of building an Employee Management System. She starts by thinking, I am gonna take Employee objects for every Employee in the organisation. So, she begins by writing an Employee class as follows
class Employee { public string name; public string address; public int SSN; public int number; public float salary; public float computePay() { return salary / 12.0F; } }

The design of an Employee class seems fine to her initially. An employee has a name, address, and number and so on... We want the compute the pay of different Employee objects.

45 | P a g e

Learn C# - do it yourself way...

2008

But, Kathy questions herself, does every Employee have a salary? Is it true that every Employee object has a salary. By studying the problem domain, she finds out that there are Employees which are paid on an hourly basis, or employees which are on contract basis. The first mistake Kathy made was to add a field of type salary to Employee. She discovers although employees are the objects in our problem domain, there are actually two different types of Employee objects : Salaried Employees and Hourly Employees. Therefore, we should write two classes : Salary and Hourly. The Salary class should have a field to represent the employees annual salary because a Salaried Employee has a salary. The Hourly class should have fields to represent the employees hourly pay rate and the no of hours for which he worked. The Salary and Hourly classes look like this
class Salary { public string name; public string address; public int SSN; public int number; public int salary; public float computePay() { return salary / 12.0F; } } class Hourly { public string name; public string address; public int SSN; public int number; public int hoursWorked; public int hourlyRate; public int computePay() { return hoursWorked*hourlyRate; } }

46 | P a g e

Learn C# - do it yourself way...

2008

Although Salary and Hourly classes are different types, they are not entirely different. In fact, the two types of employees have a lot in common, as seen by the repetition of fields and methods in these two classes. So, we can take the common elements from both the classes, and put them in a parent class leaving the unique elements behind in the child class. We can simply make the Salary and Hourly classes inherit the elements of the Employee class. Employee class is called Parent class/Base class/Super class. Salary and Hourly classes are called child class/Derived class/subclass. If you want to make Salary and Hourly the child classes of Employee, we write them as follows :
class Employee { public string name; public string address; public int SSN; public int number; } class Salary : Employee { public int salary; public float computePay() { return salary / 12.0F; } } class Hourly : Employee { public int hoursWorked; public int hourlyRate; public int computePay() { return hoursWorked*hourlyRate; } }

When your classes use inheritance, you only need to write your code once.

In the above scenario, Salary class and the Hourly class have a lot of same code.
47 | P a g e

Learn C# - do it yourself way...

2008

Salary Employee and Hourly Employee are both employees. When you have two classes which are more specific cases of something more general, you can set them up to inherit from the same base class.
Employee name address SSN number GetEmployee()

Salary salary computePay()

Hourly hourlyRate hoursWorked computePay()

Build up your class model, by starting General and getting more Specific

7.2 Method Overriding


class Employee { public string name; public string address; public int SSN; public int number;

48 | P a g e

Learn C# - do it yourself way...

2008

public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine(); } } class Salary : Employee { public int salary; public float computePay() { return salary / 12.0F; } public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine("Salary : " + salary); Console.WriteLine(); } } class Hourly : Employee { public int hoursWorked; public int hourlyRate; public int computePay() { return hoursWorked * hourlyRate; } public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine("Hours Worked : " + hoursWorked); Console.WriteLine("Hourly Rate : " + hourlyRate); Console.WriteLine(); } } class EmployeeDemo { public static void Main() { Employee e = new Employee(); e.name = "Robert Smith"; e.address = "111 Palm street"; e.SSN = 999901111;

49 | P a g e

Learn C# - do it yourself way...


e.number = 1; Salary s = new Salary(); s.name = "Jane Smith"; s.address = "Oak Drive"; s.SSN = 111009999; s.number = 2; s.salary = 10000; Hourly h = new Hourly(); h.name = "George Washington"; h.address = "333 Espresso Lane"; h.SSN = 111990000; h.number = 3; h.hoursWorked = 200; h.hourlyRate = 30; e.GetEmployee(); s.GetEmployee(); h.GetEmployee(); } }

2008

7.3 Use of base keyword


using System; class Employee { public string name; public string address; public int SSN; public int number; public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine(); } } class Salary : Employee { public int salary; public float computePay() { return salary / 12.0F; } public void GetEmployee() { base.GetEmployee(); Console.WriteLine("Salary : " + salary); Console.WriteLine(); } }

50 | P a g e

Learn C# - do it yourself way...

2008

class Hourly : Employee { public int hoursWorked; public int hourlyRate; public int computePay() { return hoursWorked * hourlyRate; } public void GetEmployee() { base.GetEmployee(); Console.WriteLine("Hours Worked : " + hoursWorked); Console.WriteLine("Hourly Rate : " + hourlyRate); Console.WriteLine(); } } class EmployeeDemo { public static void Main() { Employee e = new Employee(); e.name = "Robert Smith"; e.address = "111 Palm street"; e.SSN = 999901111; e.number = 1; Salary s = new Salary(); s.name = "Jane Smith"; s.address = "Oak Drive"; s.SSN = 111009999; s.number = 2; s.salary = 10000; Hourly h = new Hourly(); h.name = "George Washington"; h.address = "333 Espresso Lane"; h.SSN = 111990000; h.number = 3; h.hoursWorked = 200; h.hourlyRate = 30; e.GetEmployee(); s.GetEmployee(); h.GetEmployee(); } }

7.4 Adding Constructors


using System; public class Employee { public string name; public string address;

51 | P a g e

Learn C# - do it yourself way...


public int SSN; public int number; public Employee() { Console.WriteLine("Inside Grandparent"); } public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine(); } } public class Salary : Employee { public int salary; public Salary() { Console.WriteLine("Inside Parent"); } public float computePay() { return salary / 12.0F; } public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine("Salary : " + salary); Console.WriteLine(); } } public class PartTimeSalary : Salary { public PartTimeSalary() { Console.WriteLine("Inside PartTimeSalary"); } } class EmployeeDemo { public static void Main() { PartTimeSalary pts = new PartTimeSalary(); } }

2008

52 | P a g e

Learn C# - do it yourself way...

2008

7.5 Calling Parent class Constructors


using System; public class Employee { public string name; public string address; public int SSN; public int number; public Employee(string n, string a, int S, int num) { name = n; address = a; SSN = S; number = num; } public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine(); } } public class Salary : Employee { public int salary; public Salary(string n,string a, int S, int num, int sal):base(n,a,S,num) { salary = sal; } public float computePay() { return salary / 12.0F; } public void GetEmployee() { Console.WriteLine("Name : " + name); Console.WriteLine("Address : " + address); Console.WriteLine("SSN : " + SSN); Console.WriteLine("Number : " + number); Console.WriteLine("Salary : " + salary); Console.WriteLine(); } } class EmployeeDemo { public static void Main() {

53 | P a g e

Learn C# - do it yourself way...

2008

Salary s = new Salary("Jane Smith", "222 Oak Drive", 111009999, 3, 10000); s.GetEmployee(); } }

54 | P a g e

Learn C# - do it yourself way...

2008

8
Advanced C# Language Concepts
8.1 Using Parent class references to Child Objects
An object reference can refer to an object of its class, or to an object of any class derived from it by Inheritance. Suppose, we have the following class hierarchy.

For example, if Animal class is the parent, and Bird is its child, SongBird is the child of Bird and so on,... Animal reference can refer to a Bird object or a SongBird object. Animal a; a = new Animal();

55 | P a g e

Learn C# - do it yourself way...

2008

a = new Bird(); a = new SongBird(); Assigning an object to an ancestor reference is considered to be a widening conversion, and can be performed using simple assignment. Animal a = new MockingBird(); Assigning an ancestor object to a child reference can also be done, but it is considered to be a narrowing conversion and must be done with a cast. MockingBird m = (MockingBird)new Bird(); The widening conversion is the most useful for implementing polymorphism.

8.2 Polymorphism via Inheritance


A polymorphic reference is the one which can refer to different types of objects at different times. Such an object reference can refer to one object at one time, and can refer to another object(related by inheritance) at another time. It is the type of object being reference, not the reference type, which determines which method is invoked. Polymorphic references are therefore resolved at run-time, not during compilation; hence it is called dynamic binding.
class Shape { public virtual void Area() { } } class TwoDimShape : Shape { public int a;

56 | P a g e

Learn C# - do it yourself way...


public int b; } class ThreeDimShape : Shape { public int a; public int b; public int c; } class Rectangle : TwoDimShape { public override void Area() { int area = a * b; Console.WriteLine("Area : " + area); } public void SetRectangle(int x, int y) { a = x; b = y; } } class Triangle : TwoDimShape { public override void Area() { double area = 0.5 * a * b; Console.WriteLine("Area : " + area); } public void SetTriangle(int bas, int height){ a = bas; b = height; } } class Cube : ThreeDimShape { public override void Area() { int area = 6 * a * a; Console.WriteLine("Area : " + area); } public void SetCube(int s) { a = b = c = s; } } class Box : ThreeDimShape { public override void Area() { int area = 2 * a * b + 2 * b * c + 2 * a * c; Console.WriteLine("Area : " + area); } public void SetBox(int x, int y, int z)

2008

57 | P a g e

Learn C# - do it yourself way...


{ a = x; b = y; c = z; } } class ShapeDemo { public static void Main() { int choice; Shape s = new Shape(); Triangle t = new Triangle(); t.SetTriangle(5,10); Rectangle r = new Rectangle(); r.SetRectangle(10,10); Cube c = new Cube(); c.SetCube(5); Box b = new Box(); b.SetBox(10,20,30); while (true) { Console.WriteLine("Enter a choice : "); Console.WriteLine("1 - Rectangle"); Console.WriteLine("2 - Triangle"); Console.WriteLine("3 - Cube"); Console.WriteLine("4 - Box"); Console.WriteLine("5 - Exit"); choice = Convert.ToInt32(Console.ReadLine()); if (choice == 1) s = r; if (choice == 2) s = t; if (choice == 3) s = c; if (choice == 4) s = b; if (choice == 5) break; s.Area(); //Call is resolved at run-time } } }

2008

58 | P a g e

Learn C# - do it yourself way...

2008

8.3 Abstract Classes and Abstract Methods


Abstraction is the ability to make a class/method/property abstract in C#. An abstract class is the one which cannot be instantiated. All other functionalities of the class still exist, its fields, its methods and constructors are all accessed in the same way. You just cannot create objects of an abstract class. An abstract class might initially seem like an odd design. Why write a class and not allow anyone to create objects of it? The Employee class that we have written in the previous programs is an example where we do not want to create objects of Employee. Notice, that the Employee class does not have any information about salary and how much his pay comes to. It is safe to say, that no employee of our organisation would like to be strictly an object of Employee. This means, although we need the Employee class as a parent of Salary and Hourly to support inheritance, we do not want to create any objects of this class. We can make it, so that no one can create objects of Employee class, by declaring the Employee class abstract. The only result of making the Employee class abstract is that we can no longer create objects of Employee. If the Employee class is made abstract, the following statement will not compile Employee e; e = new Employee(George W.,Houston,43); //Error Just like you can make a class abstract, you can also make a method abstract. For example, we could have a computePay() method in the Employee class as abstract.

59 | P a g e

Learn C# - do it yourself way...

2008

An abstract method is never called. Think about it. If computePay() is abstract in the Employee() class, we really dont care what computePay() does in the Employee class, because it will never be invoked/called. So, the abstract computePay() method in the Employee class will be empty. Our assumption is that the child classes of Employee will override the computePay(). This is where abstract methods are useful. If you want a class to contain a particular method, but you want the actual implementation to be determined by the child classes, you must declare the method in the parent class as abstract. Abstract methods consist of a method signature, but no method body.
public abstract class Employee { public string name; public string address; public int SSN; public int number; public abstract void computePay(); }

8.4 Sealed Keyword


Sealed keyword works exactly opposite to abstract. - A Sealed class cannot be sub-classed. - A Sealed method cannot be overridden.

8.5 Namespaces
Every class belongs to a namespace. Namespaces basically have two purposes 1. Namespace provides a mechanism for organising classes. 2. Namespace does compartmentalization. When developing a C# program, you put classes that go together in the same namespace. For example, in C# the classes that are used to
60 | P a g e

Learn C# - do it yourself way...

2008

perform basic Input and Output are in System namespace. The classes used for GUI applications are in System.Windows.Forms namespace. The classes used for creating threads are in System.Threading namespace. Q. Why are namespaces necessary? What if I have a small program that is only a dozen classes? Namespace is more than just a mechanism for organising classes. A more important aspect of namespaces is that they create compartments. For example, suppose that your program contains a class named Vehicle. What if I wrote a class Vehicle as well? How would you be able to tell them apart. What if someone wanted to use my Vehicle class and your Vehicle class in their program? Q. I have seen this problem before. Why dont you change the names of the classes, such as Vehicle1 and Vehicle2? No thanks. I would have to re-write and re-compile a bunch of code. With namespaces, I dont have to worry about it. If the two Vehicle classes are in different namespace/compartments, my C# program can distinguish between the two Vehicle classes.

8.6 Adding a class to a Namespace


To add a class to a namespace/compartment, we use the namespace keyword. namespace A{ ... } For example, if you wanted to put Employee, Salary and Hourly classes in the payroll namespace/compartment we can do it as follows

61 | P a g e

Learn C# - do it yourself way...


using System; namespace payroll { public class Employee { //Body of the class } public class Salary : Employee { //Body of the class } public class Hourly : Employee { //Body of the class } }

2008

The Employee, Salary and Hourly classes are now all in the same namespace.

8.7 Compartments created by Namespaces


Namespace creates a compartment for all classes. If we put a class inside a namespace/compartment, the namespace becomes a part of the name of the class. Say for example, when we put Employee class inside payroll package, the name of the class now becomes
payroll.Employee

The Employee class can now no longer be accessed by the name Employee. To refer to the Employee class, we must everytime call it payroll.Employee. Similarly, we must refer to Salary and Hourly classes as payroll.Salary and payroll.Hourly. Suppose you have a written a Vehicle class, and I too have written a Vehicle class. Kate wants to use both the Vehicle classes in their program. So, I put my Vehicle class in a compartment quasar, and you put your vehicle class in another compartment student. Kate will now refer to both the Vehicle classes as,

62 | P a g e

Learn C# - do it yourself way...

2008

quasar.Vehicle student.Vehicle To create objects of these classes, Kate would write quasar.Vehicle v1 = new quasar.Vehicle(); student.Vehicle v2 = new student.Vehicle(); Here, v1 refers to a quasar.Vehicle object, whereas v2 refers to student.Vehicle object. Thus, from the above example, you can deduce the fact that, namespaces help you to avoid naming conflicts by creating compartments. Note Classes within the same namespace/compartment do not need to use the <namespace>.<class-name> convention while referring to each other. Thus, if write another class Test inside payroll namespace, we can call Employee, Salary and Hourly classes directly without using any special naming convention. Classes in the same compartment find each other without any special syntax.

8.8 using Keyword


If a class wants to refer to another class within the same namespace/compartment, the namespace need not be used. We could refer to it directly. However, outside the compartment, we must use the fully qualified name of the class. Consider the following program :
using System; namespace payroll { public class Employee { public string name; public string address; public int SSN; public int number;

63 | P a g e

Learn C# - do it yourself way...


public Employee(string n, string a, int ssn, int num) { name = n; address = a; SSN = ssn; number = num; } } }

2008

There is another class Boss which would like create Employee objects.
using System;

class Boss { public static void Main() { payroll.Employee e = new payroll.Employee("Jane Smith", "111 Oak drive", 999001111, 1); } }

Writing payroll.Employee everytime could become tedious or cumbersome. To make things easy, we can use the using keyword. using keyword specifies in which namespace to look for the given classes. If you write using payroll, then we can refer to the Employee class, simply as Employee without using the fully-qualified name.
using System; using payroll; class Boss { public static void Main() { Employee e = new Employee("Jane Smith", "111 Oak street", 999001111, 1); } }

Note that, using keyword is just a convenience statement. During compilation, the C# compiler will replace all instances of Employee class with payroll.Employee(Fully-Qualified name).

64 | P a g e

Learn C# - do it yourself way...

2008

8.9 Skeleton of a C# Executable


Assembly MyProgram.exe

File1.cs

File2.cs

File3.cs

namespace A { .... }

namespace B { .... }

namespace C { .... }

class A { //Body of class }

class B { //Body of class }

class C { //Body of class }

8.10 Interfaces
An interface is a collection of abstract members. A class implements an interface thereby inheriting the abstract methods of the i interface. All the methods of an interface need to be defined in the class. Syntactically, an interface is defined using the C# interface keyword.
public interface IName { void method1(); void method2(); }

In the .NET Framework, interfaces have a special naming convention. All interface names begin with a capital I. Interfaces can have properties as well. Difference from a class 1. You cannot create an object of an interface.
65 | P a g e

Learn C# - do it yourself way...

2008

2. An interface does not contain any constructor. 3. All methods in an interface are abstract. 4. An interface can inherit multiple interfaces. An interface is like a contract a promise that a class will implement a specific set of functionalities. When a class implements an interface, it signs a contract, a treaty and promises to provide implementation/definition of all methods or functions declared in the interface. C# code can question an object to determine whether it supports an interface. Interrogating an object is basically asking the question,Do you support this interface?. If the object answers, Yes, I do!, than you can call the methods defined in the interface on the object.

8.11 Exposing Methods through an Interface


public class Employee : Payable,EmployeeInfo { string name, address; double weeklyPay; public Employee(string n, string a) { name = n; address = a; } public string GetName() { return name; } public string GetAddress() { return address; } public void SetName(string n) { name = n; } public void SetAddress(string a) { address = a; }

66 | P a g e

Learn C# - do it yourself way...

2008

public double GetWeeklyPay() { return weeklyPay; } public void computePay(int hoursWorked) { weeklyPay = hoursWorked * 6.50; Console.WriteLine("Weekly Pay for : " + name + " is Rs." + weeklyPay); } public void MailCheck() { Console.WriteLine("Mailing check to : " + name + " at " + address); } }

An organisation has many employees working in it. The Employee of an organisation is represented by an Employee class object. Associated with every Employee is his personal information such as his name, address. Every employee also has a salary and other payrelated information. The organisation has two departments Payroll and Human Resource. Different parts in an organisation have different data needs. For example, the payroll department handles the payroll needs, but it does not need access to or change the personal information of an employee. On the same lines, the Human Resource department manages the general information about Employees, but it does not need access to the Employees pay details. How do we realise these business rules in C#? The answer lies in the innovative use of Interfaces. Although we cannot instantiate(create an object) an interface, we can do the following

67 | P a g e

Learn C# - do it yourself way...

2008

interface MyInterface { void a(); void b(); } class MyClass : MyInterface { void a(){ Console.WriteLine(Inside A); } void b(){ Console.WriteLine(Inside B); } void c(){ Console.WriteLine(Inside C); } } Declare an interface reference MyInterface iref; Assign to it, an object of a class that implements this interface iref = new MyClass(); Using iref, we can call the methods a() and b(), but we cannot call the method c(). Thus, we can call only those methods on the object, which are declared and exposed by the interface. Thus, by assigning an object to an interface reference, we can restrict access to the methods that can be called on the object. In the Employee class example, we could take two different interfaces payable and EmployeeInfo for the Payroll and HR departments. The payable interface exposes and provides an interface to only those
68 | P a g e

Learn C# - do it yourself way...

2008

methods that are needed by the payroll department. Through the EmployeeInfo interface, the HR department can only access those methods which help it to manage Employee Information like name and address.
public interface Payable { void computePay(int hoursWorked); void MailCheck(); double GetWeeklyPay(); } public interface EmployeeInfo { string GetName(); void SetName(string name); string GetAddress(); void SetAddress(string address); }

To represent the Payroll and Human Resource Departments, we write the Payroll and HumanResource classes.
public class Payroll { public void PayEmployee(Payable p) { p.computePay(10); p.MailCheck(); } } public class HumanResource { public string GetInfo(EmployeeInfo e) { return e.GetName() + " " + e.GetAddress(); } public void ChangeName(EmployeeInfo e, string n) { Console.WriteLine("Changing Name for : " + e.GetName()); e.SetName(n); Console.WriteLine("New name is : " + e.GetName()); } public void UpdateAddress(EmployeeInfo e, string a) { Console.WriteLine("Changing address for : " + e.GetName()); e.SetAddress(a); Console.WriteLine("New address is :" + e.GetAddress()); } }

69 | P a g e

Learn C# - do it yourself way...

2008

Now, we write the Main Program, where we take a fictious Employee, and the payroll and HR departments.
class EmployeeManagement { public static void Main() { Employee e = new Employee("George Washington","Mt. Vernon"); Payroll payroll = new Payroll(); HumanResource hr = new HumanResource(); payroll.PayEmployee(e); hr.GetInfo(e); hr.ChangeName(e, "Bill Gates"); hr.UpdateAddress(e, "Redmond VA"); } }

70 | P a g e

Learn C# - do it yourself way...

2008

9
File Reading and Writing I/O
9.1 Concept of Streams
Many applications which you would write, need to store data and retrieve data from a file. For example, in an Employee Management System, you would like the Employee details to be stored permanently in a file on the disk. You would also want to read Employee data from the file on disk. You might also need to update an employees information in a file, say for example his salary is raised, or his marital status changes from single to Married. Reading or writing data to files is a functionality which you require often while making your application. Thus, it is important that we study, how we can read or write to files. However, an application cannot directly read or write data to a file. To connect an application to a file, we must use a virtual pipe. Just as a real pipe carries water, the virtual pipe carries bytes of data to and fro between the application and the file. This virtual pipe in C# is called a Stream. If the stream connects to a file, its called FileStream.

71 | P a g e

Learn C# - do it yourself way...

2008

To create a FileStream in C#, we must create an object of the ream FileStream class. FileStream fs = new FileStream(<file FileStream(<file-name>,<file-mode>,<file mode>,<fileaccess>,<file-Share>) The FileStream constructor accepts the FileName as the first argument. This must be the absolute file path. N Next, the file mode must be specified. The file mode tells the C# system, which mode you would like to operate the file in. The FileMode enum looks like this enum FileMode{ CreateNew, Create, Open, OpenOrCreate, Truncate, Append } Create always creates a new file. CreateNew create a new file, and if the file already exists, it overwrites the old file. OpenOrCreate works in 2 ways if the file does not exist, it creates the file, if the file exists

72 | P a g e

Learn C# - do it yourself way...

2008

it will open the file. Open simply opens the file. Append is used to append whatever you write/delete to(from) the end of the file. FileAccess enum specifies whether you would like to read from the file, write to the file or do both ; ReadWrite. A FileStream attached to a file, is all you need to do operations like adding data, modifying data and deleting data from a file. To write to a FileStream, we can call its Write() method. Before reading from the stream, we must reset the internal position of the stream(using Position property) and call the ReadByte() method. Directly reading and writing bytes to a file can become tedious as it demands that you work directly with bytes. Reader and Writer objects encapsulate(hide from you) the detailed process of reading and writing, and provide a higher level of abstraction to you.

9.2 Concept of Reader and Writer


Once a FileStream has been hooked up to a file, we can read or write to the FileStream object. However, we directly do not read or write to the stream. We use Reader and Writer objects to read-write to the FileStream. To read, the Reader object reads from the FileStream, fetches whatever there is in the FileStream into a buffer/temporary memory. Similarly, a writer object is used to write bytes to a FileStream. Lets study a simple program to write a few lines of text to a file.
using System; using System.IO; class WriteDemo { public static void Main() { Console.WriteLine("Enter the file you want to write to : "); String path = Console.ReadLine(); Console.WriteLine("What do you want to write ? "); String textToWrite = Console.ReadLine();

73 | P a g e

Learn C# - do it yourself way...


FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write); StreamWriter writer = new StreamWriter(stream); writer.Write(textToWrite); writer.Close(); stream.Close(); } }

2008

The above program asks the user to enter the path, where he would like to store the file. It then asks the user to enter some text to be written to the file. A FileStream object is created and hooked to the file in the specified path, with the Create FileMode and Write access(as we want to write text to the file). A writer object is created. There is a class StreamWriter in C# that represents the concept of writer. To model a writer, we must create an object of the StreamWriter class. While creating a StreamWriter object, we must pass as an argument to the constructor, the stream, we would like the StreamWriter object to write to. The writer object is now the tool that you would use to actually write things to a file. You do so by calling the methods of the StreamWriter object. To simply write text, we use Write() method. WriteLine() method always write the text onto a new line each time. To the Write() and WriteLine() methods you can pass the text that you would like to write as a String object. After youre done with writing text to the file, it is very important to remember that we must unhook the FileStream from the file. If you forget to do this, even after the program is over, the file will remain blocked by the FileStream, so no other program which needs access to the file will be able to access it. To do so, we close the FileStream and StreamWriter objects, by calling their Close() methods.

74 | P a g e

Learn C# - do it yourself way...

2008

9.3 Simple Program to read from a file


using System; using System.IO; class ReaderDemo { public static void Main() { FileStream stream = new FileStream("C:\\abc.txt", FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(stream); string input = null; while ((input = reader.ReadLine()) != null) Console.WriteLine(input); reader.Close(); } }

To read from a file, one must first create a FileStream object and hook it upto the file, open the file in read-mode. Next, we take a StreamReader object and pass to its constructor the stream, we would like to read from. We read one line at a time, by calling ReadLine() method on the reader object. Thus, the entire file is read line-by-line till we do not encounter the end of the file, where the input read is null. Finally, we close the StreamReader object.

9.4 Using the Seek() Method


The Seek() method can be used to skip bytes in FileStream, and move the cursor ahead in the stream, by specifying an offset. This is helpful, if you dont always want to start reading from the beginning of the file, but maybe at 10 bytes from start of file.
using System; using System.IO; class ReaderDemo { public static void Main() {

75 | P a g e

Learn C# - do it yourself way...

2008

FileStream stream = new FileStream("C:\\abc.txt", FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(stream); string input = null; stream.Seek(12, SeekOrigin.Begin); while ((input = reader.ReadLine()) != null) Console.WriteLine(input); reader.Close(); } }

Given the above abc.txt file, we get the following output, when we specify the offset = 12 bytes from the beginning.

If we modify the Seek() function as


stream.Seek(10, SeekOrigin.Begin); stream.Seek(2, SeekOrigin.Current);

The output is still the same, SeekOrigin.Current move the cursor ahead by 2 bytes from its current position. After the first call to Seek() the cursor is at position 10. Thus, current position of cursor becomes 10. After the second call to Seek(), the cursor would reach 10+2=12th position.

76 | P a g e

Learn C# - do it yourself way...

2008

9.5 DirectoryInfo and FileInfo classes


The FileInfo class in C# allows you to access, manipulate and find information about a single file on the Hard-disk. You can question the file for various things such as name of the file Name property, fully qualified name FullName property, last accessed time LastAccessTime property, size of the file Length property, extension - Extension property of the file etc.
class FileDemo { public static void Main() { FileInfo f = new FileInfo("C:\\abc.txt"); Console.WriteLine("File Name : " + f.FullName); Console.WriteLine("File Attributes : " + f.Attributes.ToString()); Console.WriteLine("File Creation Time : " + f.CreationTime); Console.WriteLine("File Exists : " + f.Exists); Console.WriteLine("File last accessed : " + f.LastAccessTime); Console.WriteLine("File Size : " + f.Length); } }

The DirectoryInfo class is used in a similar manner to find information about a directory.
using System; using System.IO; class DirectoryDemo { public static void Main() { DirectoryInfo dir = new DirectoryInfo("C:\\"); Console.WriteLine("Directory Name : " + dir.FullName); Console.WriteLine("Last Access Time : " + dir.LastAccessTime); Console.WriteLine("Creation Time : " + dir.CreationTime); Console.WriteLine("Attributes : " + dir.Attributes); } }

77 | P a g e

Learn C# - do it yourself way...

2008

9.6 Enumerating the files in a Directory


We may use the DirectoryInfo and the FileInfo classes to find out the contents of a directory. Lets suppose, we are given a directory C:\Windows and we would like to find what are the sub-directories and files inside this directory. To find the subdirectories in a given directory, we call the GetDirectory() method. The result of calling this method is an array of DirectoryInfo[]. Each element of the array represents a subdirectory. Similarly, to find the files inside a Directory, we call the GetFiles() method.
using System; using System.IO; class EnumeratingDemo { public static void Main() { DirectoryInfo dir = new DirectoryInfo("C:\\"); DirectoryInfo[] subDirs = dir.GetDirectories(); Console.WriteLine("Name " + "\t\t\t" + "Creation Time "); foreach (DirectoryInfo d in subDirs) { Console.WriteLine(); Console.Write(d.Name); Console.Write("\t\t\t"+d.CreationTime); } } }

78 | P a g e

Learn C# - do it yourself way...

2008

79 | P a g e

Learn C# - do it yourself way...

2008

10
Threads, Processes, AppDomains and Multi-threading

80 | P a g e