Sunday, May 30, 2010

programming in c#

CSharp Basics


2.1 Introduction

Compile and link the programs with

csc filename.cs

This generates an execute file named filename.exe. This is also known as an executable

assembly. The most common compiler options are:

• /checked Explicitly request checking for entire component

• /r: Reference libraries

• /out: Output file

• /target: Component type (Library, module, .exe)

• /define: Define preprocessor symbols

• /doc: Defines documentation output

• /version: Define version

• /reference: Record dependency information

• /debug+ Generate debug code (creates .exe and .pdb)

• /main Define class which contains entry main

In C# everything must be inside a class. Thus also the Main method must be contained

inside a class. In the first example this is Hello1. The method name, Main,

is reserved for the starting point of a program. Main is often called the entry point

(starting address) of the program. In front of the word Main is a static modifier.

The static modifier explains that this method works in this specific class only, rather

6

2.1. INTRODUCTION 7

than an instance of the class. This is necessary, because when a program begins, no

object instances exists.

To avoid fully qualifying classes throughout the program, we can use the using

directive. We write to the screen, where \n provides a newline. Note that C# is

case-sensitive. A comment is indicated by //.

// cshello.cs

using System;

class Hello1

{

public static void Main()

{

Console.WriteLine("Hello Egoli\n"); // \n newline

Console.WriteLine("Good Night Egoli");

Console.Write("midnight");

} // end Main

}

The namespace declaration, using System; indicates that we are referencing the

System namespace. Namespaces contain groups of code that can be called upon by

C# programs. With the using System; declaration, we are telling our program that

it can reference the code in the System namespace without pre-pending the word

System to every reference. The System.Console class contains a method

WriteLine()

and a method

Write()

that can be used to display a string to the console. The difference is that the

Console.Write(.) statement writes to the Console and stops on the same line,

but the Console.WriteLine(.) goes to the next line after writing to the Console.

Strings are embedded in double quotes, for example "name".

An exception is an error condition or unexpected behavior encountered by an executing

program during runtime. We write to the screen using exception handling

with a try catch finally block. The try block is used around statements that

might throw exceptions. The catch block defines exception handlers. Code in a

finally block is always executed. Use it to release resources, for example to close

any streams or files that were opened in the try block. Some common exceptions

are listed here:

8 CHAPTER 2. CSHARP BASICS

• System.ArithmeticException: A base class for exceptions that occur during

arithmetic operations, such as System.DivideByZeroException

• System.ArgumentException: Thrown when an argument to a method is

invalid

• System.ArrayTypeMismatchException: Thrown when a store into an

array fails because the actual type of the stored element is incompatible with

the actual type of the array.

• System.DivideByZeroException: Thrown when an attempt to divide an

integral value by zero occurs.

• System.IndexOutOfRangeException: Thrown when an attempt to index

an array via an index that is less than zero or outside the bounds of the array.

• System.InvalidCastException: Thrown when an explicit conversion from

a base type or interface to derived types fails at run time.

• System.MulticastNotSupportedException: Thrown when an attempt to

combine two non-null delegates fails, because the delegate type does not have

a void return type.

• System.NullReferenceException: Thrown when a null reference is used

in a way that causes the referenced object to be required.

• System.OutOfMemoryException: Thrown when an attempt to allocate

memory (via new) fails.

• System.OverflowException: Thrown when an arithmetic operation in a

checked context overflows.

To access command line parameters we change the signature of the Main(void) to

Main(string[] args). The expression string[] args defines an array of strings.

// hello2.cs

using System;

class Hello2

{

public static void Main(string[] args)

{

try { Console.WriteLine("Hello {0}",args[0]); }

catch(Exception e) { Console.WriteLine(e); }

Console.WriteLine("Good Night");

} // end Main

}

2.2. BASIC DATA TYPES 9

After compiling the program we run it with, for example,

Hello2 James

To read from the keyboard we use the method ReadLine(). The command Length

returns the number of elements in the array. We are also using an if-else construct.

// hello3.cs

using System;

class Hello3

{

public static void Main(string[] args)

{

if(args.Length > 0)

{

Console.WriteLine("Hello {0}",args[0]);

}

else

{

Console.WriteLine("Enter your name: ");

string name = Console.ReadLine();

Console.WriteLine("Hello {0}",name);

}

Console.WriteLine("Good Night");

} // end Main

}

In the case of compiling using Visual Studio or some other IDE the problem of the

program’s console window disappearing too quickly to view its output might occur.

This problem can be solved using the Read() method to pause the window. The

program above can be modified like so:

...

Console.WriteLine("Good Night");

Console.Read(); // Pauses the program until a key is pressed

} // end Main

}

2.2 Basic Data Types

Basic (primitive) data types are

10 CHAPTER 2. CSHARP BASICS

bool,

byte, sbyte, char,

short, ushort, int, uint, long, ulong

float, double, decimal

The range of byte is 0..255 and for sbyte is -128..127. short and ushort are 2

bytes (16 bits), where ushort is unsigned. int and uint are 4 bytes. The floating

point number float is 4 bytes and the floating point number double is 8 bytes.

char data type (2 bytes) in C# contains Unicode characters similar to Java. CSharp

is a strongly typed language and therefore variables must be declared with an available

type and must be initialized with a value (or reference) of the same type.

Built-in types are also string and object.

C# .NET Type Description

bool System.Boolean true/false

byte System.Byte unsigned byte value

sbyte System.SByte signed byte value

char System.Char a single character

short System.Int16 16 bit signed integer

ushort System.UInt16 16 bit unsigned integer

int System.Int32 32 bit signed integer

uint System.UInt32 32 bit unsigned integer

long System.Int64 64 bit signed integer

ulong System.UInt64 64 bit unsigned integer

float System.Single 32 bit floating point

double System.Double 64 bit floating point

decimal System.Decimal a high precision double

string System.String string of characters

object System.Object a generic type

At compile time the C# compiler converts the C# types into their corresponding

.NET types described in the above table. Apart from the above basic types the user

may define his own types using enum, struct and class.

// datatypes.cs

using System;

class Datatypes

{

public static void Main()

{

bool b = true; // boolean data type

Console.WriteLine(!b); // ! is the logical NOT

2.3. ASCII TABLE 11

// character 2 bytes Unicode

char e = ’a’; // character ’a’ ASCII value 97

Console.WriteLine(e);

char f = ’\0’; // null character ASCII value 0

Console.WriteLine(f);

// default integer type is int

byte c = 255; // unsigned byte 0...255

c++;

Console.WriteLine(c);

sbyte d = -125; // signed byte -128...127

d--;

short g = -10000; // short -32768...32767 (2 bytes)

Console.WriteLine(g);

ushort h = 20000; // unsigned short 0...65535 (2 bytes)

Console.WriteLine(h);

int i = -100000; // signed int -2147483648...2147483647

Console.WriteLine(i);

uint j = 200000; // unsigned int 0...4294967295

Console.WriteLine(j);

long k = -234567899; // signed long 64 bits -2^63...2^63-1

Console.WriteLine(k);

ulong l = 3456789123; // unsigned long 64 bits 0...2^64-1

Console.WriteLine(l);

// default floating point number is double

// (float) type conversion from double to float

float m = (float) 3.145; // float 32 bits

Console.WriteLine(m);

double n = 3.14159; // double 64 bits

Console.WriteLine(n);

// decimal 128 bits

decimal p = (decimal) 2.89124357865678; // type conversion

Console.WriteLine(p);

}

}

Note that (data type) is the type conversion operator.

2.3 ASCII Table

ASCII (American Standard Code for Information Interchange) is a character set

and a character encoding based on the Roman alphabet as used in modern English.

ASCII codes represent text in computers, in other communication equipment, and in

control devices that work with text. ASCII specifies a correspondence between digit

12 CHAPTER 2. CSHARP BASICS

bit patterns and the symbol of a written language. ASCII is, strictly, a seven-bit

code, meaning that it uses the bit patterns representable with seven binary digits

(a range of 0 to 127) to represent character information. ASCII reserves the first 32

codes (numbers 0-31 decimal) for control characters. The capital ’A’ is 65 (decimal)

and the small ’a’ is 97. Furthermore ’0’ is 48 and ’9’ is 57. Space is 32.

We are doing type conversion from char -> int using the ASCII table. The type

conversion operator is (data-type). The null character is ’\0’.

// Escape.cs

using System;

class Escape

{

public static void Main()

{

char c1 = ’\b’; // backspace

int i1 = (int) c1; // ASCII value

Console.WriteLine("i1 = " + i1); // 8

char c2 = ’\f’; // form feed

int i2 = (int) c2; // ASCII value

Console.WriteLine("i2 = " + i2); // 12

char c3 = ’\n’; // newline

int i3 = (int) c3; // ASCII value

Console.WriteLine("i3 = " + i3); // 10

char c4 = ’\r’; // carriage return

int i4 = (int) c4; // ASCII value

Console.WriteLine("i4 = " + i4); // 13

char c5 = ’\t’; // horizontal tab

int i5 = (int) c5; // ASCII value

Console.WriteLine("i5 = " + i5); // 9

char c6 = ’ ’; // blank

int i6 = (int) c6; // ASCII value

Console.WriteLine("i6 = " + i6); // 32

} // end Main

}

2.4. ARITHMETIC OPERATIONS 13

2.4 Arithmetic Operations

The arithmetic operations are

++, --, +, -, *, /, %

where ++ is the increment by 1 and -- is the decrement by −1. The operation %

provides the remainder in integer division.

Note that we have integer division (for example 17/4 = 4) and floating point division

depending on the data types.

// arithmetic.cs

using System;

class Arithmetic

{

public static void Main()

{

byte c = 255;

c++;

Console.WriteLine(c);

sbyte d = -125; // signed byte

d--;

Console.WriteLine(d);

int i = -100000; // signed int

int j = 15002;

int k = i + j;

Console.WriteLine(k);

long m = -234567899; // signed long

long n = 345;

long p = m*n;

Console.WriteLine(p);

int r1 = 27;

int r2 = 5;

int r3 = r1/r2; // integer division

Console.WriteLine("r3 = " + r3);

int r4 = r1%r2; // remainder

Console.WriteLine("r4 = " + r4);

float f1 = (float) 3.145; // type conversion

float f2 = (float) 2.81;

14 CHAPTER 2. CSHARP BASICS

float f3 = f1*f2;

Console.WriteLine(f3);

double d1 = 3.14159;

double d2 = 4.5;

double d3 = d1/d2;

Console.WriteLine(d3);

decimal p1 = (decimal) 2.89124357865678; // type conversion

decimal p2 = (decimal) 3.14159; // type conversion

decimal p3 = p1 + p2;

Console.WriteLine(p3);

}

}

2.5 Control Statements

Control statements control the program flow. For example, selection statements

such as if ... else and switch use certain criteria to select a course of certain

action within the program.

// myIf.cs

using System;

class myIf

{

public static void Main()

{

int i;

Console.WriteLine("Enter integer: ");

string line = Console.ReadLine();

i = System.Convert.ToInt32(line); // convert string of digits to int

if(i > 5) // if true do the next command else skip it

Console.WriteLine("The number is larger than 5");

else

Console.WriteLine("The number is smaller than 5 or equal to 5");

} // end Main

}

The for loop applied to a one-dimensional array.

// forloop.cs

using System;

2.5. CONTROL STATEMENTS 15

class forloop

{

public static void Main()

{

double[] numbers = { 1.1, 2.2, 3.3, 4.4 };

int i = 0;

double sum = 0.0;

for(i=0;i

{

sum += numbers[i]; // sum = sum + numbers[i];

}

Console.WriteLine("sum = {0}",sum);

int[] x = new int[3]; // declare array and allocate memory

x[0] = 4; x[1] = 3; x[2] = 7;

int intsum = 0;

for(i=0;i

{

intsum += x[i]; // shortcut for intsum = intsum + x[i];

}

Console.WriteLine(intsum);

} // end Main

}

Another example for the for loop applied to numbers read from the keyboard. Note

that ! is the logical NOT and ToInt32(string) converts a string of digits to an

integer.

// forloop1.cs

using System;

class ForLoop

{

public static void Main()

{

int sum = 0; // initialize sum to 0

String line;

for(line=Console.In.ReadLine();line!="";line=Console.In.ReadLine())

{

sum += System.Convert.ToInt32(line);

} // end for loop

16 CHAPTER 2. CSHARP BASICS

Console.WriteLine(sum.ToString() + "\n");

} // end Main

}

The foreach loop can be applied to an array of strings. We count how often the

string "otto" is in the array of strings.

// foreachloop.cs

using System;

class foreachloop

{

public static void Main()

{

string[] namelist = { "willi","otto","carl","john","otto" };

int count = 0;

string n = "otto";

foreach(string name in namelist) // keyword in

{

if(name==n) // compare strings for equality case sensitive

{

count++;

}

} // end foreach

Console.WriteLine("count = {0}",count);

} // end Main

}

The while loop

// whileloop.cs

using System;

class whileloop

{

public static void Main()

{

int[] numbers = { 1, 2, 3, 4 };

int i = 0;

int sum = 0;

while(i < numbers.Length)

{

2.5. CONTROL STATEMENTS 17

sum += numbers[i];

i++;

}

Console.WriteLine("sum = {0}",sum);

} // end Main

}

The do-while loop applied to an array of floating point numbers.

// dowhileloop.cs

using System;

class whileloop

{

public static void Main()

{

double[] numbers = { 1.1, 2.3, 3.5, 4.5 };

int i = 0;

double sum = 0.0;

do

{

sum += numbers[i];

i++;

}

while(i < numbers.Length);

Console.WriteLine("sum = {0}",sum);

} // end Main

}

If one has a large decision tree and all the decisions depend on the value of the same

variable we use a switch statement instead of a series of if ... else constructions.

The switch statement transfers control to one of several case-labeled statements,

depending on the value of the switch expression. Note that if the break is omitted,

execution will continue over the remaining statements in the switch block. The

break statement can also be used to break out of an iteration loop.

// switch.cs

using System;

class Myswitch

{

public static void Main()

{

18 CHAPTER 2. CSHARP BASICS

string st = "bella";

for(int i=0;i

{

char c = st[i];

switch(c)

{

case ’a’: Console.WriteLine("character is a ’a’ ");

break;

case ’b’: Console.WriteLine("character is a ’b’ ");

break;

default: Console.WriteLine("character is not an ’a’ or a ’b’ ");

break;

}

} // end for loop

int[] numbers = { 3,4,6,1,4,-3,1,6};

for(int j=0;j

{

switch(numbers[j])

{

case 4: Console.WriteLine("number at position {0} is 4",j);

break;

case 6: Console.WriteLine("number at position {0} is 6",j);

break;

default: Console.WriteLine("number at position {0} is not 4 or 6",j);

break;

} // end switch

} // end for loop

} // end Main

}

2.6 Logical Operations

The logical operators in CSharp, C, C++ and Java are

&& logical AND



logical OR

! logical NOT

// logical.cs

using System;

class MyLogica

2.7. POINTERS 19

{

public static void Main()

{

int j;

Console.WriteLine(" Enter an integer: ");

string line = Console.ReadLine();

j = System.Convert.ToInt32(line);

if((j%2 == 0) && (j < 10))

Console.WriteLine("The integer is even and smaller than 10");

else

Console.WriteLine("The integer is either odd or larger than 10 or both");

Console.WriteLine();

int k;

Console.WriteLine("Enter an integer: ");

line = Console.ReadLine();

k = System.Convert.ToInt32(line);

if((k > 0)

(k < 0))

Console.WriteLine("The integer is nonzero");

else

Console.WriteLine("The integer is zero");

Console.WriteLine();

int n;

Console.WriteLine("Enter an integer: ");

line = Console.ReadLine();

n = System.Convert.ToInt32(line);

if(n == 0) Console.WriteLine("The integer is zero");

else

Console.WriteLine("The integer is nonzero");

}

}

2.7 Pointers

A pointer is a data type whose value refers directly to (”points to”) another value

stored elsewhere in the computer memory using its address. Thus the pointer has

an address and contains (as value) an address. Obtaining the value that a pointer

referes to is called dereferencing. The dereference operator is *. Pointers in CSharp

20 CHAPTER 2. CSHARP BASICS

must be declared unsafe.

// Pointers1.cs

using System;

class Pointers

{

public static unsafe void Main()

{

int i = 15;

int* p = &i; // declare pointer and assignment to address of i

int j = 15;

int* q = &j;

bool b1 = (i==j);

Console.WriteLine("b1 = " + b1); // true

bool b2 = (p==q);

Console.WriteLine("b2 = " + b2); // false

// dereferencing pointers

int r = *q;

Console.WriteLine("r = " + r); // 15

}

}

We are using pointer to pass by reference (see section 2.10).

2.8 Recursion

Recursion plays a central role in computer science. A recursive function is one whose

definition includes a call to itself. A recursion needs a stopping condition. We use

recursion to find the Fibonacci numbers.

// recursion.cs

using System;

class recur

{

public static ulong fib(ulong n)

{

if(n==0) return 0;

if(n==1) return 1;

return fib(n-1) + fib(n-2);

} // end fib

2.9. JUMP STATEMENTS 21

public static void Main()

{

ulong n = 10;

ulong result = fib(n);

Console.WriteLine("Result = {0}",result);

} // end Main

}

2.9 Jump Statements

C# also has an goto for jumping to labels. We use the goto to jump to the labels

L1, L2, L3, L4 if a condition is met.

// mygoto.cs

using System;

class Mygoto

{

public static void Main()

{

Random r = new Random(51);

L3:

int a = r.Next(100);

int b = r.Next(100);

int result;

L1:

Console.WriteLine("{0} + {1} =",a,b);

string s = Console.ReadLine();

result = Convert.ToInt32(s);

if(result == (a+b))

goto L2;

Console.WriteLine("sorry you are not correct: try again");

goto L1;

L2:

Console.WriteLine("congratulations you are correct");

Console.WriteLine("Want to add again: Press y for yes and n for no: ");

string t = Console.ReadLine();

if(t == "y") goto L3;

if(t == "n")

{

Console.WriteLine("bye, see you next time around");

goto L4;

22 CHAPTER 2. CSHARP BASICS

}

L4:

int e = 0;

}

}

The method Exit() is used for program termination. It is part of the class Environment.

// password.cs

using System;

class password

{

public static void Main()

{

string password = "XYA";

int i,j,k;

for(i=65;i<91;i++)

{

for(j=65;j<91;j++)

{

for(k=65;k<91;k++)

{

char c1 = (char) i;

char c2 = (char) j;

char c3 = (char) k;

char[] data = { c1,c2,c3 };

string s = new string(data); // converting array of char to string

bool found = password.Equals(s);

if(found == true)

{

Console.WriteLine("Password = {0}",s);

Environment.Exit(0);

}

}

}

}

}

}

2.10 Pass by Value, Pass by Reference

Arguments to functions can be passed either by value or by reference. When an argument

is passed by value, a copy of the argument is produced, and the associated

2.10. PASS BY VALUE, PASS BY REFERENCE 23

parameter is the same as a local variable for the function. This means, changes to

the parameter variable will have no effect on the original argument value. Functions

that receive variables as parameters get local copies of those variables, not the originals.

The alternative, pass by reference, is indicated by the presence of the keyword

ref in the argument list. When arguments are passed by reference, the parameter

variable is an alias for the argument value. Thus, change in the parameter also alter

the original argument. In C# we can also use pointers and the dereference operator

to pass by reference. Thus functions that receive pointers to variables gain access

to the original variables associated with the pointers.

In the next program we pass by value.

// Pitfall.cs

using System;

public class Pitfall

{

public static void add(int i)

{

int n = i + i;

i = n;

Console.WriteLine("i inside function add = " + i); // 20

} // end add

public static void Main()

{

int i = 10;

add(i);

Console.WriteLine("i in Main = " + i); // 10

}

}

Note that without static in method add(int): error message: An object reference

is required for the nonstatic method Pitfall.add(int).

In the next program we use pointers to pass by reference. We rotate integer numbers.

// pointers2.cs

using System;

public class Rotate

{

public static unsafe void rot(int* p,int* q,int* r)

24 CHAPTER 2. CSHARP BASICS

{

int t = *r;

*r = *p; *p = *q; *q = t;

}

public static unsafe void Main(string[] args)

{

int a = 10; int b = 12; int c = 17;

rot(&a,&b,&c);

Console.WriteLine("a = {0} and b = {1} and c = {2}",a,b,c);

} // end main

}

In the following program we use the keyword ref to pass by reference. We rotate

three integers.

// references.cs

using System;

public class Rotate

{

public static void rot(ref int p,ref int q,ref int r)

{

int t = r;

r = p; p = q; q = t;

}

public static void Main()

{

int a = 10; int b = 12; int c = 17;

rot(ref a,ref b,ref c);

Console.WriteLine("a = {0} and b = {1} and c = {2}",a,b,c);

} // end Main

}

In the following program we pass the first argument by reference and the second by

value.

// passing.cs

using System;

public class Passing

{

static void change(ref string sa,string sb)

2.10. PASS BY VALUE, PASS BY REFERENCE 25

{

sa = "yyy";

sb = "222";

}

public static void Main()

{

string s1 = "xxx";

string s2 = "111";

change(ref s1,s2);

Console.Write("s1 = {0} and s2 = {1}",s1,s2); // => s1 = yyy s2 = 111

}

}

The out keyword explicitely speciefies that a variable should be passed by reference

to a method, and set in that method. A variable using this keyword must not be

initialized before the method call.

// Divide.cs

using System;

class Divider

{

public static int Divide1(int dividend,int divisor,out int r)

{

int quot = dividend/divisor;

r = dividend - quot*divisor;

return quot;

} // end Divide1

public static void Divide2(int dividend,int divisor,out int quot,out int r)

{

quot = dividend/divisor;

r = dividend - quot*divisor;

} // end Divide2

public static void Main()

{

int r;

int q = Divide1(123,14,out r);

Console.WriteLine("Quotient = {0} and Remainder = {1}",q,r);

int s;

int t;

26 CHAPTER 2. CSHARP BASICS

Divide2(145,3,out s,out t);

Console.WriteLine("Quotient = {0} and Remainder = {1}",s,t);

} // end Main

}

2.11 Arrays

An array is a data structure that contains a number of variables. These are accessed

through computed indices. C# supports one-dimensional arrays, multidimensional

arrays (rectangular arrays) and arrays of arrays (jagged arrays). As C, C++ and

Java C# arrays are zero indexed. This means the array indexes start as zero. When

declaring arrays, the square bracket [] must come after the type, not the identifiers,

for example int[] table. The size of the array is not part of its type as it is in the

C language. Thus

int[] numbers = new int[20];

We can initialise arrays very simply:

int[] numbers = {0, 1, 2, 3, 5};

This is identical to the complete initialisation statement:

int[] numbers = new int[] {0, 1, 2, 3, 5};

In C# arrays are actually objects. System.Array is the abstract base type of all

array types. The class Array contains methods for sorting and searching.

// myArray.cs

using System;

class myArray

{

public static void Main()

{

int[] numbers = { 4, 12345, 890, 23456789 };

int prod = numbers[2]*numbers[0];

Console.Write("prod = " + prod);

Console.Write("\n");

int numb = Array.BinarySearch(numbers,4);

Console.Write("numb = " + numb);

Console.Write("\n");

double[] d = new double[3];

d[0] = 1.1; d[1] = 3.4; d[2] = 8.9;

int dpos = Array.BinarySearch(d,8.9);

Console.Write("dpos = " + dpos);

2.11. ARRAYS 27

Console.Write("\n");

string[] slist = { "otto", "uli", "carl", "marius", "jacob" };

int pos1 = Array.BinarySearch(slist,"carl");

Console.Write("pos1 = {0}",pos1);

Console.WriteLine();

Array.Sort(slist); // sorting the array

int pos2 = Array.BinarySearch(slist,"carl");

Console.Write("pos2 = {0}",pos2);

Console.WriteLine();

for(int j=0;j

{

Console.WriteLine("{0} {1}",j,slist[j]);

}

}

}

To create multidimensional arrays the array initializer must have as many levels of

nesting as there are dimensions in the array. Thus:

int[,] numbers = {{0, 2}, {4, 6}, {8, 10}, {12, 17}, {16, 18}};

The outermost nesting level corresponds to the leftmost dimension. The innermost

nesting level corresponds to the rightmost dimension. The length of each dimension

of the array is determined by the number of elements at the corresponding nesting

level in the array initializer. Thus the example above creates a two-dimensional

array with a length of five for the leftmost dimension and a length of two for the

rightmost dimension. For example

int[,] numbers = new int[5,2];

and initialises the array with:

numbers[0,0] = 0; numbers[0,1] = 2;

numbers[1,0] = 4; numbers[1,1] = 6;

numbers[2,0] = 8; numbers[2,1] = 10;

numbers[3,0] = 12; numbers[3,1] = 14;

numbers[4,0] = 16; numbers[4,1] = 18;

We can also create jagged arrays, which are arrays of arrays. The element arrays do

not all have to be the same.

28 CHAPTER 2. CSHARP BASICS

// twodim.cs

using System;

public class TwoDim

{

public static void Main()

{

int[][] matrix = new int[2][]; // rows

matrix[0] = new int[2]; // columns

matrix[1] = new int[2]; // columns

matrix[0][0] = 2; matrix[0][0] = 4;

matrix[1][0] = 7; matrix[1][1] = 3;

int i = 1;

Console.WriteLine("matrix[" + i + "][" + i + "] = " + matrix[i][i]);

double[,] myarray;

myarray = new double[2,3];

myarray[0,0] = 3.1;

myarray[0,1] = 4.7;

myarray[0,2] = 3.3;

myarray[1,0] = 2.7;

myarray[1,1] = 1.1;

myarray[1,2] = 7.3;

double r = myarray[0,1]*myarray[1,2];

Console.WriteLine("r = " + r);

} // end Main

}

2.12 Bitwise Operations

Consider the integer number 17 (base 10, i.e. 17 = 1 · 101+7 · 100. It can be written

in binary as

17 = 1 · 24 + 0 · 23 + 0 · 22 + 0 · 21 + 1 · 20 .

Thus the binary representation of 17 would be 10001. If 17 is considered as data

type int (32 bits) we have the binary representation

00000000000000000000000000010001

The bitwise operation in CSharp, C, C++ and Java are:

& AND


OR (inclusive OR)

^ XOR (exclusive OR)

~ NOT

2.13. SHIFT OPERATION 29

// bitwise.cs

using System;

class MylBitwise

{

public static void Main()

{

int r3 = 4; int r4 = 5;

int r5 = r3 & r4; // bitwise AND

Console.WriteLine("Binary AND of 4 and 5 gives {0}",r5);

int r6 = 7; int r7 = 11;

int r8 = r6
r7; // bitwise OR

Console.WriteLine("Binary OR 7 and 11 gives {0}",r8);

int r9 = r6 ^ r7; //bitwise XOR

Console.WriteLine("Binary XOR of 7 and 11 gives {0}",r9);

int x = 125;

int r10 = x^x;

Console.WriteLine("Binary XOR of 125 with itself gives {0}",r10);

int r11 = ~r9;

Console.WriteLine("Binary NOT of r9 gives {0}",r11);

int r12 = 4;

int r13 = ~r12; // one’s complement

int r14 = ++r13;

Console.WriteLine("two’s complement of 4 {0}",r14);

}

}

2.13 Shift Operation

We can use shift operation for fast integer multiplication by 2, 4, 8, ... and fast

integer division by 2, 4, 8, .... The shift operations are << and >>.

// MyShift.cs

using System;

class Shift

{

public static void Main()

30 CHAPTER 2. CSHARP BASICS

{

int i = 17; // 17 in binary 10001

int j = i >> 1; // integer divison by 2

Console.WriteLine("j = " + j); // => 8

int k = i >> 2; // integer divison by 4

Console.WriteLine("k = " + k); // => 4

int m = 9;

int n = m << 1; // multiplication by 2

Console.WriteLine("n = " + n); // => 18

int p = m << 2; // multiplication by 4

Console.WriteLine("p = " + p); // => 36

}

}

2.14 Commmand-Line Arguments

C# enables us to access command-line arguments by supplying and using the following

parameters in function Main

Main(string[] args)

Basically a C# program consists of a class with a static member method (class

function) called Main. When the C# compiler (csc.exe) compiles a C# program

it marks the Main method as the entrypoint in the generated IL code. The Main

method may accept an array of string as its arguments (though this is optional). This

array will always contain the command line arguments passed to the program by its

user. We start counting from zero. The following program shows an application.

// CommandLine.cs

using System;

class CommandLine

{

public static void Main(string[] args)

{

Console.WriteLine("Hello{0}",args[0]);

Comsole.WriteLine("Goodbye.");

}

}

We run the program, for example

CommandLine World

2.15. BOXING AND UNBOXING TYPES 31

2.15 Boxing and UnBoxing Types

Boxing refers to converting a value type to an object type, and unboxing refers to

the opposite. Boxing is carried out implicitly in C#, whereas we have to use type

casting to unbox to an appropiate data type. For example

int i;

Console.WriteLine("i={0}",i);

The WriteLine() method requires an object, so in the above statement integer i

is implicitly boxed to an object and passed to the WriteLine method. An example

for unboxing is

int i;

object obj = i; // boxing is implicit

int j;

j = (int) obj; // to unbox we use type cast

Typically unboxing is done in a try block. If the object being unboxed is null

or if the unboxing cannot succeed because the object is of a different type, an

InvalidCastException is thrown.

2.16 Delegates

A delegate essentially creates a name for a the specific type/signature of a method.

Delegates are type safe function pointers. One must first declare a delegate.

// delegates.cs

using System;

// declare delegate with the signature of the

// encapsulated method

delegate void MyDelegate(string m,int a,int b);

class Application

{

public static void Main()

{

MyDelegate md = new MyDelegate(FirstMethod);

md += new MyDelegate(SecondMethod);

md("message A",4,5);

md("message B",7,11);

} // end Main

32 CHAPTER 2. CSHARP BASICS

static void FirstMethod(string s1,int x1,int y1)

{

Console.WriteLine("1st method: " + s1);

int sum1 = x1 + y1;

Console.WriteLine("sum1 = " + sum1);

}

static void SecondMethod(string s2,int x2,int y2)

{

Console.WriteLine("2st method: " + s2);

int sum2 = x2 + y2;

Console.WriteLine("sum2 = " + sum2);

}

}

The output is

1st method message A

sum1 = 9

2st method message A

sum2 = 9

1st method message B

sum1 = 18

2st method message B

sum2 = 18

2.17 Types

The typeof command is an operator. It resolves at compile time and operates over

a type. To check whether an object is compatible to a specific type is to apply the

is keyword.

// myTypeof.cs

using System;

using System.Text;

class myTypeof

{

public static void Main()

{

double b = 3.14;

string s = "xxx";

StringBuilder sb = new StringBuilder("123456789");

2.18. REFLECTION 33

Type at = typeof(double);

Console.WriteLine("at = {0}",at);

Type st = typeof(string);

Console.WriteLine("st = {0}",st);

Type sbt = typeof(StringBuilder);

Console.WriteLine("sbt = {0}",sbt);

if(s is string) Console.WriteLine(at);

if(s is StringBuilder) Console.Write("s is of the StringBuilder");

else Console.Write("s is not of StringBuilder");

if(b is int) Console.WriteLine("b is int");

}

}

2.18 Reflection

Exposing and utilizing types at runtime is called reflection. The type of an object is

stored as an instance of System.Type class the reference to which can be obtained

using one of the following methods.

1. From the declaration type: If declaration AType var is legal then System.Type

representing AType can be obtained using the typeof operator as:

Type t = typeof(AType);

2. From an instance: Type of an instance obj can be obtained using GetType

method defined in System.Object as

Type t = obj.GetType();

3. From the type name within current assembly: System.Type offers a static method

called GetType to obtain a Type from a fully qualified name of the type. The name

will be searched in the current assembly

Type t = Type.GetType("FullyQualifiedTypeName");

4. From the type name within any assembly: First load the assembly and obtain a

reference to it. This reference can be used to obtain the Type with a given name:

using System.Reflection;

Assembly asm = Assembly.LoadFrom("AssemblyName");

Type t = asm.GetType("FullyQualifiedTypeName");

The program showtypes.cs displays all the Types defined in an assembly whose

name is passed in as first command line argument:

34 CHAPTER 2. CSHARP BASICS

// showtypes.cs

using System;

using System.Reflection;

class ShowTypes

{

public static void Main(string[] args)

{

Assembly asm = Assembly.LoadFrom(args[0]);

Type[] types = asm.GetTypes();

foreach(Type t in types) Console.WriteLine(t);

}

}

We would run the program as, for example

showtypes datatypes.exe

Pass complete path to any .NET exe or dll to see the types declared in it.

The next program showmembers.cs takes the assembly name and type name as

its command line arguments and displays all the members defined in that type of

assembly.

// showmembers.cs

using System;

using System.Reflection;

class ShowMembers

{

public static void Main(string[] args)

{

Assembly asm = Assembly.LoadFrom(args[0]);

Type t = asm.GetType(args[1]);

MemberInfo[] members = t.GetMembers();

foreach(MemberInfo m in members) Console.WriteLine(m);

}

}

2.19 Generics

C# Generics are similar to C++ Templates. They were introduced in version 2.0

of the C# language and the common language runtime (CLR). Generics introduce

2.19. GENERICS 35

to the .NET Framework the concept of type parameters. This makes it possible to

design classes and methods that defer the specification of one or more types until the

class or method is declared and instantiated. The .NET Framework class library

contains several new generic collection classes in the System.Collections.Generic

namespace.

Some of the classes in

System.Collection.Generic

are:

Dictionary represents a collection of keys

and values

LinkedList represents a doubly linked list

List represents a strongly typed list

of objects

Queue represents a firs-in, first out

collection of objects

SortedDictionary represents a collection of key/value

pairs that are sorted on the key

Stack represents a varaible size last-in

first-out collection of instances

The first example shows an application of Stack. It shows how the Push and

Pop methods are used.

// MyStack0.cs

using System;

using System.Collections.Generic;

class MyStack0

{

public static void Main()

{

Stack stackint = new Stack();

stackint.Push(5);

stackint.Push(8);

int i = stackint.Pop();

Console.WriteLine("i = " + i); // 8

stackint.Push(11);

bool b0 = stackint.Contains(8); // false

Console.WriteLine("b0 = " + b0);

bool b1 = stackint.Contains(11);

Console.WriteLine("b1 = " + b1);

36 CHAPTER 2. CSHARP BASICS

int j = stackint.Peek(); // Peek does not Pop

Console.WriteLine("j = " + j); // 11

Stack stackstring = new Stack();

stackstring.Push("Abba");

stackstring.Push("Baab");

int r = stackstring.Count;

Console.WriteLine("r = " + r); // 2

} // end Main

}

The next program shows an application of List. The method Add will add an

element to the List.

// permutation.cs

using System;

using System.Collections;

using System.Collections.Generic;

public class Test

{

private static void Swap(ref char a,ref char b)

{

if(a==b) return;

a ^= b; b ^= a; a ^= b; // using XOR operation for swapping

}

private static List _permutations = new List();

// Recursive Function

private static void Permute(char[] list,int k,int m)

{

if(k==m)

{

_permutations.Add(new string(list));

}

else

{

for(int i=k;i<=m;i++)

{

Swap(ref list[k],ref list[i]);

Permute(list,k+1,m);

Swap(ref list[k],ref list[i]);

}

}

2.19. GENERICS 37

}

[STAThread]

static void Main(string[] args)

{

try

{

string str = "ola";

char[] list = str.ToCharArray();

Permute(list,0,list.Length-1);

foreach(string perm in _permutations)

{

Console.WriteLine(perm);

}

}

catch (Exception ex)

{

Console.WriteLine("Error: " + ex.Message);

}

} // end Main

}

The next program shows an application of Dictionary.

// Dictionary1.cs

using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

public class Test

{

private static Dictionary _dict = new Dictionary();

private static string Substitution(string str)

{

StringBuilder sb = new StringBuilder();

for(int i=0;i

{

if(Char.IsWhiteSpace(str[i])) sb.Append(str[i]);

else sb.Append(_dict[str[i]]);

}

return sb.ToString();

}

38 CHAPTER 2. CSHARP BASICS

[STAThread]

static void Main(string[] args)

{

try

{

// Build the dictionary

// original alphabet A:

// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

string a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// substitution alphabet B:

// D E F G H I J K L M N O P Q R S T U V W X Y Z A B C

string b = "DEFGHIJKLMNOPQRSTUVWXYZABC";

for(int i=0;i

{

_dict[a[i]] = b[i];

}

string res = Substitution("PLEASE CONFIRM RECEIPT");

// SOHDVH FRQILUP UHFHLSW

Console.WriteLine("Result=" + res);

}

catch (Exception ex)

{

Console.WriteLine("Error: " + ex.Message);

}

}

}

An application of the SortedDictionary is given in the next program.

The method Add will add a TKey, TValue element to the SortedDictionary.

The method Count will find the number of TKey, TValue pairs in the SortedDictionary.

// MyDictionary.cs

using System;

using System.Collections.Generic;

class MyDictionary

{

// declare key dictionary object

public static SortedDictionary items =

new SortedDictionary();

static void Main(string[] args)

{

2.19. GENERICS 39

items.Add(1,"willi");

items.Add(2,"ola");

items.Add(7,"bulli");

bool b1 = items.ContainsKey(7);

Console.WriteLine("b1 = " + b1);

bool b2 = items.ContainsValue("ola");

Console.WriteLine("b2 = " + b2);

int no = items.Count;

Console.WriteLine("no = " + no);

ICollection k = items.Keys;

foreach(int i in k)

Console.WriteLine("{0},name: {1:k}",i,items[i]);

}

}

We can also write our own generics. An example for the stack is given below. It

shows how the Pop and Push methods are implemented and used

// MyStack1.cs

using System;

using System.Collections.Generic;

class MyStack

{

int MaxStack = 20;

T[] StackArray;

int StackPointer = 0;

public MyStack() { StackArray = new T[MaxStack]; }

public void Push(T x)

{

if(StackPointer < MaxStack) StackArray[StackPointer++] = x;

}

public T Pop()

{

return (StackPointer > 0) ? StackArray[--StackPointer] : StackArray[0];

}

40 CHAPTER 2. CSHARP BASICS

public void Print()

{

for(int i=StackPointer-1;i>=0;i--)

Console.WriteLine("Value: {0}",StackArray[i]);

}

}

public class MainClass

{

public static void Main()

{

MyStack stackint = new MyStack();

stackint.Push(5);

stackint.Push(8);

int i = stackint.Pop();

stackint.Print(); // 5

MyStack stackstring = new MyStack();

stackstring.Push("Abba");

stackstring.Push("Baab");

stackstring.Print(); // Baab Abba

} // end Main

}

2.20 Indexers

An indexer is a member that enables an object to be indexed in the same way

as an array (one or higher dimensional). Indexers have the same this and have

a set of arguments in rectangular brackets. Two examples are given below for a

one-dimensional array and a two-dimensional array.

// indexers1.cs

using System;

public class Number

{

double[] Numbers;

public double this[int i]

{

get { return Numbers[i]; }

}

2.20. INDEXERS 41

public Number() // default constructor

{

Numbers = new double[3];

Numbers[0] = 1.23;

Numbers[1] = 3.14;

Numbers[2] = 2.83;

}

} // end class Number

public class MyMain

{

public static void Main()

{

Number nbr = new Number();

for(int i=0;i<3;i++)

Console.WriteLine("Number {0}:{1}", 1+1,nbr[i]);

Console.WriteLine();

} // end Main

} // end class MyMain

// indexers2.cs

using System;

public class Number

{

double[,] Numbers;

public double this[int i,int j]

{ get { return Numbers[i,j]; } }

public Number()

{

Numbers=new double[3,3];

Numbers[0,0]=1.23;

Numbers[0,1]=3.14;

Numbers[0,2]=2.83;

Numbers[1,0]=4.56;

Numbers[1,1]=7.54;

Numbers[1,2]=9.23;

Numbers[2,0]=8.34;

Numbers[2,1]=7.43;

Numbers[2,2]=5.24;

}

}

42 CHAPTER 2. CSHARP BASICS

public class MyMain

{

static void Main()

{

Number nbr = new Number();

for(int i=0;i<3;i++)

{

for(int j=0;j<3;j++)

Console.WriteLine("Number {0},{1}: {2}",i,j,nbr[i,j]);

}

Console.WriteLine();

} // end Main

}

No comments:

Post a Comment