Programming in CSharp

by Willi-Hans Steeb International School for Scientific Computing and E.J. Dembskey Version: 2008-08-28 email addresses of the authors: steeb_wh@yahoo.com steebwilli@gmail.com whsteeb@uj.ac.za evan.dembskey@gmail.com demskeye@tut.ac.za

Contents
1 Introduction 2 CSharp Basics 2.1 Introduction . . . . . . . . . . . . 2.2 Basic Data Types . . . . . . . . . 2.3 ASCII Table . . . . . . . . . . . . 2.4 Arithmetic Operations . . . . . . 2.5 Control Statements . . . . . . . . 2.6 Logical Operations . . . . . . . . 2.7 Pointers . . . . . . . . . . . . . . 2.8 Recursion . . . . . . . . . . . . . 2.9 Jump Statements . . . . . . . . . 2.10 Pass by Value, Pass by Reference 2.11 Arrays . . . . . . . . . . . . . . . 2.12 Bitwise Operations . . . . . . . . 2.13 Shift Operation . . . . . . . . . . 2.14 Commmand-Line Arguments . . . 2.15 Boxing and UnBoxing Types . . . 2.16 Delegates . . . . . . . . . . . . . 2.17 Types . . . . . . . . . . . . . . . 2.18 Reflection . . . . . . . . . . . . . 2.19 Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 6 6 8 10 11 13 17 18 19 20 21 24 27 28 29 29 30 31 32 33

3 String and StringBuilder 36 3.1 String Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.2 Convert Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.3 StringBuilder Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4 Built-in Classes 4.1 DateTime Class . . . . 4.2 Array Class . . . . . . 4.3 ArrayList Class . . . . 4.4 ListDictionary Class . 4.5 Class IEnumerator . . 4.6 Mathematics Class and . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Random Class i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 41 42 43 44 45 45

4.7 4.8 4.9

Point Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Class BitArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Object Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 55 60 62 66 67 68 69 74 74 74 76 79 81 83 86 86 89 91 93 94 100 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 104 105 105 106 107 109 110 111 113 115 116 117 122 123 124

5 Object-Oriented Programming 5.1 Write your own class . . . . . 5.2 Override Methods . . . . . . . 5.3 Inheritance . . . . . . . . . . 5.4 Overloading Methods . . . . . 5.5 Operator Overloading . . . . . 5.6 Structures . . . . . . . . . . . 5.7 Delegates . . . . . . . . . . .

6 Streams and File Manipulations 6.1 Introduction . . . . . . . . . . . 6.2 Binary File Manipulations . . . 6.3 Text File Manipulation . . . . . 6.4 Byte by Byte Manipulation . . 6.5 Object Serialization . . . . . . . 6.6 XML Documents . . . . . . . . 7 Graphics 7.1 Drawing Methods . . . . . 7.2 Color Class . . . . . . . . 7.3 Button and EventHandler 7.4 Displaying Images . . . . . 7.5 Overriding OnPaint . . . . 8 Events . . . . . . . . . . . . . . .

9 Processes and Threads 9.1 Processes . . . . . . . . . . . . . . 9.2 Threads . . . . . . . . . . . . . . . 9.2.1 Introduction . . . . . . . . . 9.2.2 Background Thread . . . . . 9.2.3 Sleep Method . . . . . . . . 9.2.4 Join Methods . . . . . . . . 9.3 Monitor . . . . . . . . . . . . . . . 9.4 Synchronization . . . . . . . . . . . 9.5 Deadlock . . . . . . . . . . . . . . . 9.6 Interlocked Class . . . . . . . . . . 9.7 Thread Pooling . . . . . . . . . . . 9.8 Threading in Windows Forms . . . 9.9 Asynchronous Programming Model 9.10 Timers . . . . . . . . . . . . . . . . 9.11 Interrupt and Abort . . . . . . . . ii

. . . . . . . . .1 Introduction . . . . . . . . . . . . . . . 128 . . . . . . . 152 . 10. . . . . . . . .2 State Management . . . . . . . . . . . . . . . . . . . . . . 135 11 Remoting 137 11. .3 Page Load . . . . .1 Introduction . . . . . . . . . . . 153 155 155 iii . . . .NET 13. . . . . . . .1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . 146 12. . Bibliography Index 152 . . . . . 10. . . . . . . . . . . . . . . . . . . . 147 13 ASP. .10 Sockets Programming 10. . . . . . .2 Transmission Control Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 User Datagram Protocol . .1 Introduction . . 127 . . . . . . . 152 . 137 12 Accessing Databases 146 12. . . 13. . . . . . . 13. . . . . . . . . . . . . . . . . . .2 Examples . . . . . . . . . . . . .

za steeb_wh@yahoo.ac.com The web sites of the author is: http://issc. this book can be extended. If you have comments or suggestions. we would be pleased to have them.ac.za iv . Without doubt.uj. The email addresses of the author are: whsteeb@uj.Preface The book gives a collection of C# programs.

means protected or internal Classes can be marked as public or internal.accessible to code in same assembly protected internal .NET framework. CSharp is standardised as ECMA-334 by ECMA International and as ISO/IEC 23270 by ISO/IEC. etc) are magic and do not interoperate with objects. 1 .accessible to containing or derived classes internal .NET). methods. In C++ and Java primitive date types (int.accessible to containing class protected . By default classes are private. Collections work for all types. double. The accessibility options are: public . CSharp is the first component oriented language in the C/C++ family. Component concepts are first class: Properties. CSharp has a great set of tools for the object oriented programmer. In CSharp. private is the default accessibility. In Smalltalk and Lisp primitive types are objects.accessible to all private . for example decimal. The .Chapter 1 Introduction CSharp is designed for the . events Design-time and run-time attributes integrated documentation using XML CSharp can be embedded in web pages (ASP.NET framework is object oriented. CSharp unifies this with no performance cost. but at great performance cost. CSharp also adds new primitive data types.

Our types can implement interfaces. CSharp has built in support for events. Comments using such syntax are called documentation comments. A single type can register interest in any number of events. . We can implement simpler constructors in terms of more complex ones with the this keyword. INTRODUCTION Fields: The state of an object or type Methods: Constructors. We can indicate which base constructor to call by using the base keyword.per type data and methods (use the static keyword). More than one type can register interest in a single event. or begin with an underscore. We use the static keyword to indicate a type constructor. methods etc. In a derived class. All types in the system are derived from class object. CSharp supports interfaces using the interface keyword. by the programmer are referred to as identifiers. The following is a list of keywords. we can convert to an integer int i = (int) c. An identifier has to: begin with a letter.2 Type members in CSharp are: CHAPTER 1.per object data and methods (default) Static . Interfaces can contain methods but no fields with properties and events included. Type constructors are used to initialize static fields for a type. Keywords are reserved identifiers that hold a special meaning to the CSharp compiler. The class object contains the functions string ToString() and bool Equals() which should be overriden when we write our own class. It cannot be the same as built-in keywords. Functions. Properties (smart fields) Members come in two basic forms Instance . This is useful for dealing with objects in an event driven operating system. We can use the same name as a keyword identifier as long as we prefix the name with an @ symbol. for example if char c = ’a’. CSharp also provides type conversion. C# provides a mechanism for programmers to document their code using a special comment syntax that contains XML text. an override method is marked with the override keyword. Identifiers are case-sensitive. The names given to variables. via the ASCII table. We use the virtual keyword to make a method virtual. The XML generation tool is called the documentation generator. This generator could be the C# compiler itself. Constructors are used to initialize fields. We must implement all methods.

They aid in conditional compilation. these directives cannot be used to create macros. Unlike with C and C++. do not use the following for a class name: System Collections Forms UI There are a number of preprocessor directives available.3 abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while The following is a list of contextual keywords. These provide a specific meaning in the code. Some have meanings in two or more contexts. #if #elif #else #endif . While the compiler lacks a separate preprocessor. from get group into join let orderby partial (type) partial (method) select set value var where (generic type constraint) where (query clause) yield Do avoid using class names duplicated in heavily used namespaces. for example. partial and where. directives are processed as if there was one. but are not reserved words. For example.

1.1 for an overview of the stack. When the .0. 2. Windows Communication Foundation (WCF).NET. A benefit of the CLR is that it provides these execution services to all .5 adds several capabilities to the stack: the Windows Presentation Foundation (WPF). The runtime.exe file does not contain directly executable instructions.NET Framework is also available as a separate download from Microsoft. Windows CardSpace and Language Integrated Query (LINQ).NET Framework. Instead it contains Common Intermediate Language (CIL). The . It is also installed when Visual Studio 2003. However.4 CHAPTER 1. the most important of which are the runtime and Class Library. SilverLight is a web-based subset of WPF. 2005 or 2008 is installed. When a . CLR provides services that include memory management.NET Framework is installed automatically when Windows Server 2003. but many machines still run 1.NET applications without any additional effort on the part of the programmer. The . INTRODUCTION Languages: C#. In addition. Windows Workflow Foundation (WF). VB. Jscript. Windows XP SP2. or Common Language Runtime (CLR) provides a virtual machine for the execution of .NET Windows Forms XML Web Services Web Forms Data and XML Classes Base Framework Classes Common Language Runtime (CLR) Operating System Table 1. thread management.NET Framework consists of several components.Net Framework is version 3.NET program is compiled. Pascal Common Language Specification (CLS) Common Type System (CTS) ASP. VJ#.1: . See Table 1. the compiler generates an .5. component lifetime management.0 and 3.exe is executed it does not interact . Vista or later is installed.exe file. garbage collection and default error handling. this .NET Framework Stack #define #warning #line #endregion #pragma warning #undef #error #region #pragma #pragma checksum C# cannot be run without installing the . The current version of the . Version 3.NET code. The . Cobol.

.NET). XML and network communications. This is a component of the CLR and provides a common set of data types that are consistent between all .Forms namespace allows the programmer to take advantage of the Windows forms engine to create graphical user interface objects easily.5 with the operating system directly but with the CLR. When a . with CIL being analogous to bytecode and CLR with the Java Virtual Machine(JVM). This theoretically overcomes the performance overhead associated with using virtual machines. This is similar to Java. numbers and dates.NET compatible. The CLS uses uses a Common Type System (CTS). cryptography.Windows. It contains all the types that represent the base data types such as text. The Class Library covers a wide range. data access and database connectivity (ADO.NET languages. including user interface. The Class Library is language-independent. The Common Language Specification (CLS) is a specification for creating or porting programming languages to that they are . The Class Library is a collection of extensible class libraries organised hierarchically into namespaces. For example. The Systems.NET application is first executed. web application development (ASP. the System namespace is at the top of the namespace hierarchy. numeric algorithms.NET). This is known as Just In Time compilation. the CLR performs a compile of the CIL and creates a directly executable file from it.

where \n provides a newline. // cshello. Note that C# is case-sensitive. Thus also the Main method must be contained inside a class.cs using System. A comment is indicated by //.1 Introduction Compile and link the programs with csc filename.WriteLine("Hello Egoli\n"). To avoid fully qualifying classes throughout the program.cs This generates an execute file named filename. is reserved for the starting point of a program. We write to the screen. Console. 6 . The static modifier explains that this method works in this specific class only. no object instances exists. // \n newline Console.exe. class Hello1 { public static void Main() { Console. The method name. Main. In front of the word Main is a static modifier. This is necessary. Main is often called the entry point (starting address) of the program. rather than an instance of the class. we can use the using directive.Write("midnight").Chapter 2 CSharp Basics 2. In the first example this is Hello1. because when a program begins. This is also known as an executable assembly. In C# everything must be inside a class.WriteLine("Good Night Egoli").

.WriteLine("Good Night"). With the using System.Console class contains a method WriteLine() and a method Write() that can be used to display a string to the console.2. for example "name". Namespaces contain groups of code that can be called upon by C# programs.WriteLine("Hello {0}". Strings are embedded in double quotes.Write(. The difference is that the Console. but the Console. // hello2. INTRODUCTION } // end Main } 7 The namespace declaration. declaration.) goes to the next line after writing to the Console. } // end Main } After compiling the program we run it with.WriteLine(.args[0]). To access command line parameters we change the signature of the Main(void) to Main(string[] args).cs using System. The expression string[] args defines an array of strings. } Console. indicates that we are referencing the System namespace. using System. } catch(Exception e) { Console. for example. We write to the screen using exception handling with try and catch block.) statement writes to the Console and stops on the same line.WriteLine(e). The System. class Hello2 { public static void Main(string[] args) { try { Console..1. we are telling our program that it can reference the code in the System namespace without pre-pending the word System to every reference.

cs using System. // Pauses the program until a key is pressed } // end Main } 2. The command Length returns the number of elements in the array. uint.WriteLine("Good Night"). char. The program above can be modified like so: . We are also using an if-else construct. long..WriteLine("Enter your name: "). int.2 Basic Data Types Basic (primitive) data types are bool.Length > 0) { Console. Console. decimal . // hello3..WriteLine("Hello {0}". Console.WriteLine("Hello {0}". class Hello3 { public static void Main(string[] args) { if(args. } // 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.name). byte. ushort. string name = Console. } Console. double. short. This problem can be solved using the Read() method to pause the window.8 Hello2 James CHAPTER 2.args[0]).WriteLine("Good Night"). ulong float.Read(). CSHARP BASICS To read from the keyboard we use the method ReadLine(). } else { Console. sbyte. Console.ReadLine().

class Datatypes { public static void Main() { bool b = true.NET Type System. // boolean data type Console.UInt32 System.Boolean System.WriteLine(!b).2. struct and class.WriteLine(e). .Char System. The floating point number float is 4 bytes and the floating point number double is 8 bytes..Object Description true/false unsigned byte value signed byte value a single character 16 bit signed integer 16 bit unsigned integer 32 bit signed integer 32 bit unsigned integer 64 bit signed integer 64 bit unsigned integer 32 bit floating point 64 bit floating point a high precision double string of characters a generic type At compile time the C# compiler converts the C# types into their corresponding . int and uint are 4 bytes.Single System.UInt16 System.WriteLine(f). short and ushort are 2 bytes (16 bits). char data type (2 bytes) in C# contains Unicode characters similar to Java.127.cs using System. 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. // null character ASCII value 0 Console. C# bool byte sbyte char short ushort int uint long ulong float double decimal string object .Decimal System.. // ! is the logical NOT // character 2 bytes Unicode char e = ’a’.UInt64 System.Byte System. char f = ’\0’.Int16 System.Double System. // datatypes.255 and for sbyte is -128.Int64 System.2. // character ’a’ ASCII value 98 Console. Apart from the above basic types the user may define his own types using enum.Int32 System. BASIC DATA TYPES 9 The range of byte is 0.String System. where ushort is unsigned.SByte System.NET types described in the above table. Built-in types are also string and object.

. Console. // float 32 bits Console.65535 (2 bytes) // signed int -2147483648.255 // signed byte -128... 2. ASCII is.WriteLine(h). // type conversion Console.WriteLine(c). double n = 3.WriteLine(l).10 CHAPTER 2. ASCII codes represent text in computers. strictly. long k = -234567899.2^63-1 // unsigned long 64 bits 0.... int i = -100000..32767 (2 bytes) // unsigned short 0. and in control devices that work with text. ushort h = 20000. meaning that it uses the bit patterns representable with seven binary digits (a range of 0 to 127) to represent character information. d--.2147483647 // unsigned int 0. // decimal 128 bits decimal p = (decimal) 2. a seven-bit code...127 // short -32768..WriteLine(k). ASCII reserves the first 32 codes (numbers 0-31 decimal) for control characters. c++.. Console. Console. Console.14159.WriteLine(g). is int // unsigned byte 0.WriteLine(p). uint j = 200000... ulong l = 3456789123. } } Note that (data type) is the type conversion operator.2^64-1 // default floating point number is double // (float) type conversion from double to float float m = (float) 3.WriteLine(n).. Console. Console.WriteLine(j).145.WriteLine(m). ASCII specifies a correspondence between digit bit patterns and the symbol of a written language.4294967295 // signed long 64 bits -2^63. Console.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. short g = -10000. in other communication equipment..89124357865678. sbyte d = -125.. CSHARP BASICS // default integer type byte c = 255. The capital ’A’ is 65 (decimal) . // double 64 bits Console.WriteLine(i).

Furthermore ’0’ is 48 and ’9’ is 57. // 13 char c5 = ’\t’. // 12 char c3 = ’\n’. +.4 Arithmetic Operations The arithmetic operations are ++. // ASCII value Console. // carriage return int i4 = (int) c4.WriteLine("i1 = " + i1).WriteLine("i4 = " + i4). The type conversion operator is (data-type). // Escape. // 9 char c6 = ’ ’. // newline int i3 = (int) c3. *. // 8 char c2 = ’\f’. // 32 } // end Main } 2.4. // ASCII value Console. // backspace int i1 = (int) c1. // horizontal tab int i5 = (int) c5.cs using System.WriteLine("i5 = " + i5).WriteLine("i2 = " + i2). % . /.2. The null character is ’\0’. // form feed int i2 = (int) c2. // ASCII value Console. // 10 char c4 = ’\r’. Space is 32. -. // ASCII value Console. // ASCII value Console. ARITHMETIC OPERATIONS and the small ’a’ is 97. // ASCII value Console.WriteLine("i3 = " + i3). 11 We are doing type conversion from char -> int using the ASCII table. class Escape { public static void Main() { char c1 = ’\b’. --. // blank int i6 = (int) c6.WriteLine("i6 = " + i6).

// type conversion float f2 = (float) 2. // integer division Console. c++.WriteLine(d).5. int r3 = r1/r2. float f1 = (float) 3. double d2 = 4. Console. float f3 = f1*f2. // signed int int j = 15002. int r2 = 5. int k = i + j.WriteLine("r4 = " + r4). .WriteLine(f3).WriteLine(k).WriteLine(c).WriteLine(p). // remainder Console. CSHARP BASICS where ++ is the increment by 1 and -. double d1 = 3. class Arithmetic { public static void Main() { byte c = 255. long m = -234567899.12 CHAPTER 2. Console. int r4 = r1%r2. Console. long p = m*n.is the decrement by −1.145.cs using System. // arithmetic. // signed long long n = 345. 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.14159. int i = -100000.WriteLine("r3 = " + r3).81. int r1 = 27. sbyte d = -125. Console. // signed byte d--. Console.

. // convert string of digits to int if(i > 5) // if true do the next command else skip it Console. // type conversion decimal p3 = p1 + p2. } } 13 2.2. Console.5. i = System.ReadLine().cs using System.. else and switch use certain criteria to select a course of certain action within the program.WriteLine(p3).WriteLine(d3).ToInt32(line). decimal p1 = (decimal) 2.5 Control Statements Control statements control the program flow. // forloop. Console.WriteLine("Enter integer: ").WriteLine("The number is larger than 5"). CONTROL STATEMENTS double d3 = d1/d2. // type conversion decimal p2 = (decimal) 3.89124357865678. else Console. string line = Console. selection statements such as if .14159. class forloop { public static void Main() { .WriteLine("The number is smaller than 5 or equal to 5"). Console. For example. } // end Main } The for loop applied to a one-dimensional array. class myIf { public static void Main() { int i. // myIf.cs using System.Convert.

2. x[1] = 3. class ForLoop { public static void Main() { int sum = 0. int i = 0. int intsum = 0. We count how often the string "otto" is in the array of strings. // declare array and allocate memory x[0] = 4.WriteLine("sum = {0}". for(i=0. // initialize sum to 0 String line. for(i=0.In. } Console.Convert.i++) { intsum += x[i]. Note that ! is the logical NOT and ToInt32(string) converts a string of digits to an integer.2. } Console.Length.ToString() + "\n").line!="".WriteLine(sum. // sum = sum + numbers[i].In. int[] x = new int[3].0.i<x. .1. } // end Main } The foreach loop can be applied to an array of strings.sum). 3.cs using System. // shortcut for intsum = intsum + x[i].3.WriteLine(intsum). } // end Main } Another example for the for loop applied to numbers read from the keyboard.ReadLine()) { sum += System.i++) // Length provides length of array { sum += numbers[i].ToInt32(line). for(line=Console.Length.14 CHAPTER 2.ReadLine(). double sum = 0. x[2] = 7. // forloop1. } // end for loop Console.i<numbers. 4.4 }. CSHARP BASICS double[] numbers = { 1.line=Console.

} // end Main } The while loop // whileloop. } // end Main } 15 . CONTROL STATEMENTS // foreachloop.WriteLine("count = {0}".cs using System. } } // end foreach Console.sum). 2. class foreachloop { public static void Main() { string[] namelist = { "willi". while(i < numbers. 3. string n = "otto". int count = 0."carl". i++. 4 }."otto".WriteLine("sum = {0}". int i = 0.count).2.5. foreach(string name in namelist) // keyword in { if(name == n) // compare strings for equality case sensitive { count++."otto" }. class whileloop { public static void Main() { int[] numbers = { 1. int sum = 0. } Console.cs using System.Length) { sum += numbers[i]."john".

class whileloop { public static void Main() { double[] numbers = { 1. 2. else constructions. class Myswitch { public static void Main() { string st = "bella".Length)..i<st.1.WriteLine("character is a ’a’ "). // dowhileloop.. } // 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 . 3. The switch statement transfers control to one of several case-labeled statements.3. . switch(c) { case ’a’: Console. CSHARP BASICS The do-while loop applied to an array of floating point numbers. double sum = 0.0.16 CHAPTER 2. do { sum += numbers[i]. depending on the value of the switch expression. Console.sum).cs using System. for(int i=0. Note that if the break is omitted. // switch.i++) { char c = st[i].5 }. execution will continue over the remaining statements in the switch block. 4.cs using System. int i = 0. i++.5.WriteLine("sum = {0}". } while(i < numbers.Length. The break statement can also be used to break out of an iteration loop.

Convert.6 Logical Operations The logical operators in CSharp. string line = Console.1. } // end switch } // end for loop } // end Main } 2. default: Console.6. break. break. case ’b’: Console.Length.ToInt32(line).4.j). C++ and Java are && logical AND || logical OR ! logical NOT // logical. default: Console.cs using System.WriteLine("character is a ’b’ "). C. LOGICAL OPERATIONS break.6.WriteLine("character is not an ’a’ or a ’b’ "). . } } // end for loop int[] numbers = { 3. 17 for(int j=0.2. j = System.WriteLine("number at position {0} is not 4 or 6".j<numbers. case 6: Console.6}.ReadLine(). break.1.WriteLine("number at position {0} is 6".-3.WriteLine("number at position {0} is 4". break. class MyLogica { public static void Main() { int j.j).j).j++) { switch(numbers[j]) { case 4: Console. break. Console.4.WriteLine(" Enter an integer: ").

line = Console. int n.WriteLine(). CSHARP BASICS if((j%2 == 0) && (j < 10)) Console. The dereference operator is *. } } 2. Console.Convert. Console.WriteLine("The integer is zero").WriteLine("The integer is nonzero"). Console.WriteLine(). n = System.18 CHAPTER 2. k = System. if(n == 0) Console. Pointers in CSharp must be declared unsafe. if((k > 0) || (k < 0)) Console.WriteLine("The integer is zero"). else Console. Console.Convert. Obtaining the value that a pointer referes to is called dereferencing. else Console. Thus the pointer has an address and contains (as value) an address.WriteLine("The integer is either odd or larger than 10 or both"). int k. // Pointers1.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.cs using System. line = Console. else Console.ToInt32(line).ToInt32(line).WriteLine("Enter an integer: ").WriteLine("The integer is even and smaller than 10").ReadLine().WriteLine("The integer is nonzero").WriteLine("Enter an integer: ").ReadLine(). class Pointers { .

// declare pointer and assignment to address of i int j = 15. // 15 } } We are using pointer to pass by reference (see section 2. class recur { public static ulong fib(ulong n) { if(n == 0) return 0. We use recursion to find the Fibonacci numbers. Console.WriteLine("b2 = " + b2).8. if(n == 1) return 1.WriteLine("b1 = " + b1). } // end fib public static void Main() { ulong n = 10. ulong result = fib(n). return fib(n-1) + fib(n-2). int* q = &j. A recursive function is one whose definition includes a call to itself.10). } // end Main } .8 Recursion Recursion plays a central role in computer science.cs using System. bool b1 = (i == j). A recursion needs a stopping condition.WriteLine("r = " + r). Console. 19 2. // recursion. // false // dereferencing pointers int r = *q.WriteLine("Result = {0}". Console.2. Console.result). int* p = &i. RECURSION public static unsafe void Main() { int i = 15. // true bool b2 = (p == q).

if(result == (a+b)) goto L2. It is part of the class Environment.ReadLine(). int b = r. Console. We use the goto to jump to the labels L1.a. // mygoto. L2: Console. goto L4.ToInt32(s). see you next time around"). L2. if(t == "y") goto L3.cs .9 Jump Statements C# also has an goto for jumping to labels.Next(100). L3: int a = r. result = Convert. string t = Console.WriteLine("{0} + {1} =". Console. L3.ReadLine(). string s = Console. // password. } } The method Exit() is used for program termination.cs using System.WriteLine("bye.20 CHAPTER 2. L1: Console. int result. CSHARP BASICS 2.b). if(t == "n") { Console. class Mygoto { public static void Main() { Random r = new Random(51). L4 if a condition is met.Next(100).WriteLine("congratulations you are correct"). } L4: int e = 0.WriteLine("Want to add again: Press y for yes and n for no: "). goto L1.WriteLine("sorry you are not correct: try again").

The alternative.2. a copy of the argument is produced.j<91. When an argument is passed by value. Thus functions that receive pointers to variables gain access to the original variables associated with the pointers. When arguments are passed by reference. not the originals. the parameter variable is an alias for the argument value. char[] data = { c1.k. Functions that receive variables as parameters get local copies of those variables.i<91. In C# we can also use pointers and the dereference operator to pass by reference. Environment. char c2 = (char) j. Thus. This means. char c3 = (char) k. if(found == true) { Console.Equals(s).j++) { for(k=65.c2. // converting array of char to string bool found = password. Pass by Reference Arguments to functions can be passed either by value or by reference. pass by reference. string s = new string(data). change in the parameter also alter the original argument.k<91.WriteLine("Password = {0}". } } } } } } 2.c3 }. PASS BY REFERENCE using System. is indicated by the presence of the keyword ref in the argument list.10.j. and the associated parameter is the same as a local variable for the function. . changes to the parameter variable will have no effect on the original argument value.Exit(0).k++) { char c1 = (char) i. 21 class password { public static void Main() { string password = "XYA". PASS BY VALUE.s). for(i=65. int i.10 Pass by Value.i++) { for(j=65.

Console.WriteLine("i inside function add = " + i).WriteLine("i in Main = " + i). *q = t.int* r) { int t = *r. rot(&a. add(i).&b.cs using System. Console. // 20 } // end add public static void Main() { int i = 10. In the next program we use pointers to pass by reference. *r = *p. *p = *q. // pointers2.&c). public class Rotate { public static unsafe void rot(int* p.22 CHAPTER 2. .cs using System. int c = 17. // 10 } } Note that without static in method add(int): error message: An object reference is required for the nonstatic method Pitfall. i = n. We rotate integer numbers. CSHARP BASICS In the next program we pass by value. int b = 12. public class Pitfall { public static void add(int i) { int n = i + i. // Pitfall.int* q. } public static unsafe void Main(string[] args) { int a = 10.add(int).

b.ref int q.2.ref b. } // end main } 23 In the following program we use the keyword ref to pass by reference. We rotate three integers.c). sb = "222". } public static void Main() { int a = 10. } public static void Main() { string s1 = "xxx". // references. public class Passing { static void change(ref string sa. PASS BY VALUE. . int c = 17.ref c). } // end Main } In the following program we pass the first argument by reference and the second by value. int b = 12.string sb) { sa = "yyy".cs using System.a.c). q = t.cs using System. PASS BY REFERENCE Console.10. Console.ref int r) { int t = r. r = p.WriteLine("a = {0} and b = {1} and c = {2}". p = q. rot(ref a. // passing.b.WriteLine("a = {0} and b = {1} and c = {2}". public class Rotate { public static void rot(ref int p. string s2 = "111".a.

s.out s.14. Divide2(145. int s. } // end Main } 2. return quot. } // end Divide1 public static void Divide2(int dividend.q. A variable using this keyword must not be initialized before the method call.WriteLine("Quotient = {0} and Remainder = {1}". Console.3.out int r) { quot = dividend/divisor. r = dividend .out t). multidimensional . class Divider { public static int Divide1(int dividend. CSHARP BASICS change(ref s1.quot*divisor. r = dividend .WriteLine("Quotient = {0} and Remainder = {1}".int divisor.out int r) { int quot = dividend/divisor.r).t).Write("s1 = {0} and s2 = {1}".s2). Console. int t. Console.24 CHAPTER 2.int divisor.11 Arrays An array is a data structure that contains a number of variables. // Divide. } // end Divide2 public static void Main() { int r.cs using System. // => s1 = yyy s2 = 111 } } The out keyword explicitely speciefies that a variable should be passed by reference to a method.out r).s1. C# supports one-dimensional arrays. and set in that method. int q = Divide1(123. These are accessed through computed indices.s2).out int quot.quot*divisor.

// sorting the array . This is identical to the complete initialisation statement: int[] numbers = new int[] {0. 1. When declaring arrays.Write("\n"). 5}. 890. Console. As C. double[] d = new double[3]. Console. Console. int pos1 = Array. Console.Write("\n"). Array."carl"). 3. This means the array indexes start as zero. 5}. 2. int numb = Array. class myArray { public static void Main() { int[] numbers = { 4. d[0] = 1. d[1] = 3. "uli". System. Console.Sort(slist).Array is the abstract base type of all array types. The size of the array is not part of its type as it is in the C language. 3.BinarySearch(numbers.Write("prod = " + prod). 23456789 }. d[2] = 8.WriteLine().Write("pos1 = {0}". for example int[] table. In C# arrays are actually objects.9. Console. 12345.Write("dpos = " + dpos). "carl".2. int prod = numbers[2]*numbers[0]. ARRAYS 25 arrays (rectangular arrays) and arrays of arrays (jagged arrays). Thus int[] numbers = new int[20].4. The class Array contains methods for sorting and searching. int dpos = Array. the square bracket [] must come after the type. // myArray. 2.BinarySearch(slist.1. C++ and Java C# arrays are zero indexed.9).Write("\n"). not the identifiers.8. We can initialise arrays very simply: int[] numbers = {0. Console.pos1).cs using System.Write("numb = " + numb). "marius".4). 1. string[] slist = { "otto". Console. "jacob" }.11.BinarySearch(d.

Length. 1] = 2.BinarySearch(slist.pos2). which are arrays of arrays. The outermost nesting level corresponds to the leftmost dimension. numbers[3. 10}. Console.WriteLine(). } } } To create multidimensional arrays the array initializer must have as many levels of nesting as there are dimensions in the array.j++) { Console. Thus: int[. 8. 1] = 10. numbers[0.] numbers = new int[5. 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. Or: int[. 1] = 14. The length of each dimension of the array is determined by the number of elements at the corresponding nesting level in the array initializer. numbers[4. CSHARP BASICS int pos2 = Array. {16. for(int j=0. 2}. {4.j<slist. public class TwoDim { public static void Main() { int[][] matrix = new int[2][]. // twodim.26 CHAPTER 2.WriteLine("{0} {1}". 12. 18}}. numbers[1.slist[j]). {8. numbers[2. Console. 6}.j. numbers[1. {12.Write("pos2 = {0}". 1] = 6. 2].] numbers = {{0. 0] 0] 0] 0] 0] = = = = = 0. The element arrays do not all have to be the same. // rows . and initialises the array with: numbers[0. 17}. 16."carl").cs using System. numbers[2. 4. We can also create jagged arrays. The innermost nesting level corresponds to the rightmost dimension. numbers[3. numbers[4. 1] = 18.

C++ and Java are: & | ^ ~ AND OR (inclusive OR) XOR (exclusive OR) NOT // bitwise. myarray[0. } // end Main } 2.12 Bitwise Operations Consider the integer number 17 (base 10. myarray[1.2] = 3.2] = 7. // columns matrix[1] = new int[2]. int i = 1.e. Console. Console. 17 = 1 · 101 + 7 · 100 . It can be written in binary as 17 = 1 · 24 + 0 · 23 + 0 · 22 + 0 · 21 + 1 · 20 .7.1. // columns matrix[0][0] = 2.WriteLine("matrix[" + i + "][" + i + "] = " + matrix[i][i]). If 17 is considered as data type int (32 bits) we have the binary representation 00000000000000000000000000010001 The bitwise operation in CSharp. myarray[1. Thus the binary representation of 17 would be 10001. matrix[1][0] = 7.1. matrix[0][0] = 4.2]. double[. myarray[1.WriteLine("r = " + r). myarray = new double[2.12. double r = myarray[0.1]*myarray[1.0] = 3.3.1] = 1.3.2.1] = 4.3]. C. matrix[1][1] = 3. class MylBitwise { public static void Main() { . i.0] = 2.7. BITWISE OPERATIONS 27 matrix[0] = new int[2]. myarray[0. myarray[0.cs using System.] myarray.

. 8. } } 2.13 Shift Operation We can use shift operation for fast integer multiplication by 2. int r9 = r6 ^ r7.r10).. // one’s complement int r14 = ++r13. int r4 = 5. . Console. int r13 = ~r12. //bitwise XOR Console. int r7 = 11. // bitwise OR Console. and fast integer division by 2. CSHARP BASICS int r3 = 4. // => int m = 9.r9). // => int k = i >> 2. 8. The shift operations are << and >>. // integer divison Console. // bitwise AND Console. int r12 = 4. class Shift { public static void Main() { int i = 17.WriteLine("Binary XOR of 7 and 11 gives {0}".WriteLine("Binary AND of 4 and 5 gives {0}". // MyShift.r5).WriteLine("Binary NOT of r9 gives {0}". int r6 = 7.r8). int r11 = ~r9.28 CHAPTER 2.WriteLine("Binary OR 7 and 11 gives {0}". // integer divison Console. 4. int r5 = r3 & r4.. Console. // 17 in binary 10001 int j = i >> 1. int x = 125.WriteLine("Binary XOR of 125 with itself gives {0}". 4. int r8 = r6 | r7. .r14).cs using System.WriteLine("two’s complement of 4 {0}".WriteLine("k = " + k).WriteLine("j = " + j). Console. int r10 = x^x..r11).. by 2 8 by 4 4 .

cs using System.WriteLine("p = " + p). Console. Boxing is carried out implicitly in C#.i).args[0]). When the C# compiler (csc. The Main method may accept an array of string as its arguments (though this is optional). Comsole.14. COMMMAND-LINE ARGUMENTS int n = m << 1.WriteLine("i={0}"."). for example CommandLine World 2. // multiplication by 2 Console. class CommandLine { public static void Main(string[] args) { Console.15 Boxing and UnBoxing Types Boxing refers to converting a value type to an object type.2.exe) compiles a C# program it marks the Main method as the entrypoint in the generated IL code. // => 36 } } 29 2.WriteLine("Goodbye. // => 18 int p = m << 2. The following program shows an application. This array will always contain the command line arguments passed to the program by its user. and unboxing refers to the opposite. // multiplication by 4 Console.WriteLine("Hello{0}".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. We start counting from zero.WriteLine("n = " + n). . For example int i. whereas we have to use type casting to unbox to an appropiate data type. } } We run the program. // CommandLine.

11). } static void SecondMethod(string s2.WriteLine("sum1 = " + sum1). An example for unboxing is int i. } // end Main static void FirstMethod(string s1. class Application { public static void Main() { MyDelegate md = new MyDelegate(FirstMethod).int y2) { . // declare delegate with the signature of the // encapsulated method delegate void MyDelegate(string m.int b).7. md("message A". // delegates. // to unbox we use type cast Typically unboxing is done in a try block. CSHARP BASICS The WriteLine() method requires an object. md("message B".16 Delegates A delegate essentially creates a name for a the specific type/signature of a method.int x1.cs using System.4.int x2.5). an InvalidCastException is thrown.int y1) { Console.int a. object obj = i.30 CHAPTER 2. 2. If the object being unboxed is null or if the unboxing cannot succeed because the object is of a different type. md += new MyDelegate(SecondMethod).WriteLine("1st method: " + s1). // boxing is implicit int j. so in the above statement integer i is implicitly boxed to an object and passed to the WriteLine method. One must first declare a delegate. int sum1 = x1 + y1. Console. Delegates are type safe function pointers. j = (int) obj.

Write("s is of the StringBuilder").WriteLine("at = {0}".WriteLine("2st method: " + s2).sbt). Console.at).Text. if(s is string) Console.17 Types The typeof command is an operator. . It resolves at compile time and operates over a type. StringBuilder sb = new StringBuilder("123456789").WriteLine("sum2 = " + sum2). TYPES Console. if(s is StringBuilder) Console. Type sbt = typeof(StringBuilder).st).14.WriteLine("sbt = {0}". Type st = typeof(string). // myTypeof. Type at = typeof(double).WriteLine("st = {0}". Console. } } The output is 1st method sum1 = 9 2st method sum2 = 9 1st method sum1 = 18 2st method sum2 = 18 message A message A message B message B 31 2. To check whether an object is compatible to a specific type is to apply the is keyword. class myTypeof { public static void Main() { double b = 3.WriteLine(at). Console. int sum2 = x2 + y2.2. Console.cs using System.17. using System. string s = "xxx".

The name will be searched in the current assembly Type t = Type.Reflection. 4.Reflection. This reference can be used to obtain the Type with a given name: using System. 1. CSHARP BASICS else Console. Assembly asm = Assembly. From the type name within current assembly: System.18 Reflection Exposing and utilizing types at runtime is called reflection.GetType("FullyQualifiedTypeName").cs using System. The program showtypes.cs displays all the Types defined in an assembly whose name is passed in as first command line argument: // showtypes.32 CHAPTER 2.Object as Type t = obj.GetType().Type class the reference to which can be obtained using one of the following methods. Type t = asm. 2. class ShowTypes { public static void Main(string[] args) . if(b is int) Console. 3.LoadFrom("AssemblyName"). The type of an object is stored as an instance of System. From an instance: Type of an instance obj can be obtained using GetType method defined in System.WriteLine("b is int").GetType("FullyQualifiedTypeName"). } } 2. From the declaration type: If declaration AType var is legal then System. using System.Type offers a static method called GetType to obtain a Type from a fully qualified name of the type. From the type name within any assembly: First load the assembly and obtain a reference to it.Write("s is not of StringBuilder").Type representing AType can be obtained using the typeof operator as: Type t = typeof(AType).

Generic namespace.GetTypes(). GENERICS { Assembly asm = Assembly.Reflection.cs takes the assembly name and type name as its command line arguments and displays all the members defined in that type of assembly.19. The standard example provided by Microsoft is a generic stack.NET Framework the concept of type parameters.LoadFrom(args[0]). for example showtypes datatypes.GetType(args[1]).exe Pass complete path to any . foreach(MemberInfo m in members) Console. MemberInfo[] members = t. .LoadFrom(args[0]). 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 .WriteLine(m).0 of the C# language and the common language runtime (CLR).GetMembers(). Type t = asm.NET exe or dll to see the types declared in it. // showmembers. Generics introduce to the .19 Generics C# Generics are similar to C++ Templates.Collections. Type[] types = asm. They were introduced in version 2. foreach(Type t in types) Console. class ShowMembers { public static void Main(string[] args) { Assembly asm = Assembly.WriteLine(t). } } We would run the program as. 33 The next program showmembers.NET Framework class library contains several new generic collection classes in the System.cs using System.2. } } 2. using System.

public Stack():this(100) {} public Stack(int size) { m_Size = size. m_Items[m_StackPointer] = item. T[] m_Items. stack.} } Stack<int> stack = new Stack<int>().Push(1). } else { m_StackPointer = 0. CHAPTER 2.Push(2). int m_StackPointer = 0.34 public class Stack<T> { T[] m_Items. m_StackPointer++.. int number = stack.} public T Pop() {. The generic stack code is public class Stack<T> { readonly int m_Size.. stack. public void Push(T item) {. if(m_StackPointer >= 0) { return m_Items[m_StackPointer]..Pop(). } public void Push(T item) { if(m_StackPointer >= m_Size) throw new StackOverflowException(). CSHARP BASICS . } public T Pop() { m_StackPointer--.. m_Items = new T[m_Size].

2. } } } 35 . GENERICS throw new InvalidOperationException("Cannot " + "pop an empty stack").19.

// mystring. s2 = s2. string result = s3. which means that once the value of the string instance is set. The string class and the StringBuilder class provide ways to perform string manipulations.WriteLine(length).WriteLine(s1).WriteLine(s2). class mystring { public static void Main() { string s1 = "otto".1 String Class The most importent built-in class is the string class. Console. Console. Console. // => otto Console.Chapter 3 String and StringBuilder 3. // => annes 36 . it is actually returning a new instance of the string class in memory. The string class provides an immutable object string s = "Hello". Even though it appears that the application is changing the value of the string instance. // => 4 string s2 = "willi". // witti string s3 = "Johannesburg".Replace(’l’.cs using System. int length = s1. it cannot be changed.Substring(3.’t’).Length.5).WriteLine(result).

// => opa string s8 = "xeNa".WriteLine(textarray[1]). Console.Split(’&’).Equals(s13). Console.WriteLine("s14 = " + s14). Console. Console.ToLower(). // => False // copy a string string s15 = string.textarray).cs . STRING CLASS 37 string s4 = "olli&ulli&ruedi". Console. } // end Main } Arrays of strings can be implemented as follows. string s7 = new string(s6).ToUpper().Copy(s14). string s9 = s8. Console.WriteLine(s5). string s11 = s10.1. ’a’ }. // => olli:ulli:ruedi char[] s6 = { ’o’.WriteLine(s7). string s14 = s12 + s13. string[] textarray = s4. // use Equals() to compare strings // case sensitive bool b1 = s12.Join(":".WriteLine("b1 = " + b1). // stringarrays. Console. Console. // => ulli string s5 = string.WriteLine(s9). // => willi hans // use + to concatenate strings string s12 = "Carl-". ’p’. // => False // can also use overloaded == to compare strings // case sensitive bool b2 = (s12 == s13). // => XENA string s10 = "WILLI HANS".WriteLine("s15 = " + s15). string s13 = "Otto".WriteLine("s11 = " + s11).3. Console.WriteLine("b2 = " + b2).

"three"}}."one"}. // => in // one-dimensional array of strings string[] names = { "willi".0]). STRING AND STRINGBUILDER using System.WriteLine(names[2]). "xena" }. class stringarrays { public static void Main() { // one-dimensional array of strings string[] keywords = new string[] { "as".0]).] strArry = {{"1". {"3".WriteLine(keywords[3]).WriteLine(strArry[0.cs using System. Console. public class MyConvert . // => xena // two-dimensional array of strings string[.38 CHAPTER 3. The methods are string ToString(T x) // any numerical type bool ToBoolean(string s) byte ToByte(string s) char ToChar(string s) short ToInt16(string s) int ToInt32(string s) long ToInt64(string s) float ToSingle(string s) double ToDouble(string s) decimal ToDecimal(string s) An example is // MyConvert. "do". Console. Console. "if". {"2"."two"}. "ola".2 Convert Class Using the Convert class we can convert string to numbers (integers and floating point) and numbers (integers and floating point) to strings. // => 1 Console. "in" }.WriteLine(strArry[2. // => 3 } // end Main } 3.

cs using System. The StringBuilder class is defined in the System.WriteLine("b = " + b).Length+12).ToChar("x"). Console.14159.WriteLine("s1 = " + s1). // for StringBuilder class mystringbuilder { public static void Main() { string s = "carl". Remove() and Replace(). Console.WriteLine("s2 = " + s2).3. StringBuilder b1 = new StringBuilder(s. string s1 = Convert. Using the StringBuilder class. Insert(). STRINGBUILDER CLASS { public static void Main() { int i = 34. Console. } } 39 3.14159". bool b = Convert.3. double y = Convert.ToString(i). string s3 = "3.ToString(x). Console. Thus we have to add the following line in our application. using System. // mystringbuilder. It is called mutable because it can be modified once it has been created by using the methods Append(). using System.Text.ToInt32("12345").Text namespace. Console. string s2 = Convert.WriteLine("y = " + y).3 StringBuilder Class The StringBuilder class represents a mutable string a characters.WriteLine("j = " + j).Text. Console. . int j = Convert.WriteLine("c = " + c). double x = 3.ToDouble(s3). char c = Convert.ToBoolean("true").

the method mythuemorse calls itself. STRING AND STRINGBUILDER b1. Console. return tm2.Remove(3.C b2. Console.B.cs using System. Console. Console. using System.30).’.Append("10"). We apply recursion.WriteLine(b1)."B.WriteLine(mythuemorse(i)). i.Insert(2.i<7. } public static StringBuilder mythuemorse(int n) { if(n == 0) return new StringBuilder("0".WriteLine(b1).").Replace(’. for(int i=0.Text.i<tm.C"). // => A:B:C StringBuilder b3 = new StringBuilder("stringbuilder").40 CHAPTER 3.Append("-uli"). b3. StringBuilder tm2 = new StringBuilder("". b1. // => stri } } Another application of the StringBuilder class is given by generating the ThueMorse sequence. // thuemorse.i++) Console. StringBuilder tm = mythuemorse(n-1).9). // => caruli StringBuilder b2 = new StringBuilder("A.50). // => carl-uli b1. else tm2.Append("carl").WriteLine(b2).Remove(4.2).WriteLine(b2). class ThueMorse { public static void Main() { for(int i=0. // => A. Console.’:’).Append("01").e.WriteLine(b3). } } . b2.Length.i++) if(tm[i] == ’0’) tm2.

WriteLine("s = " + s). int milli1 = m1. DateTime m1 = DateTime.Now.Minute.1 DateTime Class To get the dates and time we use the DateTime class. for(uint j=0.j<10000000. j--.dt.Chapter 4 Built-in Classes 4.cs using System.Millisecond.today). Today returns the current date. j = j/2. 2005. Console.dt. For formatting we could use d which would be the short date mm/dd/yyyy.dt.Now.dt. for example 9/24/2005 and D would be Saturday.ToString(). Console.j++) { j = j*2.Month. j++. Console. Console.dt. } 41 .WriteLine("Date Time output: {0}". The two static members are Now and Today.WriteLine("Time output: {0}:{1}:{2}". // myDate.Year.WriteLine("Date output: {0}\\{1}\\{2}". The DateTime class stores both a full date and the full time.dt).dt. // 7/29/2006 3:18:03 PM string s = dt. Console. Now contains the date and time for the moment the call is made.WriteLine("Today is: {0}". September 24. class myDate { public static void Main() { DateTime dt = DateTime.Second).Today.Day). Console.Hour.WriteLine("milli1 = " + milli1). DateTime today = DateTime.

877). // Saturday.WriteLine("D: {0:D}". void Copy(Array source.milli1.Millisecond. 123. BUILT-IN CLASSES DateTime m2 = DateTime. int p1 = Array.int length.int length).object value). void Reverse(Array array). Console.cs using System. // Formats DateTime currTime = DateTime. September 24.int length). .currTime).int index.WriteLine("d: {0:d}".WriteLine("milli2 = " + milli2).Collections. 45. int diff = milli2 . class MyArray { public static void Main() { int[] a1 = { 669. IList cotains methods for manipulations of arrays. int IndexOf(Array array. 2005 } } 4. // 9/24/2005 Console. ICollection.int length).2 Array Class The Array class class Array : IClonable.BinarySearch(a1.WriteLine("diff = " + diff).Now. Console. An example is // MyArray.Now.WriteLine("p1: {0}". Console. public virtual object Clone(). For example int BinarySearch(Array array. IEnumerable. 777 }.Array destination.object value). Console. //using System. int BinarySearch(Array array. p1).object value). void Clear(Array array.int index. int milli2 = m2. 456. 56. void Reverse(Array array.IList.currTime). 877.int index.42 CHAPTER 4.

// arraylist.4.i<a1. "ana" }.Sort(s1). "alla".Count.3. but cannot restrict the number of elements it may contain.Clear(a1.i<alist. Array.i<s1.Length. ARRAYLIST CLASS 43 string[] s1 = new string[] { "aaba".IndexOf(a1. for(int i=0.WriteLine("j = " + j).cs using System.i<s1.Length.Reverse(s1). } Array. for(int i=0. } Array.2). class arraylist { public static void Main(string[] arg) { ArrayList alist = new ArrayList().Add(s).3.Collections.WriteLine("a1[" + i + "]=" + a1[i]).Length.WriteLine("s1[" + i + "]=" + s1[i]).3 ArrayList Class An ArrayList is used in situations where we want an array-like list.i++) { Console. for(int i=0.i++) { Console. using System. // j = -1 why ? } } 4. "baaba".WriteLine("s1[" + i + "]=" + s1[i]). Console. } int j = Array.i++) { .123). An application of the ArrayList class is given below. for(int i=0.i++) { Console. foreach(string s in arg) alist. The method Add() adds an element to the list.

Console. population. BUILT-IN CLASSES Console. using System.Write("{0}". string s1 = "Xena".550500). } Console. } // end main } 4. using System.Collections.s1).Specialized.Equals(nlist). removes an element in the dictionary.cs using System. alist. population.Add("Durban".alist.9345120).WriteLine("{0}". bool test = alist.Add("Johannesburg".Write("\n"). Console.Insert(3.RemoveAt(1).Add("CapeTown".Write("Argument Count:{0}\n". class Dictionary { public static void Main() { ListDictionary population = new ListDictionary().Count). nlist = alist.4 ListDictionary Class The ListDictionary class stores a key and a value. The method void Remove(object key). The method public void Add(key.alist[i]).44 CHAPTER 4. foreach(DictionaryEntry name in population) { .test).Collections. population.value) adds an element to the ListDictionary. ArrayList nlist = new ArrayList().3500500). alist. // Dictionary.

sEnum. PI and E. using System. so we cannot create an object of type Math. A sealed class cannot be used for inheritance. IEnumerator sEnum = strArry.6 Mathematics Class and Random Class The Math class is sealed.name. // Enumerator. while(sEnum.Key.GetEnumerator()."two"}. all the classes and data members are static.Collections.WriteLine("{0} = {1}".5 Class IEnumerator The method public virtual IEnumerator GetEnumerator() returns a System.Write(" {0}". Console.cs using System.Collections. // distance. {"2".IEnumerator for the current instance. public class ArrayGetEnumerator { public static void Main() { string[. } } // end Main() } 45 4.Current). foreach(DictionaryEntry name in population) { Console.4.Value).Write("The elements of the array are: "). } population.MoveNext()) Console."three"}}.name. Instead.Value). {"3". } } 4. The Math class also includes two constants. CLASS IENUMERATOR Console. Additionally. we use the members and methods with the class name.Remove("Durban").name."one"}.name.cs .WriteLine("{0} = {1}".Key.] strArry = {{"1".5.

string source. BUILT-IN CLASSES using System. Console.Convert. Console.WriteLine("Enter the latitude of {0}: ".ReadLine(). dir = line[0]. Console.ReadLine(). Console. beta1 = (double) System. alpha2.ToInt32(line). beta1 += temp/60.WriteLine("Enter the name of the destination: "). Console. line = Console.dest). beta1. if(dir == ’S’ || dir == ’s’) beta1 = -beta1. source). class Distance { public static void Main() { double r = 6371. source = Console. line = Console. Console. temp = (double) System.ReadLine(). Console.WriteLine("N/S: ").0. line = Console. char dir. Console. temp = (double) System.WriteLine("degrees: ").WriteLine("minutes: ").ReadLine(). Console.0.ToInt32(line).WriteLine("Enter the name of the source: "). distance. Console. alpha1 = (double) System. dest = Console.WriteLine("degrees: "). line = Console. dir = line[0]. if(dir == ’E’ || dir == ’e’) alpha1 = -alpha1.0.WriteLine("Enter the latitude of {0}: ". double alpha1. Console.46 CHAPTER 4. Console.ReadLine().Convert.Convert.source). alpha1 += temp/60.ToInt32(line).ReadLine(). dest. theta. beta2.ReadLine().ReadLine().ReadLine().Convert. line = Console.WriteLine("Enter the longitude of {0}: ".WriteLine("degrees: "). line. .WriteLine("minutes: "). temp.ToInt32(line). line = Console. line = Console.WriteLine("W/E: ").

Console.Sin(beta2). line = Console. } } 47 The following table shows a partial list of the Math methods. alpha2 += temp/60. line = Console.PI/180.Convert.WriteLine("W/E: "). line = Console.Cos(beta1)*Math. temp = (double) System. distance = r*theta.ReadLine().PI/180. if(dir == ’S’ || dir == ’s’) beta2 = -beta2. beta2 += temp/60. Console. alpha2 *= Math.ToInt32(line).PI/180.0.Cos(alpha1-alpha2) + Math.0.ToInt32(line).ReadLine().WriteLine("The distance between {0} and {1} is {2} km".ReadLine().WriteLine("minutes: "). Console.distance).WriteLine("minutes: ").ReadLine().Convert.ToInt32(line).ReadLine().6. source.Convert.4.ToInt32(line). line = Console.Convert.0. temp = (double) System.0. Console.0.PI/180.Cos(beta2)*Math. alpha1 *= Math. line = Console.WriteLine("degrees: "). theta = Math.0. beta2 *= Math. dir = line[0]. beta1 *= Math. if(dir == ’E’ || dir == ’e’) alpha2 = -alpha2. . Console. alpha2 = (double) System.Acos(temp). MATHEMATICS CLASS AND RANDOM CLASS beta2 = (double) System. Console.Sin(beta1)*Math.dest). Console.WriteLine("Enter the longitude of {0}: ".dest.WriteLine("N/S: "). dir = line[0]. temp = Math.

x2) Larger of the two arguments Min(x1.i<10.WriteLine("random Console..r. sequence(no seed. x2) Value of x1 raised to the power of x2 Round(x. BUILT-IN CLASSES Argument Return Data Type Data Type Overloaded Return matches argument type Double Double Double Double Double Overloaded Overloaded Double Overloaded Double Double Double Double Double Double Return matches argument type Return matches argument type Double Return matches Double Double Double Angle in Radians whose tangent is x Cos(x) Cosine of x where x is in radians Exp(x) Value of e raised to the power of x Log(x) Natural log of x.i<10.i++) Console. // random. Console. no: {0}".int. y) Value of x rounded to y decimal places Sin(x) Sine of x where x is in radians Sqrt(x) Square root of x where x <= 0 Tan(x) Tangent of x where x is in radians The next program shows an application of the Random class.10)"). class LearnRandom { public static void Main() { Random r = new Random(). for(int i=0. x2) Smaller of the two arguments Pow(x1..MaxVal)").i++) Console.WriteLine().limit 0.WriteLine("random sequence(no seed. no: {0}".Next(10)). .cs using System. where x >= 0 Max(x1.WriteLine("Random for(int i = 0.r.Next()).48 Method Abs(x) Atan(x) Returns Absolute value of x CHAPTER 4.limit 0.WriteLine("Random Console.

4.WriteLine("The x coordinate is " + xcoord).100)).cs using System. class PointTest { public static void Main() { Point p = new Point(23.Drawing.WriteLine("Random sequence(no seed.i<10.WriteLine("Our Point is: " + pF). limit 0. int xcoord = p. Console.Length.WriteLine("random byte: {0}". r.7.b[i]). byte[] b = new byte[5].limit 50. Console. // pointt. int ycoord = p.Forms.NextBytes(b). float ycoordF = pF. Console. Point q = new Point(xcoord.Y.100)").r.WriteLine("Our Point is: " + p). for(int i=0. bool b = p.666666666667)..WriteLine("The y coordinate is " + ycoord).. } } 4. The PointF structure represents an ordered pair of floating point x.WriteLine(" the points are equal: " + b).r.WriteLine("random no: {0}". Console.and y.WriteLine("Random sequence in byte array(no seed.i++) Console.13). for(int i=0. Console.WriteLine("The x coordinate is " + xcoordF).i<10.WriteLine("Random sequence(no seed.Y. POINT CLASSES 49 Console. using System. ..i<b.Equals(q).i++) Console.WriteLine("random no: {0}".3333.Windows. PointF pF = new PointF((float)23.X.coordinates that define a point in a two-dimensional plane. float xcoordF = pF.NextDouble()). Console.X.1)").limit 0.1)"). Console.(float)13.i++) Console. using System.ycoord). for(int i=0.Next(50.7 Point Classes The Point structure represents an ordered pair xy of integers. Console.

50

CHAPTER 4. BUILT-IN CLASSES Console.WriteLine("The y coordinate is " + ycoordF); PointF qF = new PointF(xcoordF,ycoordF); b = pF.Equals(qF); Console.WriteLine(" the points are equal: " + b); }

}

4.8

Class BitArray

For dealing with bit string we use the class BitArray, where 1 is identified with true and 0 is identified with false. The constructor BitArray a = new BitArray(16); sets all elements to false. // BitArrayTest.cs using System; using System.Collections; public class BitArrayTest { static void Main() { BitArray a = new BitArray(16); BitArray b = new BitArray(16); a[3] = a[4] = a[5] = true; b[4] = b[5] = b[6] = true; BitArray c = a.And(b); Console.WriteLine("Bitarray c"); int i; for(i=0;i<16; i++) Console.WriteLine(c[i]); Console.WriteLine(""); BitArray d = (BitArray) c.Clone(); Console.WriteLine("Clone c into d"); for(i=0;i<16;i++) Console.WriteLine(d[i]); BitArray e = a.Not(); Console.WriteLine("Not a");

4.9. OBJECT CLASS for(i=0;i<16;i++) Console.WriteLine("e[" + i + "]=" + e[i]); a.SetAll(true); Console.WriteLine("a.SetAll(true)"); for(i=0;i<16;i++) Console.WriteLine("f[" + i + "]=" + a[i]); BitArray g = d.Not(); for(i=0;i<16;i++) Console.WriteLine("g[" + i + "]=" + g[i]); BitArray f = d.Xor(g); Console.WriteLine("Xor d to get f"); for(i=0;i<16;i++) Console.WriteLine("f[" + i + "]=" + f[i]); } }

51

4.9

Object Class

The Object class supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate superclass of all classes in the .NET Framework; it is the root of the type hierarchy. The C# syntax is [Serializable] public class Object Public static (non-instance) members of this type are safe for multithreaded operations. Instance members are not guaranteed to be thread-safe. Languages typically do not require a class to declare inheeritance from Object since the inheritance is implicit. Since all classes in the .NET Framework are derived from Object, every method defined in the Object class is available in all objects in the system. Derived classes can and do override some of these methods, including Object.Equals - support comparisons between objects Object.Finalize - performs cleanup operations before an object is automatically reclaimed Object.GetHashCode - generates a number corresponding to the value of the object to support the use of a hash table Object.ToString - manufactures a human-readable text that describes an instance of the class

52

CHAPTER 4. BUILT-IN CLASSES

The default constructor is called by derived class constructors to initialize state in this type. Initializes a new instance of the Object class. The method GetHashCode() serves as a hash function for a particular type, suitable for use in hashing algorithms and data structures like a hash table. The method GetType() gets the type of the current instance. The following code compares the current instance with another object. // object1.cs using System; public class object1 { public static void Main() { Object obj1 = new Object(); Object obj2 = new Object(); Console.WriteLine(obj1.Equals(obj2)); // => false obj2 = obj1; Console.WriteLine(obj1.Equals(obj2)); // => true } } The following example shows a Point class that overrides the Object.Equals() method to provide value equality and a class Point3D, which is derived from the Point class. The Object.Equals() method uses Object.GetType() to determine whether the run-time types of the two objects are identical. // object2.cs using System; class Point : Object { protected int x, y; public Point() { this.x = 0; this.y = 0; } public Point(int X,int Y) { this.x = X; this.y = Y; } public override bool Equals(Object obj)

int h2 = p3. Point3D p4 = new Point3D(5. Point p2 = new Point(6. Point p = (Point) obj.x = X.GetHashCode() ^ z.int Z) { this.8). return (x == p. public Point3D(int X. this. } public override int GetHashCode() { return base.z = Z.int Y. bool b1 = p1.GetType()) return false.9).x) && (y == p. OBJECT CLASS { // check for null and compare run-time types if(obj == null || GetType() != obj.WriteLine("h2 = " + h2).WriteLine("h1 = " + h1). } } // end class Point3D public class object1 { public static void Main() { Point p1 = new Point(5.GetHashCode(). Console.z.Equals(obj) && z == ((Point3D) obj). } // ^ XOR operation } // end class Point class Point3D : Point { int z. } public override int GetHashCode() { return x^y. Console.Equals(p2).Equals(p4).y). Console.7).6.9. } public override bool Equals(Object obj) { return base. 53 .9). this.4. Console.WriteLine("b1 = " + b1). bool b2 = p3.GetHashCode(). Point3D p3 = new Point3D(5. int h1 = p1.y = Y.6.WriteLine("b2 = " + b2).

class MyBaseClass { public static string CompanyName = "KXK". } class MyDerivedClass : MyBaseClass { public static void Main() { // create an instance of MyDerivedClass and assign values // to its fields MyDerivedClass m1 = new MyDerivedClass(). CHAPTER 4. m1.name = "John".e.cs using System. it returns a shallow copy of the current object.WriteLine("name = " + m2.age).54 } } The method protected object MemberwiseClone(). Console. i. Console. BUILT-IN CLASSES creates a shallow copy of the current object. m1.MemberwiseClone(). } } . // performs a shallow copy of m1 and assign it to m2 MyDerivedClass m2 = (MyDerivedClass) m1.MemberwiseClone(). public int age.age = 42. // object3. The following code shows how to copy an instance of a class using Object.WriteLine("age = " + m2. public string name.name).

55 .e. Thus we have three attributes: myName. age and sex. class Person1 { private string myName = "N/A". Sometimes the set of operations supported by an object is also referred to as the interface exposed by this object. The following program shows an example for class Person. We say the state of the object is defined by the attributes it supports and its behaviour is defined by the operations it implements. // Person1. defining the class) is called abstraction. Object-oriented programming is essentially programming in terms of smaller units called objects. myAge. The class also defines a set of functions (also called methods or operations) which can be invoked on its objects. Generally the data is hidden within the objects (instances) and can be accessed only through functions defined by its class (encapsulation). The Person is described by his name. One or more objects (instances) can be created from a class by a process called instantiation. private int myAge = 0.cs using System. The term passing a message to an object means invoking its operation. These private data members are only visible inside the body of class Person1. The process of deciding which attributes and operations will be supported by an object (i.Chapter 5 Object-Oriented Programming 5.1 Write your own class In CSharp we can write our own class. private char mySex = ’n’. Each object holds some data (fields or attributes) as defined by its class. An object oriented program is composed of one or more objects. mySex.

this. } } public char Sex { get { return mySex.myName) && (myAge==((Person1) o). this.myAge) && (mySex==((Person1) o). Age = " + Age + ".56 CHAPTER 5. Sex = " + Sex. } set { myName = value.myName = name.mySex = sex. } } public override string ToString() { return "Name = " + Name + ". } set { myAge = value. } . } // declare a Name property of type string public string Name { get { return myName.char sex) { this.int age. } } public int Age { get { return myAge.myAge = age. } public override bool Equals(object o) { if((myName==((Person1) o). OBJECT-ORIENTED PROGRAMMING // default constructor public Person1() { } // constructor public Person1(string name. else return false. } set { mySex = value.mySex)) return true.

Name = "Jane".Sex = ’m’. Console.WriteLine("name of person[0]: " + pmany[0]. bool same = person2. namely public string get_Name() . person2. To access these variable outside the class we use the special property methods Name. Console.myName).WriteLine("sex of person[1]: " + pmany[1]. Console.mySex).mySex).Equals(person3).WriteLine("Person details . These variable are visible only inside the body of class Person1.’m’). Console. Console. myAge. WRITE YOUR OWN CLASS public static void Main() { // create a new Person object using default constructor Person1 person1 = new Person1().Age = 31.Sex = ’f’.Sex = ’f’. } // end Main } 57 class Person1 defines three private member variables.WriteLine("same person = " + same). // Set some values on the person object person1. mySex. myName.WriteLine("Person details: " + person4.7.{0}".myName).’f’). Console. person2.Age = 31. Person1 person3 = new Person1().Name = "Jane".WriteLine("Person details .{0}". Person1 person4 = new Person1("otto".42.person3).’m’).person1). Console. // array of persons Person1[] pmany = new Person1[2].1. Console. and Sex. pmany[1] = new Person1("Ola". person3.Name = "Joe". pmany[0] = new Person1("Carl". Person1 person2 = new Person1(). person2. The CSharp compiler translates for example the Name property to a pair of methods.23.5. person1. person1. Age.WriteLine("Person details .{0}".WriteLine("Person details: " + person4.person2).Age = 99. person3. person3.

In some application it would be better to keep the class Person1 without the Main() method and have an extra file which calls the Person objects. class Person { public string myName = "N/A".cs only contains the class Person and no Main() method. this.char sex) { this. public char mySex = ’n’. this. } set { myName = value.cs using System.myName = name. } set { myAge = value.mySex = sex. // default constructor public Person() { } // constructor public Person(string name. OBJECT-ORIENTED PROGRAMMING public void set_Name(string value) { myName = value. } // declare a Name property of type string public string Name { get { return myName. } } public int Age { get { return myAge.58 { return myName. } } public char Sex . } The class Person1 contains the Main() method. The file Person. public int myAge = 0. // Person.myAge = age. } CHAPTER 5.int age.

WRITE YOUR OWN CLASS { get { return mySex.5. else return false. person2.cs using System. Person person2 = new Person().person1). } } To generate the Person. Age = " + Age + ". person2.Name = "Joe". } public override bool Equals(object o) { if((myName==((Person) o). } set { mySex = value.Sex = ’m’.dll file we run csc /t:library Person. } } public override string ToString() { return "Name = " + Name + ". Sex = " + Sex.Age = 99.cs contains the Main() method. person1.myName) && (myAge==((Person) o).Name = "Jane".mySex)) return true.{0}". // Set some values on the person object person1.myAge) && (mySex==((Person) o).Age = 31. Console.1. // PersonMain. 59 . class PersonMain { public static void Main() { // create a new Person object using default constructor Person person1 = new Person().cs The file PersonMain. person1.WriteLine("Person details .

{0}".cs PersonMain.WriteLine("Person details: " + person4. Console. An example is given below . // increment the age of person3 person3. person3.exe file we run csc /r:Person.Equals(person3).Sex = ’f’. person3. 5.42.60 CHAPTER 5.WriteLine("name of person[0]: " + pmany[0].Age).Age = 31.WriteLine("person3 new age: " + person3.Sex = ’f’.’m’).person3).’m’).2 Override Methods bool Equals().7. Console. Console. pmany[1] = new Person("Ola". } // end Main } To get the PersonMain.person2).Name = "Jane".mySex). person3.WriteLine("same person = " + same). // array of persons Person[] pmany = new Person[2].mySex).{0}". Person person3 = new Person(). we can also use the short-cut csc Person.WriteLine("sex of person[1]: " + pmany[1]. Console. Person person4 = new Person("otto".dll PersonMain. Console.23.cs However.WriteLine("Person details . bool same = person2.myName).WriteLine("Person details: " + person4. OBJECT-ORIENTED PROGRAMMING person2. pmany[0] = new Person("Carl". Console.’f’).cs to generate the PersonMain. Console.WriteLine("Person details .Age++. Console.exe file. object Clone() When we write our own class in most cases we should override the methods string ToString().myName).

Z-p2.X-p2. public class Point3D { public double X. } } An application of this class is .{1}.Format("({0}. } public override bool Equals(object o) { if((X==((Point3D) o).X-p2.X) && (Y==((Point3D) o).double z) = x.Z).Y) && (Z==((Point3D) o). OVERRIDE METHODS // Point3D.Y.Y)+(p1.X this. return o.Z-p2.2.Point3D p2) { return (p1. public double Y. } public object Clone() { object o = new Point3D(X.5. public double Z.Z)*(p1.X)+(p1.Z).Y.Z } Point3D(double x.X. = z. else return false.cs using System.Y)*(p1.Y this. } public override string ToString() { return String.Z)) return true.X)*(p1. public Point3D() { } // default constructor public { this. 61 // square of distance between two Points public double distance(Point3D p1.double y. = y.Y-p2.{2})".Y-p2.Z).

62 // Point3DMain.cs using System. Point3D p4 = new Point3D(0. double z = 4.0. // type conversion Console. double d = q. First we must declare our intention to use Vehicle as the base class of Car. double y = 3.p3).WriteLine("p1 = " + p1). double m = 1. CHAPTER 5.WriteLine("p4 = " + p4).0.0).3 Inheritance Inheritance is one of the primary concepts of object-oriented programming. bool r = p1.0. p4 = (Point3D) p3.0.b.z).n). } } 5. Point3D p2 = new Point3D(a. This is accomplished through the Car class declaration public class Car : Vehicle . Console. Console.WriteLine("r = " + r).Clone(). double a = 2.1. double b = 3. Point3D p1 = new Point3D(x.5.y.5.0.Equals(p2). double k = 2. In the next program we use inheritence. double c = 4.5.1.0.1.distance(p1. OBJECT-ORIENTED PROGRAMMING public class Point3DMain { public static void Main() { double x = 2. It allows us to reuse existing code.1. Point3D p3 = new Point3D(k.c).WriteLine("d = " + d). In the class Car we use code from the class Vehicle. Point3D q = new Point3D(). Console. double n = 7.m. The class Car is derived from class Vehicle.

int aTopSpeed. price = aPrice. } public virtual void print() { Console. and the keyword base call the base class constructor.WriteLine("Top Speed: {0} km/h".5.price).} public int getTopSpeed() { return topSpeed. } public double getPrice() { return price. Console. class Vehicle { private int weight. int displacement.WriteLine("Weight: {0} kg". private double price. private int topSpeed.weight).cs using System. Console. // MVehicle. public Vehicle() {} public Vehicle(int aWeight. .3. : .double aPrice.double aPrice) { weight = aWeight.WriteLine("Price: {0} Dollar". int horsepower. INHERITANCE 63 Then the colon.int aTopSpeed. C# supports single class inheritance only. } public int getWeight() { return weight.topSpeed). topSpeed = aTopSpeed.int aNumberCylinders. } } // end class Vehicle class Car { private private private : Vehicle int numberCylinders. public Car() { } public Car(int aWeight.

displacement = aDisplacement. Console.print().00.cs public interface Policy .30000. Console.aTopSpeed.Write("A car: "). and/or properties.aPrice) { numberCylinders = aNumberCylinders.120. they must define a contract. horsepower = aHorsepower.00). The reason interfaces only provide definitions is because they are inherited by classes and structs. Console. } } class myCar { public static void Main() { Vehicle aVehicle = new Vehicle(15000.print().300). } public int getDisplacement() { return displacement. methods.6. aVehicle. Console.120. but has no implementation.WriteLine("Diplacement: {0} cubic cm". Console.12000.64 CHAPTER 5. which must provide an implementation for each interface member defined. OBJECT-ORIENTED PROGRAMMING int aHorsepower.int aDisplacement) : base(aWeight.WriteLine("Cylinders: {0} ".WriteLine("").displacement). The only thing it contains are definitions of events. indexers.WriteLine("Horsepower: {0} ". // Policies. Since interfaces must be defined by inheriting classes and structs.numberCylinders). aCar. Console. Console.100. } public int getHorsepower() { return horsepower.Write("A vehicle: "). } public override void print() { base. The following program shows an example. Car aCar = new Car(3500.WriteLine("").print(). } } An interface looks like a class.horsepower). } public int getNumberCylinders() { return numberCylinders.

This feature can be used to write more generic (dynamically extensible) programs which receive names of classes at runtime. } } public class SilverPolicy : Policy { public double Rate(double p. and args[2]. } } public class GoldPolicy { public double Rate(double p.3. All policy classes implement the Policy interface except GoldPolicy which defines Rate without implementing policy. INHERITANCE { double Rate(double principal. if(n >= 3) r += 1. } } 65 Each policy provides a Rate method which returns the rate of interest for a given principal and for a given period.cs as .0) ? 10 : 12.int n) { double r = (p < 50000.cs to create Policies.cs program including Main accepts principal.int period). } public class BronzePolicy : Policy { public double Rate(double p. period and policy name as arguments args[0].int n) { return 7. } } public class PlatinumPolicy : Policy { public double Rate(double p.5. We compile investment.int n) { return (p < 25000.dll via csc /t:library Policies. args[1]. The investment. return r.int n) { return (n < 5) ? 9 : 11. We compile Policies.0) ? 8 : 10.cs Using reflection we can also create an instance of a class and invoke its member methods at runtime.

// methods.double q) { .cs We would execute the program.dll investment. or if they have different parameter types. for example. double amount = p*Math. double r = pol.n). or if they have different parameter kinds.Pow(1.Reflection. class Investment { public static void Main(string[] args) { double p = Double. We overload the method max() to find the maximum of numbers. // string to int Type t = Type. The methods of a class may have the same name if they have different numbers of parameters.Rate(p. // string to double int n = Int32.amount). OBJECT-ORIENTED PROGRAMMING csc /r:Policies.Parse(args[1]).cs using System. Policy pol = (Policy) Activator.GetType(args[2]). investment 60000 5 SilverPolicy.cs using System.0+r/100. using System.WriteLine("you will get {0:#. public class Maximizer { public class Maximum { public static double max(double p.Parse(args[0]).Policies // investment.66 CHAPTER 5. Console. } } 5.0.4 Overloading Methods Methods in a class can be overloaded.n).CreateInstance(t).00}".

Console.7 is {0}". // Complex.int.4.double q.5.1. Console.4.r). [] In the next program we overload + to add two complex numbers. 2. -. } public static double max(double p. } // end main } } Exercise.5 and 4. *. 5. return q.double r) { return max(max(p.1.4.int. } return max.1.int) to the program that find the maximum of four integer numbers.Length == 0) return 0.7)). \.WriteLine("maximum element in array = {0}".5. } public static double max(double[] list) { if(list. double[] array = new double[4]. double max = list[0]. array[3] = 2.cs using System. array[2] = 3. } 67 public static void Main(string[] args) { Console.max(3.9. 4.9)).max(array)). foreach(double val in list) { if(val > max) max = val.5.1.5 Operator Overloading Operators can be overloaded (operator overloading) such that +.WriteLine("maximum of 4.4. Add a method max(int.2.WriteLine("maximum of 3. array[1] = 5.9 is {0}".max(4. OPERATOR OVERLOADING if(p > q) return p. %.7. array[0] = 3. .q).

0).real.real = real. } } Exercise.2.0. Console.0).1.Complex c2) { c1. return c1. // enumeration. } } class ComplexMain { public static void Main() { Complex r1 = new Complex(1. public double imag.imag + c2.double imag) { this. this. // real part of complex number // imaginary part of number public Complex(double real.real. 5.r1.r1.6 Structures In CSharp we can also use structures.0.real + c2. There is no inheritance for structure. c1. The program also shows how enumeration can be used. d real) is given by z1 ∗ z2 = a ∗ c − b ∗ d + i(ad + bc).68 CHAPTER 5. The multiplication of two complex numbers z1 = a + ib and z2 = c + id (with a.WriteLine("Real: {0} Imaginary: {1}i".imag = c1. c.imag.imag). The objects are stored on the stack compared to classes which are stored on the heap. .imag = imag. b. Overload in the program also * for the multiplication of two complex numbers. Complex r2 = new Complex(2. r1 = r1 + r2.cs using System. OBJECT-ORIENTED PROGRAMMING public class Complex { public double real. Structures do not contain methods.real = c1. } public static Complex operator + (Complex c1.

a.5. // new copy of a is assigned to b b. Call the encapsulated methods through the delegate object. } // end main } 5. We can pass method m in class A. } class enumeration { public static void Main(string[] args) { ClubMember a. a. 1. Jackals. public int Age.a. 4. C# delegates are implemented in the . Declare a delegate object with a signature that exactly matches the method signature that we are trying to encapsulate. // Value types are automatically initialized a. struct ClubMember { public string Name.Name = "John". // a. 3. .Age. 2.Name. Define all the methods whose signature match the signature of the delegate object that we have defined in step 1.Age = 13.Age remains 13 Console. Thus the use of delegates involves four steps. ClubMember b = a. DELEGATES 69 enum MemberType { Lions.Delegate. The following C# program shows the above four steps. a. Create delegate object and plug in the methods that we want to encapsulate.NET framework as a class derived from System.Eagles. public MemberType Group.a.WriteLine("Member {0} is {1} year old and belongs to group of {2}".Group = MemberType.7 Delegates A delegate in C# allows us to pass methods of one class to objects of other classes that can call those methods. Eagles.Age = 17. Elefant. This concept is familiar to C++ where one uses function pointers to pass functions as parameters to other methods in the same class or in another class. to class B and class B will be able to call method m in class A.Group). Dogs }.7. We can pass both static and instance methods. wrapped in a delegate.

MyDelegate d1 = new MyDelegate(c2. OBJECT-ORIENTED PROGRAMMING // Step 1. MyDelegate d3 = d1 + d2. MyDelegate d2 = new MyDelegate(c2. CHAPTER 5. } } // end class Class1 // Step 3. Define methods that match with the signature // of delegate declaration class Class1 { public void delegateMethod1(string input) { Console.70 // Delegate. // Step 2.input). } } // end class Class3 .WriteLine("delegateMethod2: the input to the method is {0}".delegateMethod2). Create delegate object and plug in the methods class Class2 { public MyDelegate createDelegate() { Class1 c2 = new Class1(). } public void delegateMethod2(string input) { Console. Call the encapsulated method through the delegate class Class3 { public void callDelegate(MyDelegate d. Declare a delegate with the signature of the // encapsulated method public delegate void MyDelegate(string input).input). return d3.delegateMethod1).string input) { d(input).cs using System.WriteLine("delegateMethod1: the input to the method is {0}". } } // end class Class2 // Step 4.

DELEGATES 71 class Driver { public static void Main() { Class2 c2 = new Class2(). // MyDelegate."calling the delegate"). } } // end method CompareNames() .n2) > 0) { return 1. // type conversion string n2 = ((Name) name2).Compare(n1. c3. } public static int CompareFirstNames(object name1.7. Class3 c3 = new Class3().Compare(n1. Here we use delegates to compare strings. public class Name { public string FirstName = null. } // end Main } The output is: delegateMethod1: the input to the method is calling the delegate delegateMethod2: the input to the method is calling the delegate Another example is given below.cs using System. // this is the delegate declaration public delegate int Comparer(object obj1.object name2) { string n1 = ((Name) name1). public Name(string first. MyDelegate d = c2. } else if(string. public string LastName = null.createDelegate().FirstName. // type conversion if(string.callDelegate(d.n2) < 0) { return -1.FirstName. } else { return 0.5. LastName = last.string last) { FirstName = first.object obj2).

// the delegate instantiation Comparer cmp = new Comparer(Name. sd.names[j])>0) . names[3] = new Name("Ola". names[1] = new Name("Carl". } } // end class Name class SimpleDelegate { Name[] names = new Name[4]."Cooper").j<names. sd. Console. names[2] = new Name("Rolf".CompareFirstNames). Console. } static void Main() { SimpleDelegate sd = new SimpleDelegate(). PrintNames().i++) { for(int j=i."Jones"). public SimpleDelegate() { names[0] = new Name("John"."Xenon"). // observe the delegate argument sd.72 CHAPTER 5.Length."Smithlone").j++) { // using delegate "compare" just like a normal method if(compare(names[i].WriteLine("\nAfter Sort:\n").i<names. OBJECT-ORIENTED PROGRAMMING public override string ToString() { return FirstName + " " + LastName.WriteLine("\nBefore Sort:\n").PrintNames().Length.Sort(cmp). } public void Sort(Comparer compare) { object temp. for(int i=0.

5. } // end if } } } // end method Sort public void PrintNames() { Console. names[j] = (Name) temp.ToString()). foreach(Name name in names) { Console. } } // end method PrintNames() } 73 . names[i] = names[j].WriteLine(name.WriteLine("Names:\n").7. DELEGATES { temp = names[i].

long.BinaryReader can be used for writing and reading primitive data types byte.Chapter 6 Streams and File Manipulations 6.BinaryWriter and System. Reading is the transfer of data from a stream into a data structure.2 Binary File Manipulations System. float. char and also the data type string and StringBuilder to a stream (binary file manipulation). 6. 3) Streams can support seeking. Seeking is the query and modifying of the current position within a stream.1 Introduction A stream is a sequence of bytes. int. The Stream class and its subclasses provide a generic view of data sources and repositories.IO. bool.IO. isolating the programmer from the specific details of the operating system and underlying devices. 2) Streams can be written to. such as an array of bytes. Streams involve the following three operations: 1) Streams can be read from. Writing is the transfer of data from a data structure into a stream. short. A byte is 8 bits. double. 74 .

Text.cs using System.6. BINARY FILE MANIPULATIONS // BinaryIO1.b).Close().OpenWrite("info. double d = br. bw.Write(b). s.double d.OpenRead("info. ReadData(). using System. s.dat").IO.Close(). char c = br. using System. bool b = br.i.char c.3.2.ReadDouble().c. bw.Write(c). using System.WriteLine("{0}. bw.Close(). int i = br.true).Close().Write(i). } private static void ReadData() { Stream s = File. bw.{2}.d. BinaryWriter bw = new BinaryWriter(s).dat").{1}. class BinaryIO1 { private static void WriteData(int i.ReadBoolean(). bw.’y’.Write(d).ReadInt32().cs using System.{3}". br. BinaryReader br = new BinaryReader(s). } } // BinaryIO2. } public static void Main(string[] args) { WriteData(12345.IO. using System.Text.bool b) { Stream s = File.14159. Console.ReadChar(). 75 .

string sb = br. s. standard input. Console.{1}".Write) and the asynchronous methods FileStream. The class FileStream is useful for reading and writing files on a file system.Write(t).sb). however.Close().sb).76 CHAPTER 6. bw.dat").ToString()).WriteLine("{0}. string t = br. } public static void Main(string[] args) { StringBuilder sb = new StringBuilder("Hello World!").3 Text File Manipulation Reading a text file.Read and FileStream.Close(). either synchronously or asynchronously. } } 6. bw. with signigicant performance consequences for the synchronous methods (FileStream. ReadData().StringBuilder sb) { Stream s = File.BeginRead and FileStream. and so on). as well as other file-related operating system handles (including pipes.dat"). FileStream defaults to opening files synchronously.ReadString().t. s.BeginWrite). WriteData("Hello Egoli". BinaryWriter bw = new BinaryWriter(s).Write(sb. BinaryReader br = new BinaryReader(s).Close().Close(). FileStream buffers input and output for better performance.OpenWrite("info.ReadString(). the mode will affect the performance of these methods. but . standard output. br. } private static void ReadData() { Stream s = File. The FileStrean class can open a file in one of two modes. STREAMS AND FILE MANIPULATIONS class BinaryIO2 { private static void WriteData(string t. // write length-prefixed string bw. Both sets of methods will work in either mode.OpenRead("info.

6.3. TEXT FILE MANIPULATION

77

provides a constructor to open files asynchronously. FileStream objects support random access to files using the FileStream.Seek method. The Seek method allows the read/write position to be moved to any position within the file. This is done with byte offset reference point parameters. The byte offset is relative to the seek reference point, which can be the beginning, the current position, or the end of the underlying file, as represented by the three properties of the SeekOrigin class. We convert the array of bytes into an ASCII text for displaying it on the console. // readfile.cs using System; using System.IO; using System.Text; // for encoding class ReadFile { public static void Main(string[] args) { Stream s = new FileStream(args[0],FileMode.Open); int size = (int) s.Length; byte[] buffer = new byte[size]; s.Read(buffer,0,buffer.Length); s.Close(); string text = Encoding.ASCII.GetString(buffer); Console.WriteLine(text); } } Writing to a file (text mode). We append the text provided by the line string text = "all the good men and women" + "\r\n"; to the file provided by args[0]. // writefile.cs using System; using System.IO; using System.Text; // for encoding class WriteFile { public static void Main(string[] args) { Stream s = new FileStream(args[0],FileMode.Append,FileAccess.Write);

78

CHAPTER 6. STREAMS AND FILE MANIPULATIONS string text = "all the good men and women" + "\r\n"; // append end // of line characters byte[] buffer = Encoding.ASCII.GetBytes(text); s.Write(buffer,0,buffer.Length); s.Close(); // also flushes the stream }

} Writing the date and time into a file using the DateTime class.. // placeorder.cs using System; using System.IO; class PlaceOrder { public static void Main(string[] args) { DateTime dt = DateTime.Now; string today = dt.ToString("dd-MMM-yyyy"); string record = today + "|" + String.Join("|",args); StreamWriter sw = new StreamWriter("order.txt",true); sw.WriteLine(record); sw.Close(); } } The useful classes in reading/writing text files are: StreamReader and StreamWriter. Given the file datain.txt with the two lines Green 4750 3000.40 Bakley 3451 2800.50 the following program reads the file line by line and displays it on the Console and also writes it to the output file dataout.txt. // Filemanipulation.cs using System; using System.IO; class FileManipulation { static void Main(string[] args) {

6.4. BYTE BY BYTE MANIPULATION FileInfo fr = new FileInfo(@"c:\csharp\datain.txt"); StreamReader reader = fr.OpenText(); string sline; string[] substrings; char[] separators = { ’ ’,’,’,’\t’ }; string name; int ID; float gpa; StreamWriter writer = new StreamWriter(@"c:\csharp\dataout.txt",false); sline = reader.ReadLine(); while(sline != null) { substrings = sline.Split(separators,3); name = substrings[0]; ID = int.Parse(substrings[1]); gpa = float.Parse(substrings[2]); Console.WriteLine("{0} {1} {2}",name,ID,gpa); writer.WriteLine("{0} {1} {2}",name,ID,gpa); sline = reader.ReadLine(); } writer.Flush(); writer.Close(); } }

79

6.4

Byte by Byte Manipulation

For reading and writing bytes we use the methods ReadByte() and WriteByte(). The type conversion to char is necessary in the following program. What happens if we remove (char) ? // BytebyByte.cs using System; using System.IO; public class BytebyByte { public static void Main(string[] args) { FileStream s = new FileStream(args[0],FileMode.Open,FileAccess.Read, FileShare.Read); BufferedStream bs = new BufferedStream(s); while(bs.Length > bs.Position)

ReadByte().Close().arg[1]. } } .SeekOrigin.Close(). } } public static void Main(string[] arg) { Copy(arg[0]. } } bs.Open).IO.Begin).int pos) { try { FileStream sin = new FileStream(from.Close(). sin.Write((char) bs. } In the following example we copy byte by byte a file into another file.FileName).FileMode.0). // TestFile. STREAMS AND FILE MANIPULATIONS { Console.Close(). using System. sout. class TestFile { static void Copy(string from.WriteByte((byte) ch).e.WriteLine("--file {0} not found". while(ch >= 0) { sout. int ch = sin. // type conversion ch = sin. s.Seek(pos.ReadByte().string to. FileStream sout = new FileStream(to.80 CHAPTER 6.FileMode.cs using System. } catch (FileNotFoundException e) { Console.Create). } sin.ReadByte()).

Position) { char ch = (char) bs. or a connected graph of objects (a set of objects with some set of references to each other). 81 FileStream fin = new FileStream("data. if(ch == cl) countcl++.IO. Extend the program so that it also counts the number of rectangular brackets (left and right) and parentheses (left and right).5. .cs using System.Open. BufferedStream bs = new BufferedStream(fin).Read). // employee.5 Object Serialization Often we want to store a complete object in a stream. int countcl = 0.cs using System.WriteLine("countcl = " + countcl).WriteLine("countcr = " + countcr). } // end Main } Exercise.Length > bs. By serialization we mean converting an object. // Oops1. using System. if(ch == cr) countcr++. Console. This is achieved by a process called object serialization. OBJECT SERIALIZATION In the next program we count the number of curly brackets in a file. char cr = ’}’. int countcr = 0. while(bs. stored within memory into a linear sequence of bytes. class Oops { public static void Main() { char cl = ’{’. } // end while fin. 6. This string of bytes contains all of the information that was held in the object started with.ReadByte().Close(). Console.6.FileAccess.dat".FileMode.

string job.Serialize(s.Serialization. // binsertest1.Format("{0} is a {1} and earns {2}".Close().Runtime. public string Job. s.Salary). private static void WriteEmployee(Employee emp) { Stream s = File.Runtime.IO.emp).Binary. [Serializable] public class Employee { public string Name. STREAMS AND FILE MANIPULATIONS using System.Name.Serialization. public Employee(string name. using System. public double Salary. } public Employee() { } // we override the ToString() method of System. bf. Salary = salary. class BinarySerializatioTest1 { static BinaryFormatter bf = new BinaryFormatter(). Job = job. using System.Object.Job.cs using System.bin").OpenWrite("emp.double salary) { Name = name.82 CHAPTER 6. } . } } // end class Employee end file In the following program we apply now object serialization to Employee. // This method is invoked whenever an Employee object // is to be converted to a string public override string ToString() { return String.Formatters.

xml containing information (id.44000).salary) about employees. // displays emp.WriteLine(emp). ReadEmployee(). } } 6. Console.6."Clerk".Deserialize(s). XML DOCUMENTS 83 private static void ReadEmployee() { Stream s = File. job.6.bin"). Given below is the file emp. Employee emp = (Employee) bf.Close(). s.OpenRead("emp.0"?> <employees> <employee id="101"> <name> John </name> <job> manager </job> <salary> 72000 </salary> </employee> <employee id="102"> <name> Jane </name> <job> steno </job> <salary> 23000 </salary> </employee> <employee id="103"> <name> Jim </name> <job> salesman </job> <salary> 36000 </salary> </employee> <employee id="104"> <name> Jill </name> <job> clerk </job> <salary> 45000 </salary> </employee> .ToString() } public static void Main(string[] args) { Employee emp = new Employee("Jack".NET framework provides an XML parser for reading and modifying XML documents.name.6 XML Documents The . WriteEmployee(emp). <?xml version="1. There are five employees.

class ListEmployees { public static void Main() { XmlDocument doc = new XmlDocument().sal). foreach(XmlNode emp in list) { // obtain value of id attribute of the employee tag string id = emp.FirstChild.Value. and salary of each employee in the file emp. // addemp.Value. class AddEmployee { public static void Main(string[] args) .cs using System.xml"). name.xml. // obtain value of salary subtag of the employee tag string sal = emp["salary"].cs takes informations from the command line (id. // listemp. STREAMS AND FILE MANIPULATIONS <employee id="105"> <name>Jeff</name> <job>CEO</job> <salary>105000</salary> </employee> </employees> The program listemp.xml. } } } The program addemp. using System.Attributes["id"].Xml. using System. Console. job. // obtain a list of all employee element XmlNodeList list = doc.Xml.cs displays id.cs using System. // load employee.xml in XmlDocument doc.84 CHAPTER 6.id.Load("emp. salary) and makes a new entry in the file emp.WriteLine("{0}\t{1}".GetElementsByTagName("employee").

AppendChild(name).Load("emp. name. XmlNode sal = doc."").SetAttribute("id". sal.InnerText = args[3].args[0]).AppendChild(emp). } } We execute the program with (for example) addemp 105 willi president 50000 85 .CreateNode("element"."job". emp.Save("emp.xml").""). XML DOCUMENTS { XmlDocument doc = new XmlDocument()."name". // add the newly created employee tag to the root (employees) tag doc.CreateElement("employee"). // create a new employee element and value of its attribute XmlElement emp = doc.6.xml"). // save the modified document doc.AppendChild(sal). doc. XmlNode job = doc. // make name tag a subtag of newly created employee tag emp."").InnerText = args[2].6.CreateNode("element".CreateNode("element". job.DocumentElement. emp. // create a name tag and st its value XmlNode name = doc.InnerText = args[1].AppendChild(job)."salary". emp.

Drawing namespace provides access to GDI + basic graphics functionality. The drawing methods are DrawString(). The System. Simple or complex shapes can be rendered in solid or transparent colors. the text we want to display.float height) Every method in the Graphics class has to be accessed by creating an object of that class. In this namespace we find the Form class and many other controls that can be added to forms to create user interfaces. DrawArc() and DrawImage().Pen. The Graphics object provides methods for drawing a variety of lines and shapes. All we have to do is to apply the relevant methods appropriately.1 Drawing Methods The Windows. DrawEllipse(). Ellipse.Brush. To fill in an area. The method DrawEllipse() is given by DrawEllipse(System. and outline shapes are created using a Pen object. such as a rectangle or a closed curve. open curves.Drawing. DrawLine(). We can easily update the above program to render other graphical shapes like Rectangle. or using user-defined gradient or image textures. DrawRectangle().e.Chapter 7 Graphics 7. The method DrawString() takes five arguments DrawString(string. i. etc.Font. a Brush object is required.Forms namespace contains classes for creating Windows based applications. DrawPolygon().int X.float y. 86 .int Y) The first argument is a string. The last two arguments is the position where we put the string. DrawPie(). Lines.float width. Using DrawImage() we can display an image.float x.

Pen.Graphics.y). The default Graphics unit is Pixel.Windows.Drawing. g.Drawing.y)}).y). } } The method DrawPolygon(System.DrawString("Hello C#". DRAWING METHODS 87 Using the Pen class we can specify colour of the border and also the thickness.new SolidBrush(Color.cs using System. new Point(x. using System. The following program shows how do draw two triangles using this method.Tomato). using System.new Font("Verdana".new Point(x. By applying the PageUnit property.Forms. The Brush is applied for filling shapes such as SolidBrush and HatchStyleBrush. // HelloGraphics.PaintEventArgs e) { Graphics g = e.DrawRectangle(new Pen(Color.3). } private void f1_paint(object sender.20. } public static void Main() { Application. draws a polygon for a given set of points.100). new Point(x.1.20.7.Run(new Hello()). 40.Paint += new PaintEventHandler(f1_paint).y).Pink.150. we can change the unit of measurement to Inch and Millimeter. public class Hello : Form { public Hello() { this. .new Point[]{ new Point(x. g.y).40).new Point(x.y).20).new Point(x. The Pen class is applied for drawing shapes.

255)}).Windows. GRAPHICS class Triangle : Form { public Triangle() { this. Point(250. Pen pen1 = new Pen(Color.150)}).float x.Green.Run(new Triangle()). Point[]{new Point(50.float height).Windows.float angleY).Drawing.float y.155). Point(50.float angleX. } public void draw_triangle(Object sender. CHAPTER 7. g.float y.new Point(250. float width.Forms.float width.DrawPolygon(pen1.Drawing.cs using System.2).float x. Pen pen2 = new Pen(Color.new Point(250. public class Fill : Form { public Fill() .DrawPolygon(pen2.2).float x.float height). using System. } } The following program shows how to use FillRectangle(Brush. using System.float height. FillEllipse(Brush.cs using System.new new g.150).float width.50). FillPie(Brush.Graphics.Blue. using System. public static void Main() { Application.new new } Point[]{new Point(150. using System.Paint += new PaintEventHandler(draw_triangle).155). // Fill.88 // MyPolygon.Forms.PaintEventArgs e) { Graphics g = e.float y.

40. The alpha-value is implicit 255 (no transparency). COLOR CLASS { this.Forms. Green. } } 89 7. Alpha is also known as transparency where 255 is totally solid and 0 is totally transparent.0).0.blue) we call for example Color myColor = Color. using System.100.FromArgb(0.blue) we call for example Color myColor = Color. Red. } public static void Main() { Application.FillEllipse(new SolidBrush(Color.red.Yellow).50.2.90).cs using System.2 Color Class The Color class provides “constants” for common colors such as White.FillPie(new SolidBrush(Color. } private void fillpaint(object sender.40. g. // draw.15.120).0. Pink.Graphics.15.Windows.200. using System. To create a Color structure from the specified 8-bit Color (red. g. Black.125).Drawing.FillRectangle(new SolidBrush(Color.7.Run(new Fill()).FromArgb(51. Blue.Red).255.150.green.PaintEventArgs e) { Graphics g = e.green. To create a Color structure from the four ARGB component (alpha.255.150). public class Draw : Form { public Draw() { } // default constructor protected override void OnPaint(PaintEventArgs e) .200.Paint += new PaintEventHandler(fillpaint).Blue). g.50.

Text = "OK".45. .Graphics. PointF pointF = new PointF(30.20). public ColorD() { b. e. myPen.DrawEllipse(myPen. Pen myPen = new Pen(Color.30.Pixel).1.Controls.Bold.cs using System. ColorDialog clg = new ColorDialog(). } public static void Main() { Application. Font font = new Font(fontFamily. using System.Width = 50.Graphics.1. SolidBrush solidbrush = new SolidBrush(Color.30.Location = new Point(50.Graphics.45. using System.30. public class ColorD : Form { Button b = new Button().DrawLine(myPen.10).Red).90 CHAPTER 7.40.DrawBezier(myPen. e. An example is given in the followsing program // ColorD.font.Windows.15.new Rectangle(33. TextBox tb = new TextBox().Click += new EventHandler(b_click).GraphicsUnit.255.50). First we have to create an object of ColorDialog class ColorDialog cd = new ColorDialog().45.DrawString ("Hello".50)).Drawing. tb.0)).15.Forms.solidbrush.FontStyle.Add(b).Run(new Draw()).Graphics. } } In C# the user can choose a color by applying the ColorDialog class appropriatly.pointF). b. this.65). e.24.0.FromArgb(51.87. GRAPHICS { FontFamily fontFamily = new FontFamily("Times New Roman"). e.

System. bnclick. bnclick = new Button(). class WinHello : Form { private Button bnclick. System. bnclick.Add(tb).Me".Windows.Add(bnclick). Size = new Size(400. However. Inside the Button class.Drawing.ComponentModel.Run(new ColorD()). .400). BUTTON AND EVENTHANDLER this.EventArgs e) { clg. Closing += new CancelEventHandler(WinHello_Closing). } public static void Main(string[] args) { Application.ShowDialog(). bnclick. public WinHello() { Text = "Hello World". tb. the Click member is exactly like a private field of type EventHandler.Forms.60). System.Size = new Size(60.Location = new Point(20.3 Button and EventHandler The Button class defines a Click event of type EventHandler. Controls.7. } public void b_click(object sender.3. // Winhello. } } 91 7.Click += new EventHandler(bnclick_Click). bnclick. The operator += adds a handler for the event.Controls. outside the Button class.Text = "Click. the Click member can only be used on the left-hand side of the += and -= operators.24). and the -= operator removes a handler for the event.Color.BackColor = clg.cs using using using using System.

MessageBoxButtons.Run(new WinHello()). GRAPHICS private void bnclick_Click(object sender.Controls.YesNo.CancelEventArgs ev) { if(MessageBox.Cancel = true. = new TextBox(). } } We can create a Font selection dialog box using the FontDialog class.No) ev. .MessageBoxIcon.Click += new EventHandler(b_click). using System.Controls.Add(b).cs using System. b.Show("Hello Egoli!!!!".Information).Drawing.Location = new Point(50. public class { Button b = TextBox tb FontDialog Fonts : Form new Button().MessageBoxIcon. using System."Confirm exit".Text = "OK".OK. this.Question) == DialogResult.Forms. flg = new FontDialog(). this. } // Initialize the main thread // using Single Threaded Apartment (STA) model public static void Main() { Application.Add(tb). public Fonts() { b. tb.92 } CHAPTER 7.EventArgs ev) { MessageBox."Button Clicked".Windows.50).Show("Are you sure?". } private void WinHello_Closing(object sender. The following program gives an example // Fonts. MessageBoxButtons.

bmp"). DISPLAYING IMAGES } public void b_click(object sender. } public static void Main(string[] args) { Application.Forms.cs using using using using System.4 Displaying Images Next we provide a program that displays images using the method DrawImage.Windows. } public static void Main() { Application.Font.EventArgs e) { flg. gif or jpeg. this. System.Drawing. . public class Texturedbru : Form { public Texturedbru() { this. g. System.DrawImage(bgimage.Run(new Texturedbru()). } public void Text_bru(object sender.Drawing.7.Font = flg.Drawing2D.Graphics. } } 93 7. System. // mydrawim.Run(new Fonts()).600).20.Paint += new PaintEventHandler(Text_bru). Image bgimage = new Bitmap("forest. The file formats could be bmp.1000.20.4.Text = "Using Texture Brushes".ShowDialog(). tb.PaintEventArgs e) { Graphics g = e.

} } 7. g.50. System.450. this.Forms.Graphics. System.bmp").Drawing2D. } public static void Main() { Application.FillEllipse(bgbrush. } public void Text_bru(object sender.100. We create a Button and clicking on it switches the color of the circle from red to blue and vice versa.FillEllipse(bgbrush.cs .Drawing. g.FillRectangle(bgbrush. g. Image bgimage = new Bitmap("forest.500. // MyOnPaint. public Texturedbru() { this.5 Overriding OnPaint The next program shows how to override OnPaint().150.PaintEventArgs e ) { Graphics g = e.Paint += new PaintEventHandler(Text_bru).94 } } Another option to display the picture is // textbru. CHAPTER 7.300).Drawing.Run(new Texturedbru()).130). GRAPHICS public class Texturedbru : Form { Brush bgbrush.300).150.50. bgbrush = new TextureBrush(bgimage).Windows.450.cs using using using using System.Text = "Using Texture Brushes".350. System.

class Draw : Form { private SolidBrush b = new SolidBrush(Color.Color = Color. } else { b. } // end OnPaint void HandleClick(object sender.EventArgs e) { this.Add(button1).Click += new EventHandler(HandleClick).diameter. using System. int x = 50.Blue) { b. if(b.diameter).Red).FillEllipse(b. Controls. } e. } } 95 .Blue. } protected override void OnPaint(PaintEventArgs e) { int diameter = 200.Forms.220).Refresh(). public Draw() { Button button1 = new Button().Color = Color. button1.Run(new Draw()).x. int y = 30.Graphics.5.Color == Color.7.Windows.Drawing.Text = "Click Me". OVERRIDING ONPAINT using System. button1.y.Red. } public static void Main() { Application.Location = new Point(210. using System. button1.

Restore(gs).Append). GraphicsState gs = g. CHAPTER 7. float x2 = (ClientSize.0f. } private void TimerEvent(Object myObject.Run(new TimerVector()). float x1 = ClientSize.x2.EventArgs myEventArgs) { Invalidate().Save().RotateTransform(rot.Height/2. .cs using using using using System. // Rotate.Width/4. Pen myPen = new Pen(Color. g. } public TimerVector() { rot = 0.AntiAlias. GRAPHICS class TimerVector : Form { float rot. public static void Main() { Application.Append).TranslateTransform(-centerx. float centerx = ClientSize. rot = (rot + 1)%360. float centery = ClientSize.Width*3)/4.SmoothingMode = SmoothingMode.Black.y1.DrawLine(myPen.MatrixOrder.Drawing.Height/4.y2). System. float y2 = (ClientSize.Width/2.-centery).Forms.Drawing2D. float y1 = ClientSize.TranslateTransform(centerx. System.MatrixOrder.x1.Windows.Graphics.3). g. g. System.96 Another example we consider a rotation line.centery. g.Height*3)/4. g.Drawing. g. } protected override void OnPaint(PaintEventArgs pea) { Graphics g = pea.

true). private Point playerPosition = new Point(0. OVERRIDING ONPAINT Timer t = new Timer(). public Flicker() { ClientSize = new Size(500. } set 97 . t.Text += " " + this. using System.Drawing.AllPaintingInWmPaint. SetStyle(ControlStyles.Text = DateTime.DoubleBuffer. SetStyle(ControlStyles.500).5. t.Enabled = true.50).PlayerPosition. t. } private Point PlayerPosition { get { return this.Start(). t. this. class Flicker : Form { private Timer t = new Timer().Interval = 100. using System.true).Interval = 40.Tick += new EventHandler(TimerOnTick). private Size playerSize = new Size(50.Tick += new EventHandler(TimerEvent).Now. this.cs using System. t. this. SetStyle(ControlStyles.ToString().true).Forms.EventArgs e) { this.0). } } Another example is // Flicker.Windows. t.UserPaint.ToString().Refresh(). } private void TimerOnTick(object sender.KeyDown += new KeyEventHandler(OnKeyPress).playerPosition.7.

Width-this.X+this.playerPosition.Width).Width.PlayerPosition.this.PlayerPosition.playerPosition.playerSize. GRAPHICS { if(value.playerPosition.KeyValue == 38) { this.Height-this.this.X. } if(e.Height.PlayerPosition. } else { this. } if(value.98 CHAPTER 7. .playerSize.PlayerPosition. } else if(value.X+this.PlayerPosition.Height > this.PlayerPosition = new Point(this.KeyEventArgs e) { if(e.X-this. } else if(value.playerPosition.playerSize.Height.playerPosition.PlayerPosition = new Point(this.Height) { this.playerSize.Y = 0.playerSize.ClientSize.X = value.Y < 0) { this.Width > this.X = this.Y+this.Y = value.X < 0) { this.ClientSize. } else { this. } if(e.playerSize.X = 0.playerSize.Width) { this.ClientSize.Y-this.KeyValue == 37) { this.Y). } } } private void OnKeyPress(object sender.Y = this.playerPosition.KeyValue == 39) { this.Y.this.Width.Y).PlayerPosition.ClientSize.X.PlayerPosition = new Point(this.

7.5. OVERRIDING ONPAINT }

99

if(e.KeyValue == 40) { this.PlayerPosition = new Point(this.PlayerPosition.X,this.PlayerPosition.Y+this.playerSize.Height); } } protected override void OnPaint(PaintEventArgs e) { e.Graphics.FillRectangle(new SolidBrush(Color.Red),this.PlayerPosition.X, this.playerPosition.Y,this.playerSize.Width, this.playerSize.Height); } public static void Main() { Application.Run(new Flicker()); } }

Chapter 8 Events
Event handling is familiar to any developer who has programmed graphical user interfaces (GUI). When a user interacts with a GUI control (e.g., clicking a button on a form), one or more methods are executed in response to the above event. Events can also be generated without user interactions. Event handlers are methods in an object that are executed in response to some events occuring in the application. To understand the event handling model of the .NET framework, we need to unterstand the concept of delegate. A delegate in C# allows us to pass methods of one class to objects to other classes that can call those methods. We can pass method m in class A, wrapped in a delegate, to class B and class B will be able to call method m. We can pass both static and instance methods. An event handler in C# is a delegate with a special signature, given below public delegate void MyEventHandler(object sender,MyEventArgs e) The first parameter (sender) in the above declaration specifies the object that fired the event. The second parameter (e) holds data that can be used in the event handler. The class MyEventArgs is derived from the class EventArgs. EventArgs is the base class of more specialized classes, like MouseEventArgs, ListChangedEventArgs, etc. Thus an event is a notification sent by a sender object to a listener object. The listener registers an event handler method with the sender. When the event occurs the sender invokes event handler methods of all its registered listerners. The event handler is registered by adding +=. The -= operator removes the handler from the event. As an example we set up two classes A and B to see how this event handling mechanism works in .NET framework. The delegates require that we define methods with the exact same signature as that of the delegate declaration. Class A will provide event handlers (methods with the same signature as that of the event declaration). It will create the delegate objects and hook up the event handler. Class A will then pass the delegate objects to class B. When an event occurs in class B, it will execute the event handler method of class B. 100

101 // MyHandler.cs using System; // Step 1. Create delegate object public delegate void MyHandler1(object sender,MyEventArgs e); public delegate void MyHandler2(object sender,MyEventArgs e); // Step 2. Create event handler methods class A { public const string m_id = "Class A"; public void OnHandler1(object sender,MyEventArgs e) { Console.WriteLine("I am in OnHandler1 and MyEventArgs is {0}",e.m_id); } public void OnHandler2(object sender,MyEventArgs e) { Console.WriteLine("I am in OnHandler2 and MyEventArgs is {0}",e.m_id); } // Step 3. Create delegates, plug in the handler and register // with the object that will fire the events public A(B b) { MyHandler1 d1 = new MyHandler1(OnHandler1); MyHandler2 d2 = new MyHandler2(OnHandler2); b.Event1 += d1; b.Event2 += d2; } } // end class A // Step 4. Call the encapsulated method through the delegate (fires events) class B { public event MyHandler1 Event1; public event MyHandler2 Event2; public void FireEvent1(MyEventArgs e) { if(Event1 != null) { Event1(this,e); } } public void FireEvent2(MyEventArgs e) { if(Event2 != null) { Event2(this,e); }

FireEvent1(e1).cs using System. b.Location = new Point(40. } // end Main } CHAPTER 8.FireEvent2(e2).40).Click += new EventHandler(HandleClick1). We create two buttons each of them fires an event.Size = new Size(60.Forms. MyEventArgs e1 = new MyEventArgs(). using System.m_id = "Event args for event 2". b.m_id = "Event args for event 1". . Button button2 = new Button(). A a = new A(b). Controls. class MyForm : Form { MyForm() { // button1 top left corner Button button1 = new Button(). button2.40). MyEventArgs e2 = new MyEventArgs(). button1.Windows.102 } } // end class B public class MyEventArgs { public string m_id. e1. EVENTS The next program shows GUI event handling in C#.Add(button1). button1. using System. // evthand. button2. } // end class MyEventArgs class Driver { public static void Main() { B b = new B().Text = "Button".Drawing. e2.

EventArgs e) { MessageBox.Run(new MyForm()).EventArgs e) { Console. button2. } void HandleClick2(object sender.Show("The click event fire!"). } void HandleClick1(object sender. Controls.Add(button2).WriteLine("Console click fire!"). } } . } public static void Main() { Application.Click += new EventHandler(HandleClick2).103 button2.Text = "New Button".

Start() method starts a process resource by specifying the name of a document or application file and associates the resource with a new process component. Thus we can start other applications from within our application.exe").ProcessName. It counts again from 0 to 2000 and then kills the winhlp32.Diagnostics.exe process using the Kill() method.cs using System. Console.Chapter 9 Processes and Threads 9. int id = p. The Process. class Processtest { public static void Main() { Process p = Process. winhlp32.WriteLine("id = " + id).1 Processes A process in its simplest form is a running application. Each process has an Id number.exe and asynchronously counts up from 0 to 100001.WriteLine("StartTime = " + started).Start("notepad.WriteLine("name = " + name). DateTime started = p.StartTime.Id.exe. The Process class provides access to local and remote processes and enables us to start and stop local system processes. Console. 104 . using System. then destroys the notepad. The program below launches notepad. Console. // process1.exe process. string name = p.

That thread counts from 0 to 1 while the main thread counts from 0 to 5.Kill(). Thread thread = new Thread(job). } } 105 If we also want to load a file (for example process2.j++) Console. The detect process completion we use the method WaitForExit() 9. for(int j=0. // Threads0.Start("winhlp32.9.Kill().2.i<100001. Thus the code creates a new thread which runs the ThreadJob method.exe we change this line to Process p = Process. w. for(int i=0. local variables.NET Base Class Library (BCL) the System.cs is the simple example.Start("notepad. public class Threads0 { static void Main() { ThreadStart job = new ThreadStart(ThreadJob)."c:\\csharp\\process2. p.2. Threads are part of the same process which execute concurrently. We create a Thread instance by passing it an object of ThreadStart delegate which contains a reference to our ThreadJob method. There may be more than one thread in a process.exe".j<2000. and starts it. using System.cs").2 9. and program counter.WriteLine(j). The following program Threads0.cs) with notepad.WriteLine(i).Threading namespace provides various classes for executing and controlling threads. A thread is also called a lightweight process. .exe"). It has it own execution stack. In . THREADS Process w = Process.1 Threads Introduction A thread is an execution stream within a process.cs using System.Threading.i++) Console.

WriteLine("Other thread: {0}". i++.106 thread. PROCESSES AND THREADS int i = 0. } // end while } // end ThreadJob } An output could be Main thread: Main thread: Main thread: Main thread: Main thread: Main thread: Other thread: Other thread: 0 1 2 3 4 5 0 1 At another run the output could be Other thread: Other thread: Main thread: Main thread: Main thread: Main thread: Main thread: Main thread: 0 1 0 1 2 3 4 5 9.i).2.i).2 Background Thread In the program threadtest2. CHAPTER 9. } // end while } // end Main static void ThreadJob() { int i = 0. while(i < 6) { Console.cs the Thread t is set to the background thread . i++. while(i < 2) { Console.WriteLine("Main thread: {0}".Start().

IsBackground = true. A thread can also be paused by calling Thread. } } } 107 9.Threading.Interrupt. The Sleep method takes as a parameter a timeout. Calling Thread.i).Sleep(Timeout. which is the number of milliseconds that the thread should remain blocked.i).WriteLine("Hello {0}".i++) { Console. the call is a non-blocking call that causes the .Infinite) causes a thread to sleep until it is interrupted by another thread that calls Thread.i<1001.2. // threadtest2. THREADS t. t. The Sleep method is called when a thread wants to put itself to sleep.3 Sleep Method Once a thread has been started it is often useful for that thread to pause for a fixed period of time. the call blocks until the thread is resumed by another thread.Suspend on another thread. for(int i=1. The thread will terminate when the application terminates. When a thread calls Thread.Suspend on itself. using System. Calling Thread.2. t.. } } public static void Main() { Thread t = new Thread(new ThreadStart(SayHello)).Sleep(0) causes a thread to yield the remainder of its timeslice to another thread.WriteLine("Bye {0}". One thread cannot call Sleep on another thread.Start(). // for Thread class class ThreadTest2 { public static void SayHello() { for(int i=1. Calling Thread.IsBackgound = true.Sleep causes the thread to immediately block for a fixed number of milliseconds. When one thread calls Thread.Suspend.cs using System.i++) { Console.9.

Start(). Thread thread = new Thread(job). PROCESSES AND THREADS The following program Threads0. i++. while(i < 5) { Console.Sleep(). Between each count in the main thread we sleep for 1000ms. CHAPTER 9.i). That thread counts from 0 to 9 fairly fast (about twice a second) while the main thread counts from 0 to 4 fairly slowly (about once a second). while(i < 10) { Console. which just makes the current thread sleep (do nothing) for the specified period of time (milliseconds). Thread.Sleep(500). The way they count at different speeds is by each of them including a call to Thread. } // end while } // end Main static void ThreadJob() { int i = 0. public class ThreadsSleep { static void Main() { ThreadStart job = new ThreadStart(ThreadJob). i++.cs using System.Threading. using System. Thus the code creates a new thread which runs the ThreadJob method. thread. and between each count in the other thread we sleep for 500ms. and starts it. We create a Thread instance by passing it an object of ThreadStart delegate which contains a reference to our ThreadJob method. Thread.cs is the simple example. // ThreadsSleep. int i = 0.Sleep(1000).108 other thread to pause.i).WriteLine("Main thread: {0}". } // end while } // end ThreadJob } .WriteLine("Other thread: {0}".

WriteLine("Goodbye").i).cs using System. // joiningthread. t. using System. THREADS A typical output could be Main thread: Other thread: Other thread: Main thread: Other thread: Other thread: Other thread: Main thread: Other thread: Main thread: Other thread: Other thread: Main thread: Other thread: Other thread: 0 0 1 1 2 3 4 2 5 3 6 7 4 8 9 109 At another run this could change.4 Join Methods The method Join() blocks the calling thread until a thread terminates. 9. } public static void Main() { Thread t = new Thread(new ThreadStart(Run)).Start().i++) Console.i++) Console.WriteLine("Welcome {0}".i<3.i<6. } .i). t.WriteLine("Hello {0}".Join().2. for(int i=1.9. class JoiningThread { public static void Run() { for(int i=1.2.Threading. Console.

the other one will have to wait for the new owner to release it too. A thread can enter (or acquire) a monitor only if no other thread has currently “got” it. PROCESSES AND THREADS 9. it will block until it is able to acquire it.Threading.i++) Console.Enter(obj). Monitor.i). Monitor. The Pulse(object) method notifies a thread in the waiting queue of a change in the locked object’s state. Monitor. class WaitingThread { static object obj = new object(). or exit (or release) it.3 Monitor While one thread is in a read/increment/write operation. This is where monitors come in. Every object in .Pulse(obj).i<6. public static void thread1() { for(int i=1. in which case when the current owner thread releases it for the last time. no other threads can try to do the same thing. } . If a thread tries to acquire a monitor which is owened by another thread.Exit(obj).cs using System. only one of the threads will acquire it . The monitor is only available to other threads again once it has exited as many times as it was entered. There may be more than one thread trying to acquire the monitor. Once a thread has acquired a monitor.NET has a monitor associated with it. using System.WriteLine("Welcome: {0}". it can acquire it more times.110 } The output is Welcome Welcome Welcome Welcome Welcome Hello 1 Hello 2 1 2 3 4 5 CHAPTER 9. // waitingthread. The method Wait(object) waits for the Monitor Pulse.

. The first program is without the lock operation.Pulse(obj). } public static void thread3() { for(int i=1.Exit(obj).Start(). t1. Monitor. Monitor.Start(). ThreadStart job2 = new ThreadStart(thread2).Start().i).i++) Console. Thread t1 = new Thread(job1).Wait(obj).Pulse(obj). Synchronization is done with the lock() operation.Enter(obj). t2. Thread t3 = new Thread(job3).i<15.i).Enter(obj). Monitor. Monitor.Exit(obj). Monitor. t3.i<8. } } If thread3 runs last after thread1 and thread2 have completed it freeze at Good Night: 7 9. In the second program the lock operation is introduced.9.i++) Console.4. ThreadStart job3 = new ThreadStart(thread3).4 Synchronization When two or more threads share a common resource access needs to be serialized in a process called synchronization.WriteLine("Good Night: {0}". Monitor. Thread t2 = new Thread(job2). } public static void Main() { ThreadStart job1 = new ThreadStart(thread1).WriteLine("Hello: {0}". Monitor. SYNCHRONIZATION 111 public static void thread2() { for(int i=1.

Start(). public void Withdraw(double amount) { Console.WriteLine("BALANCE {0}".cs using System. using System. Console. acc. } } Now we introduce the lock.Withdraw(3000). } } class SymnThread { static Account acc = new Account(). .Withdraw(3000). public static void Run() { acc.Threading. class Account { private double balance = 5000. if(amount > balance) throw new Exception("INSUFFICIENT FUNDS").Sleep(10).Threading.112 // syncthreads1. // syncthreads2.balance). // do other stuff balance -= amount. } public static void Main() { new Thread(new ThreadStart(Run)).amount). Thread. PROCESSES AND THREADS class Account { private double balance = 5000.cs using System. using System. CHAPTER 9.WriteLine("WITHDRAWING {0}".

this is when two threads each holds a monitor that the other one wants.Withdraw(3000).WriteLine("WITHDRAWING {0}".balance). An example is given below.WriteLine("BALANCE {0}". Thread. } public static void Main() { new Thread(new ThreadStart(Run)). waiting for the monitor that it’s waiting for to be released . } } class SymnThread { static Account acc = new Account(). // do other stuff balance -= amount. and the application hangs (or at least those threads involved in the deadlock hang). public static void Run() { acc. lock(this) { if(amount > balance) throw new Exception("INSUFFICIENT FUNDS").9. // Deadlock.5.Sleep(10). Simply put. acc. Each blocks. } } 9.Threading.cs using System. using System. DEADLOCK 113 public void Withdraw(double amount) { Console. public class Deadlock { . } Console.Start().and so the monitors are never released.5 Deadlock The second major problem of multi-threading is that of deadlocks.Withdraw(3000).amount).

Start().WriteLine("\t\t\t\tLocked firstLock"). Console.Sleep(500).WriteLine("\t\t\t\tLocking secondLock"). } // end method ThreadJob public static void Main() { new Thread(new ThreadStart(ThreadJob)).WriteLine("Released secondLock"). static readonly object secondLock = new object(). } Console. } Console.WriteLine("Released firstLock"). PROCESSES AND THREADS static readonly object firstLock = new object(). // wait until we are fairly sure the other thread // has grabbed firstlock Thread. lock(secondLock) { Console.114 CHAPTER 9. // Wait until we are fairly sure the first thread // has grabbed secondlock Thread.WriteLine("Locked secondLock"). } Console.Sleep(1000).WriteLine("\t\t\t\tLocked secondLock"). lock(firstLock) { Console.WriteLine("\t\t\t\tLocking firstLock").WriteLine("\t\t\t\tReleased firstLock"). } Console.WriteLine("Locked firstLock"). lock(secondLock) { Console. } // end Main } // end class . static void ThreadJob() { Console.WriteLine("\t\t\t\tReleased secondLock"). lock(firstLock) { Console.WriteLine("Locking firstLock"). Console. Console.WriteLine("Locking secondLock").

for(long i=0. Console. For example. we cannot have another thread changing the value half way through the read. Thus with an atomic write. object. if one thread is changing the value from 0 to 0x0123456789ABCDEF.9. Console. the Increment and Decrement methods act on variables of type int and long. for a long (64 bits) on a 32 bit machine.Increment(ref count). increments and decrements.WriteLine("final count: {0}".i<5. The Interlocked class provides a set of methods for performing atomic changes: exchanges (optionally performing a comparison first). .in other words.6 Interlocked Class An operation is atomic if it is indivisible .cs using System. // interlocked.Threading. with an atomic read. nothing else can happen in the middle. ending up with a value which is neither the old nor the new value. or float. Sinilarly. } thread.Join(). and ending up “seeing” half of the old value and half of the new value. public static void Main() { ThreadStart job = new ThreadStart(ThreadJob). thread. public class MyInterlocked { static long count = 0.WriteLine("I am in for loop in main"). Thread thread = new Thread(job).count).6.i++) { Interlocked. we cannot have another thread reading the value half way through the write. using System. INTERLOCKED CLASS 115 9. there is no guarantee that another thread will not see the value as 0x0123456700000000 or 0x0000000089ABCDEF. } // end Main static void ThreadJob() { long i = 0.Start(). The Exchange and CompareExchange methods act on a variables of type int.

An example is given below. Console.WriteLine("I am in ThreadJob").Length.Increment(ref count).Threading. depending on our application. 9. } } // end ThreadJob } First the for loop in Main will run to the end and then the while loop will be done.116 CHAPTER 9.i<a2. Using thread pooling provides our application with a pool of worker threads that are managed by the system. for(int i=0.7 Thread Pooling We can use thread pooling to make much more efficient use of multiple threads. Other threads might enter a sleeping state and be awakend only periodically to poll for a change or update status information before going to sleep again. i++.WriteLine("sum1 = " + sum1). } Console.cs using System. using System.i++) . // ThreadsSum2.i++) { sum1 += a1[i]. for(int i=0. but often those threads spend a great deal of time in the sleeping state waiting for an event to occur.i<a1. PROCESSES AND THREADS while(i < 5) { Interlocked. Many applications use multiple threads. int[] a1 = (int[]) o. int[] a2 = (int[]) o. class ThreadsSum { public static void Sum1(Object o) { int sum1 = 0.Length. allowing us to concentrate on application tasks rather than thread management. } public static void Sum2(Object o) { int sum2 = 0.

EndInvoke or CreateGraphics. 7 }.WriteLine("Sum1 queued"). we run a risk of our program hanging or misbehaving in other ways. 5. etc. we need to create a new thread (or use a thread pool thread if we prefer) to execute it on. That means we won’t receive events.8. // Give other threads a turn } } 117 9. our controls won’t be repainted. and InvokeRequired. If our code is running in the UI thread.Sleep(10). 3.9.a2)) Console. It means we have to consider re-entrancy issues etc. and we can’t use anything which might block (network access. There are message pumping issues in terms of COM objects as well. } public static void Main() { int[] a1 = { 2. Each control is effectively bound to a thread which runs its message pump. If we have a piece of long-running code which we need to execute. for instance) without risking an unresponsive UI.8 Threading in Windows Forms How to handle threading in a UI? There are two rules for Windows Forms: 1) Never invoke any method or property on a control created on another thread other than Invoke. } Console. We have to judge when to call DoEvents. BeginInvoke. 4 }. If we try to access or change anything in the UI (for example changing the Text property) from a different thread. We can execute longrunning code and periodically call Application. We may get away with it in some cases. and make . which are harder to diagnose and fix than ”normal” threading problems.WriteLine("Sum2 queued"). if(ThreadPool. that means no other code is running in that thread. BeginInvoke and EndInvoke methods have been provided so that we can ask the UI thread to call a method in a safe manner.WriteLine("sum2 = " + sum2).a1)) Console. THREADING IN WINDOWS FORMS { sum2 += a2[i]. int[] a2 = { 4. Thread.QueueUserWorkItem(new WaitCallback(Sum2). Fortunately.QueueUserWorkItem(new WaitCallback(Sum1).DoEvents(). the Invoke. if(ThreadPool. 2) Never execute a long-running piece of code in the UI thread.

There are two options when working out how to get information between the various threads involved. There are two different ways of invoking a method on the UI thread. we can use EndInvoke with the IAsyncResult returned by BeginInvoke to wait until the delegate has completed and fetch the return value. creating a delegate with lots of parameters feels clumsy. Here is an example which shows several of the above concepts. for example). and the EventArgs will be EventArgs. The thread creation part is the same as any other threading problem.Windows. // ThreadingForms. System. MethodInvoker is just a delegate which takes no parameters and returns no value (like ThreadStart). Label counter. and a message goes on the queue for the UI thread to process. public class Test : Form { delegate void StringParameterDelegate(string value). the current thread will block until the delegate has been executed. readonly object stateLock = new object().when the method is invoked. They work in much the same way . However if we pass an EventHandler delegate to Invoke or BeginInvoke then even if we specify parameters ourself. the call will return immediately.Threading. and EventHandler takes two parameters (a sender and an EventArgs parameter and returns no value. These two delegates are treated in a special (fast) manner by Invoke and BeginInvoke.cs using using using using System.118 CHAPTER 9. Using state somewhere is necessary if we are creating a new thread rather than using the thread pool .invoking a method on the UI thread in order to update the UI. the sender will be the control we have invoked it with. setting it in one thread. retrieving and processing it in the other (updating the display in the UI thread.Forms. The second option is to pass the information as parameters in the delegate. Button button. It is interesting going the other way . . and is in some ways less efficient than using a simple MethodInvoker or EventHandler delegate.Empty.Drawing. System. If we need to get the return value of a delegate invoked asynchronously. System. one synchronous (Invoke) and one asynchronous (BeginInvoke). they are ignored . Label statusIndicator.but that doesn’t mean we have to use state to return information to the UI. If we use BeginInvoke. PROCESSES AND THREADS sure it doesn’t directly try to update the UI with its results. However. The first option is to have state in the class itself. If we use Invoke.we specify a delegate and (optionally) some arguments.

Click += new EventHandler(StartThread). statusIndicator = new Label().Text = "Run". lbl = new Label(). counter = new Label(). lbl. Text = "Test". lbl. Controls.Add(statusIndicator). Test() { Size = new Size(180. Controls.Add(lbl).Size = new Size(100. int currentCount.Add(counter).58). counter. statusIndicator. button.120). statusIndicator.Location = new Point(70.Location = new Point(10. lock(stateLock) { 119 .20).Text = "Count:".Size = new Size(50.Size = new Size(100.8. Label lbl = new Label(). Controls. Controls. lbl.Add(lbl). THREADING IN WINDOWS FORMS int target.34). lbl. button.20).Size = new Size(50. Random rng = new Random().20).Location = new Point(70. lbl.10). counter.EventArgs e) { button. } void StartThread(object sender. button = new Button(). Controls.34). lbl.10).Add(button).20).Enabled = false.Size = new Size(50.Location = new Point(10.9. button. button.20).Location = new Point(10.Text = "Status:".

t. t.Start(). } UpdateStatus("Starting").Next(100). . } Invoke(updateCounterDelegate). Thread.i++) { lock(stateLock) { currentCount = i. } void ThreadJob() { MethodInvoker updateCounterDelegate = new MethodInvoker(UpdateCount). int localTarget.IsBackground = true.120 CHAPTER 9. Invoke(new MethodInvoker(EnableButton)).Sleep(100). PROCESSES AND THREADS target = rng. } UpdateStatus("Finished"). } Thread t = new Thread(new ThreadStart(ThreadJob)). } // Synchronously show the counter Invoke(updateCounterDelegate).new object[]{value}). for(int i=0. so we need to call BeginInvoke BeginInvoke(new StringParameterDelegate(UpdateStatus). lock(stateLock) { currentCount = 0.i<localTarget.Sleep(500). // Pause before starting Thread. UpdateStatus("Counting"). lock(stateLock) { localTarget = target. } void UpdateStatus(string value) { if(InvokeRequired) { // We’re not in the UI thread.

} // Must be on the UI thread if we’ve got this far statusIndicator. If it does. so we should use BeginInvoke instead of Invoke. } static void Main() { Application. } counter. BeginInvoke .Enabled = true.9. A delegate taking a parameter is used to ask the UI to update the status label. but slightly harder work in that we would either have to have another method anyway. which uses InvokeRequired to detect whether or not it needs to ”change thread”. we would decide based on whether we needed to block to wait for the access to the UI to complete before continuing or not. THREADING IN WINDOWS FORMS return. In real code. In this case we actually know that BeginInvoke is required because we are running in the worker thread anyway. It is quite rare to actually require UI access to complete first. Another approach might be to have a property which did the appropriate invoking when necessary. We do not call EndInvoke after the BeginInvoke. } void EnableButton() { button.Run(new Test()). lock(stateLock) { tmpCount = currentCount.8. It is easier to use from the client code. The choice of BeginInvoke rather than Invoke here was just to demonstrate how to invoke a method asynchronously.Text = tmpCount. Unlike all other asynchronous methods we do not need to call EndInvoke unless we need the return value of the delegate’s method. } void UpdateCount() { int tmpCount. or get the MethodInfo for the property setter in order to construct the delegate to invoke. This is quite a common way of making a method which interacts with the UI thread-safe.Text = value. } } 121 State is used to tell the worker thread what number to count up to.ToString(). it then calls BeginInvoke to execute the same method again from the UI thread. The worker thread’s principal method actually just calls UpdateStatus.

122 CHAPTER 9.int m). For every delegate declared in an assembly the compiler emits a class (subclass of System. public int EndInvoke(System. we actually know that we need to call Invoke here anyway. Again. the whole application finishes.we will either block permanently (waiting for the message to be taken off the queue. For example. } . This time there’s no attempt to detect whether or not an Invoke is required. We call this using Invoke to make sure that it executes on the UI thread. PROCESSES AND THREADS is also different to all of the other asynchronous methods as it doesn’t cause the delegate to be run on a thread pool thread. If we call BeginInvoke it will have a different effect than calling the method directly as it will occur later.int m).NET has an inbuilt support for asynchronous method invocation.AsyncCallback cb.int m.IAsyncResult result). The worker thread is set to be a background thread (IsBackground=true. BeginInvoke and EndInvoke methods. . and another MethodInvoker delegate is used to enable the button again afterwards. rather than in the current execution flow. It is disabled while the thread is running.IAsyncResult BeginInvoke(char c.MulticastDelegate) with Invoke.System. with nothing actually looking at messages) or receive an exception.9 Asynchronous Programming Model When a caller invokes a method.MulticastDelegate { public int Invoke(char c. Here the caller can issue a request for invocation of a method and concurreently execute the remaining code. of course. not updating the UI or anything else while holding the lock. In other cases where we have a thread which should keep running even after the UI thread has quit. We use a MethodInvoker delegate to execute UpdateCount. State is used again to tell the UI thread how far we have counted so far. The compiler will emit the MyWorker class class MyWorker : System. public System. 9. This probably doesn’t make too much difference here. A button is provided to let the user start the thread. object asyncState). and we end up with deadlock. We spend as little time as possible in the lock. the call is synchronous that is the caller has to wait for the method to return before the remaining code can be executed. consider a delegate declared as delegate int MyWorker(char c. we need to be careful not to call Invoke or BeginInvoke when the UI thread is no longer running . It would be disastrous to still have the lock in the worker thread when synchronously invoking UpdateCount .) so that when the UI thread exits.the UI thread would then try to acquire the lock as well. All state which is shared between threads (the current count and the target) is accessed in locks in the way described earlier.

TickCount. // returns number of milliseconds // elapsed since the system started for(int i=1. we have used Console.NET.i<=m. // asynchronous call DoWork(’*’.10 Timers There are various different timers available in . return (Environment. TIMERS 123 The BeginInvoke and EndInvoke methods can be used for asynchronous invocation of a method pointed by MyWorker delegate. As an asynchronous call executes within its own background thread.9.WriteLine("Start").i++) Console. // Timers.BeginInvoke(’+’. delegate int MyWorker(char c. // synchronous call Console.cs using System. // Asynchronous.t). in the next statement this method is directly invoked with character ’*’. worker = new MyWorker(DoWork).cs .int m) { int t = Environment. so we have to make sure to dispose when we are not using them anymore. each of which basically calls a delegate after a certain amount of time has passed. static int DoWork(char c.Read() to pause the main thread. All the timers implement IDispossible.Read().TickCount .null. In the program below the method DoWork (it displays character c m number of times) is invoked asynchronously with character ’+’.1000). worker.int m).null). } public static void Main() { Console.1000. Both ’+’ and ’*’ are displayed (1000 times each) on the Console simultaneously.Write(c). // pause until user presses a key } } 9.10. class AsncTest { static MyWorker worker.

Sleep(10000).Interrupt is similar.Now).cs using System.DateTime. Calling Thread.3000. class SleepingThread { public static void Run() . } } 9.Threading. Calling Thread. } // the timerm will now have been disposed automatically due // to the using statement so there won’t be any other threads running } // end Main() static void Tick(object state) { Console. // Interruptthread. using System. // then go slow for another 10 seconds timer.Change(0.Abort aborts that thread as soon as possible.WriteLine("Ticked at {0:HH:mm:ss.fff}". but less drastic. PROCESSES AND THREADS public class Timers { public static void Main() { Console. Aborting a thread which is executing unmanaged code has no effect until the CLR gets control again. CHAPTER 9.WriteLine("Started at {0:HH:mm:ss.124 using System. then fire every second using(Timer timer = new Timer(new TimerCallback(Tick). using System. Thread.Sleep(10000).2000).DateTime.Threading.fff}".1000)) { // wait for 10 seconds Thread. // Start in three seconds. or immediately if the thread is already in that state. This causes a ThreadInterruptedException exception to be thrown the next time the thread enters the WaitSleepJoin state.11 Interrupt and Abort There are two methods in the Thread class which are used for stopping threads Abort and Interrupt.null.Now).

i<6.WriteLine("Sleep Interrupted"). } public static void Main() { Thread t = new Thread(new ThreadStart(Run)).i++) Console.i<16.WriteLine("Welcome {0}".i). using System.WriteLine("Goodbye"). } } public static void Main() { Thread t = new Thread(new ThreadStart(SayHello)).i++) Console.i).cs using System.WriteLine("Hello {0}". // threadtest1. // for Thread class class ThreadTest1 { public static void SayHello() { for(int i=1. t.Interrupt().i). 125 .9.11.WriteLine("Hello {0}". t.cs uses the Abort method. } Console..Sleep(5000). INTERRUPT AND ABORT { for(int i=1.Threading. } } The program threadtest1. } catch(ThreadInterruptedException e) { Console.Start().i++) { Console. for(int i=1. try { Thread.

Start(). } t.126 CHAPTER 9. PROCESSES AND THREADS t.WriteLine("Bye {0}". for(int i=1.i).Abort().i<1001. } } .i++) { Console.

4.Chapter 10 Sockets Programming 10. The client needs to know of the existence of and the address of the server. an address consists of a port number on the host machine. These terms refer to the two processes which will communicating with each other. The two processes each establish their own socket. The steps for establishing a socket on the client side are: 1. This call typically blocks until a client connects with the server. Accept a connection. 127 . Once a connection is established. but both involve the basic construct of a socket.1 Introduction Most interprocess communication uses the client server model. typically to make a request for information. Connect the socket to the address of the server 3. connects to the other process. A socket is one end of an interprocess communication channel. Create a socket 2. Listen for connections. but the server does not need to know the address of (or even the existence of) the client prior to the connection being established. both sides can send and receive information. 3. One of the processes. A good analogy is a person who makes a phone call to another person. the server. Bind the socket to an address. the client. The system calls for establishing a connection are different for the client and the server. For the server socket on the Internet. Create a socket 2. Send and receive data The steps for establishing a socket on the server side are: 1.

SOCKETS PROGRAMMING Thus a socket is a communication mechanism. The server on reciept of the string will display it.1 BSD Unix system in late 1981. . Formally a socket is defined by a group of four numbers. Example 1. send an acknowledgement which will be received by the client. Send and receive data. When the server program is run it will indicate at which IPAddress it is running and the port it is listening to. A socket is normally identified by an integer which may be called the socket descriptor.2 Transmission Control Protocol TCP is reliable connection oriented protocol. The client will ask for the string which is to be transmitted to the server. Thus besides the IPAddress we also need a port number (2 bytes) which is arbitrary except for the well know port numbers associated with popular applications.2 BSD Unix system in 1983 in conjunction with the TCP/IP protocols that first appeared in the 4.128 5. CHAPTER 10. The socket mechanism was first introduced in the 4. Now run the client program so that we establish a connection with the server. There are 1) 2) 3) 4) The The The The remote host identification number or address (IPAddress) remote host port number local host identification number or address (IPAddress) local host port number 10. When the connection is established the server will display the IPAddress and port from where it has accepted the connection.

.WriteLine("Error. System. } // end try catch(Exception e) { Console.10. Console.StackTrace).WriteLine("The local End point is: " + listener. // clean up s.Send(asen.WriteLine("Connection accepted from " + s..AcceptSocket(). Socket s = listener.2055).WriteLine("Waiting for a connection.Text. // start listening at the specified port 2055 listener.GetBytes("The string was received by the server.Net.Net. " + e."). listener. s.").106.Close().i<k.").2..Stop().. Console. byte[] b = new byte[100].i++) Console..Write(Convert. TcpListener listener = new TcpListener(ipAd.Sockets. Console. } // end catch } // end Main } // end class Server1 . TRANSMISSION CONTROL PROTOCOL // Server1. ASCIIEncoding asen = new ASCIIEncoding().RemoteEndPoint). System.. Console.cs using using using using System.WriteLine("\nSent Acknowledgement"). System.Start(). Console.84")..Parse("152.")). int k = s.ToChar(b[i])). for(int i=0.Receive(b).WriteLine("Server is running at port 2055. 129 class Server1 { public static void Main() { try { // use local IP address and use the same in the client IPAddress ipAd = IPAddress.. Console.LocalEndpoint).WriteLine("Received.40.

SOCKETS PROGRAMMING class Client1 { public static void Main() { try { TcpClient tcpclnt = new TcpClient().i<k.ba..GetStream().. byte[] bb = new byte[100]. for(int i=0.WriteLine("Connecting..Net.2055).40. } // end catch } // end Main } // end class Client1 .Sockets. stm.. Console. int k = stm.Connect("152. } // end try catch(Exception e) { Console.StackTrace). Console. " + e.Write(ba. CHAPTER 10. String str = Console.ReadLine().GetBytes(str).WriteLine("Error. System.84". // clean up tcpclnt.Write("Enter the string to be transmitted: ").WriteLine("Transmitting.ToChar(bb[i]))..Read(bb.. Console.Length).100). Console. System. Stream stm = tcpclnt.").130 // Client1. byte[] ba = asen.Close().Net. ASCIIEncoding asen = new ASCIIEncoding().IO. System.Write(Convert. System.cs using using using using using System.0.WriteLine("Connected").Text.i++) Console.0."). tcpclnt.106.

class EmployeeTCPServer { static TcpListener listener. System. Next we compile the Client side csc Client2. } // end for loop } // end Main public static void Service() { while(true) . // Server2.Parse("152. System.listening to port 2055").10.cs The code between #if LOG and endif will be added by the compiler only if the symbol LOG is defined during compilation (conditional compilation).i<LIMIT.Start(). In our second example we include an xml-file (Server2.WriteLine("Server mounted. System. TRANSMISSION CONTROL PROTOCOL 131 Example 2.Net. const int LIMIT = 5. On the Server side we first compile csc /D:LOG Server2. // 5 concurrent clients public static void Main() { IPAddress ipAd = IPAddress. #endif for(int i=0. System.Configuration.exe.Net.cs using using using using using using System. #if LOG Console.2055).Sockets.2.84"). t.106.IO.40. listener.Threading. listener = new TcpListener(ipAd.cs Then on the Server side we start running the exe-file Server2 and finally we start the exe-file Client2 on the Client side. System.config) on the Server side we can query from the Client.i++) { Thread t = new Thread(new ThreadStart(Service)).Start().

#endif soc. SOCKETS PROGRAMMING { Socket soc = listener.RemoteEndPoint). #endif } // end catch #if LOG Console. if(name == "" || name == null) break.soc.AppSettings. } // end while s. // enable automatic flushing sw. #endif try { Stream s = new NetworkStream(soc).RemoteEndPoint). if(job == null) job = "No such employee".ConfigurationManager. #if LOG Console. sw.WriteLine(e. } } } // end class Server2 .AppSettings[name]. StreamWriter sw = new StreamWriter(s).WriteLine("{0} Employees available".AcceptSocket().ReadLine(). sw. string job = ConfigurationManager. while(true) { string name = sr.Message).Count). } // end try catch(Exception e) { #if LOG Console.soc. StreamReader sr = new StreamReader(s).AutoFlush = true.132 CHAPTER 10.WriteLine("Connected: {0}".Close().WriteLine("Disconnected: {0}".WriteLine(job).Close().

TRANSMISSION CONTROL PROTOCOL The file (xml-file) Server2.2.exe.config is given by <configuration> <appSettings> <add key="john" value="manager"/> <add key="jane" value="steno"/> <add key="jim" value="clerk"/> <add key="jack" value="salesman"/> </appSettings> </configuration> 133 .10.

40.ReadLine()). if(name == "") break. } // end while s. StreamWriter sw = new StreamWriter(s). Console. while(true) { Console. sw.106.84".ReadLine()). string name = Console. CHAPTER 10.Write("Name: "). sw.Close(). using System. Console.GetStream(). SOCKETS PROGRAMMING class Client2 { public static void Main() { TcpClient client = new TcpClient("152.WriteLine(name).cs using System.IO.WriteLine(sr. StreamReader sr = new StreamReader(s).WriteLine(sr. } // end finally } // end Main } // end class Client2 . try { Stream s = client.2055).134 The Client2. } finally { // code in finally block is guranteed to execute irrespective // whether any exception occurs or does not occur in the try block client.Sockets.AutoFlush = true.cs is given by // Client2.ReadLine(). using System.Close().Net.

3.Send(sdata. udpc.3 User Datagram Protocol UDP is not very reliable (but fast) connectionless protocol. System. System.10.Sockets.Net. while(true) { byte[] rdata = udpc. Console. string name = Encoding.exe.Net.Configuration.Length.ep). The UDPServer1.sdata.Receive(ref ep).cs using using using using using System. USER DATAGRAM PROTOCOL 135 10.Text.cs file is given by // UDPServer1.ASCII. System. Example. } // end while } // end Main } The xml-file UDPServer1. class ServerUDP { public static void Main() { UdpClient udpc = new UdpClient(2055).GetString(rdata). IPEndPoint ep = null. string job = ConfigurationManager.AppSettings[name].GetBytes(job).ASCII. if(job==null) job = "No such employee". byte[] sdata = Encoding.WriteLine("Server started servicing on port 2055"). System.config is given by <configuration> <appSettings> <add key="john" value="manager"/> <add key="jane" value="steno"/> <add key="jim" value="clerk"/> <add key="jack" value="salesman"/> </appSettings> </configuration> .

106. .cs using using using using System.sdata. On the Server side we first compile csc UDPServer1. while(true) { Console.136 The UDPClient1. byte[] rdata = udpc. SOCKETS PROGRAMMING class ClientUDP { public static void Main() { UdpClient udpc = new UdpClient("152.config) on the Server side we can query from the Client. udpc.Text.Send(sdata. System. IPEndPoint ep = null.Write("Name: "). string job = Encoding.Net. Console.Net.2055).84". if(name == "") break. System. System.WriteLine("job = " + job).40. byte[] sdata = Encoding.exe. } // end while } // end Main } We include an xml-file (UDPServer1.Receive(ref ep). CHAPTER 10.cs Then on the Server side we start running the exe-file UDPServer1 and finally we start the exe-file UDPClient1 on the Client side.cs Next we compile the Client side csc UDPClient1.GetString(rdata).cs file is given by // UDPClient1.Sockets.ASCII.GetBytes(name).ASCII. string name = Console.ReadLine().Length).

WriteLine("Server ready. IChannel c = new HttpChannel(8080). Usually this means the two processes are running on two different computers.1 Introduction Object running in one Virtual Machine (VM) should be able to access (call functions on) objects that are in a different Virtual Machine. ").ReadLine(). RemotingServices.Marshal(t. Console."me"). } } 137 . To set up remoting we proceed as follows: Instantiate target object (on server) Setup our channels Register our object (on server) Get a reference to object (on client) Call method on server from the client For example on the Server side: public class Server { public static void Main() { Target t = new Target().Chapter 11 Remoting 11.RegisterChannel(c). ChannelServices. Console.

138 On the Client side we have public class Client { public static void Main() {

CHAPTER 11. REMOTING

string url = "http://localhost:8080/me"; Type to = typeof(Target); Target t = (Target) RemotingServices.Connect(to,url); Console.WriteLine("Connected to server."); try { string msg = Console.ReadLine(); t.sendMessage(msg); } catch(Exception e) { Console.WriteLine("Error " + e.Message); } } } A shared class (i.e. it is on the Client and Server side) is public class Target : System.MarshalByRefObject { public void sendMessage(string msg) { System.Console.WriteLine(msg); } } Reference types passed via remoting must be serializable or marshal-by-reference. Serializable == pass-by-value Copy of object is made. MarshalByRefObject == pass-by-reference proxy object is passed. An example for the second case is: public class Counter : MarshalByRefObject { int count = 0; public void incCount() { count++; } public int getCount() { return count; } } An example for the first case is:

11.1. INTRODUCTION [Serializable] public class Counter { int count = 0; public void incCount() { count++; } public int getCount() { return count; } } We have to import: using using using using using System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Http; // for Http System.Runtime.Remoting.Channels.Tcp; // for Tcp

139

Shared objects must be available to both the client and the server. Make a separate assembly for it csc /t:library Shared.cs csc /r:Shared.dll Server.cs csc /r:Shared.dll Client.cs There are three main items in the process of remoting. The Interface, the Client and the Server. The Interface is a .dll file (generated from a .cs file) which is on the Client and Server side. The Server provides an implementation of the Interface and makes it available to call. The Client calls the Server using the Interface.

140

CHAPTER 11. REMOTING

Example. The client provides a string to the server and the server returns the length of the string. We first create an interface with the file MyInterface.cs. // MyInterface.cs public interface MyInterface { int FunctionOne(string str); } MyInterface.cs is on the Server and Client side. We compile to MyInterface.dll on the Client and Server side with csc /t:library MyInterface.cs On the Server side we now create our class which we invoke from a remote machine (client). RemoteObject.cs is on the Server side and is the implementation of MyInterface.cs. // RemoteObject.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; public class MyRemoteClass : MarshalByRefObject, MyInterface { public int FunctionOne(string str) { return str.Length; // length of string } } Any class derived from MarshalByRefObject allows remote clients to invoke its methods. Now on the Server side we compile csc /t:library /r:MyInterface.dll RemoteObject.cs This creates the file RemoteObject.dll on the Server side.

Runtime.false).Channels. Remark.Console.ReadLine(). 141 public class MyServer { public static void Main() { TcpChannel m_TcpChan = new TcpChannel(9999). Next we generate the exe file for ServerTcp via csc /r:RemoteObject. System.RemoteObject"). Now this object can be remoted. Then we use RemoteConfiguration. System.Channels.11.WriteLine("Press ENTER to quit").cs .WellKnownObjectMode.GetType("MyRemoteClass. ChannelServices.dll ServerTcp. We select 9999 as the TCP port to listen on.Runtime. This could cause problems with firewalls. RemotingConfiguration. System.1. We are using the string FirstRemote here which will be used as part of the URL that the client uses to access the remote object. System.cs using using using using System. One could have also used Singleton in which case one object would have been instantiated and used by all connecting clients. We use SingleCall mode here which means a new instance is created for each remote call.RegisterWellKnownServiceType( Type.Remoting. // ServerTcp.Console.Remoting.RegisterChannel(m_TcpChan. System. "FirstRemote".Remoting.RegisterChannel to register our TcpChannel with the channel services. INTRODUCTION Next we provide our Server on the Server side.Runtime. We use ChannelServices.Tcp.RegisterWellKnownServiceType to register our RemoteClass object as a well-known type.SingleCall). } // end Main } // end class MyServer First we create a TcpChannel object which we use to transport messages across our remoting boundary.

Remoting. System.3:9999/FirstRemote"). // ClientTcp.Remoting. Console.0.142 CHAPTER 11.Runtime. To obtain the ClientTcp.RegisterWellKnownServiceType on the Server.GetObject(typeof(MyInterface).Tcp.Channels.0. ChannelServices.dll ClientTcp.RegisterChannel to register the channel. The string FirstRemote which forms part of the URL was that we passed to RemotingConfiguration.exe file we run csc /r:MyInterface. "tcp://192.WriteLine(m_RemoteObject.168.Remoting. though in this case we do not have to specify a port. We use Activator.GetObject to obtain an instance of the MyInterface object.Channels.3 with the port 9999.168. // for LocalHost // "tcp://LocalHost:9999/FirstRemote").FunctionOne("willi hans steeb")). } // end Main } // end class MyClient Just as in the Server we have a TcpChannel object.RegisterChannel(m_TcpChan. REMOTING Now we write our Client program ClientTcp. System.cs .Runtime.Runtime. System. We also use ChannelService. The IP address of the remote machine (Server) is 192.false).cs on the client side.cs using using using using System. public class MyClient { public static void Main() { TcpChannel m_TcpChan = new TcpChannel(). MyInterface m_RemoteObject = (MyInterface) Activator.

143 .11. INTRODUCTION To run everything on the Server side we enter the exe file at the command line ServerTcp Then on the Client side we enter the exe file at the command line ClientTcp Then we are provide with the length of the string.1. In the present case 16.

RegisterChannel(chan. System. System.Runtime.Console.144 CHAPTER 11. // ServerHttp.WriteLine("Press ENTER to quit").SingleCall).Remoting. Then the files ServerTcp.Remoting. System. System.RegisterWellKnownServiceType( Type. "FirstRemote". } // end Main } // end class MyServer .false).cs and ClientTcp.Console. System.cs and ClientHttp.cs // on Server side using using using using System. REMOTING Instead of using Tcp we can also use Http. RemotingConfiguration.GetType("MyRemoteClass.Http.Remoting.ReadLine().cs are replaced by ServerHttp.RemoteObject").Channels.Runtime.WellKnownObjectMode. ChannelServices.Channels. public class MyServer { public static void Main() { HttpChannel chan = new HttpChannel(8080).Runtime.cs shown below.

Runtime.Remoting.41.Remoting. ChannelServices. System.42:8080/FirstRemote").Channels.GetObject(typeof(MyInterface).Remoting.Channels. MyInterface m_RemoteObject = (MyInterface) Activator. INTRODUCTION // Client.cs // on client side using using using using System.WriteLine(m_RemoteObject. "http://152.Runtime.Runtime.Http. System. } // end Main } // end class MyClient . System.106. // for LocalHost // "tcp://LocalHost:9999/FirstRemote").false). Console.1.FunctionOne("willi hans")).RegisterChannel(chan.11. 145 public class MyClient { public static void Main() { HttpChannel chan = new HttpChannel().

Accessing a database requires that a . When an application requests data a new database connection is created and destroyed when the request is completed.NET Data Provider is set up.NET Framework.NET is that information is stored and transferred in XML.NET to access databases. ADO. In order to use SQL with SQL Server or SQL Server Express the following namespace must be specified.NET is a set of managed classes within the . A Data Provider consists of • Connection • Command • DataReader • DataAdapter 146 .Data. It operates on a disconnected data access model.1 Introduction The . ADO. SQLClient is used for Microsoft’s SQL Server and OLEDB is used for all other database formats.OleDb.NET allows access to many different databases.SqlClient. which is desirable. In order to use OLEDB the following namespace must be specified.Data. There are two basic types of connections.NET Framework uses ADO. using System.Chapter 12 Accessing Databases 12. using System. One important advantage of ADO. A disconnected data access model is frugal with resources.

It returns individual rows directly to the application.2 Examples The following program shows how to connect to a Microsoft SQL Server 2005 or Sql Express database and retrieve some basic information about the server. EXAMPLES 147 A Dataset can be understood as a virtual database table that resides in RAM.com. The Connection object contains all the information needed to open the connection. A DataSet can contain a set of tables with all the metadata necessary to represent the structure of the original database. A DataAdapter handles retrieving and updating data. In order to open and close a database connection the Connection methods Open and Close are used respectively. using using using using System. System. A Connection String is required to connect to a database. read-only database access. namespace csDB { class OpenSQLDB { public const string CON_STRING = "Data Source=mySqlDB. It is a middle-layer between the database (Data Provider) and the disconnected DataSet. A DataSet is not always required. It can be manipulated and updated independantly of the database. Care must be taken is creating an appropriate connection string (CON STRING in these examples).User ID=JoeUser. The Connection creates the actual connection to the database. . System. For example. A good site to start with is http://www. System. A DataReader is used for fast and efficient forward-reading.12.Data.Text. The data is not cached. It decouples the DataSet from the database and allows a single DataSet to represent more than one database.Initial Catalog=dbTest.2.Password=User1234". The easiest way to find the correct connection string for a DBMS is to search the Web. 12.SqlClient.connectionstrings. The Command executes an instruction against the database. for example the userid and password. this could be a SQL query or a stored procedure. Knowledge of SQL is required.Data.

NET solves this problem by using the web.WriteLine("Database: {0}".WriteLine("Data Source: {0}".WriteLine("Connecting to db\n"). cmDB.net. Console. ASP.config file. <configuration> <appSettings> <add key="DBConnect" value="server=mySqlDB. Console.pwd=User1234. connection. The basic method of retrieving data using a Data Reader is as follows. Console. <\configuration> The following line of code fetches the connection string from web.ExecuteReader(). . SqlCommand cmDB = new SqlCommand().Connection = connection .ServerVersion).CommandText = "SELECT * FROM tblCustomer". ACCESSING DATABASES static void Main(string[] args) { Console.DataSource).newdb. is not a good idea. cmDB. The following is an extract from a web. A standard SQL query is used and submitted to the database via a SqlCommand object.user id=JoeUser..config file.config.WriteLine("Server Version: {0}". SqlDataReader myReader = cmDB. a change in the database means the code will have to be modified and recompiled. SqlConnection connection = new SqlConnection(CON_STRING). Console. In addition.. } // end Main } // end class } // end namespace Embedding the user ID and password."/> <appSettings> .Open(). it is not secure. connection.Appsettings["DBConnect"]. string CON_STRING=ConfigurationSettings. connection.WriteLine("Stats Enabled: {0}".148 CHAPTER 12. connection.initial catalog=dbTest.StatisticsEnabled). connection. as in the above code. In the case of data retrieval the SELECT statement is used.Database).

ExecuteReader().ToString(). int id.Read()) { id = (int) rdr["fldCustomerID"].Text = id + " " + strName. . string strSQL = "SELECT * FROM tblCustomer WHERE" + " fldCustSurname = ’Hardy’ AND fldCustName = ’Frank’". SqlDataReader rdr = cmDB. // etc etc TextBox1.12. The assumption is that a TextBox called txtSearch is used to input the search parameters. strName = (string) rdr["fldCustName"].Integrated Security=True". strSurname. while (rdr. string strName. string strSearch = "SELECT * FROM tblCustomer where fldCustName LIKE ’" + TextBox1. A Trim() is used to remove whitespace. connection.CommandText = strSQL.Close(). // SQL uses a % for wildcard myReader = cmDB.Open(). // Access SQL EXPRESS db and retrieve data and put field // values into variables string CON_STRING = "Data Source=ejd\\sqlexpress.2.Connection = connection. The following code shows how to access particular fields using a Data Reader. myReader[1] then accesses the SECOND field. float fltCred. } myReader. the myReader[0] accesses the FIRST field of data // the selected record. cmDB.ToString() + " " + myReader[1].ExecuteReader(). SqlCommand cmDB = new SqlCommand(). SqlConnection connection = new SqlConnection(CON_STRING)." + "Initial Catalog=dbCustomer. // string strTmp = myReader[0]. fltBal. EXAMPLES 149 while(myReader. cmDB. A wildcard search can be achieved as follows.Text.Trim() + "%’".Read()) { // Do something with the data // In the following code.

Text. SqlConnection connection = new SqlConnection(CON_STRING). String MyString = @"INSERT INTO tblCustomer(fldCustName.Close(). fldCustSurname)" + "VALUES(’" + txtFirstName. connection.Text. ’" + txtSurname.Open().Open(). using a SQL UPDATE command.Close()." + "Initial Catalog=dbCustomer. using a SQL INSERT command. fldCustSurname)" + "VALUES(’Angus’. String MyString = "UPDATE tblCustomer SET fldCustCred = ’1000’ " + . ’MacBeth’)".150 } rdr. In the case of wanting to insert the values from two TextBoxes called txtFirstName and txtSurname. CHAPTER 12. String MyString = @"INSERT INTO tblCustomer(fldCustName. The following code shows how to edit a row in a database. connection.Trim() + "’)". SqlCommand MyCmd = new SqlCommand(MyString. string CON_STRING = @"Data Source=mname\sqlexpress. connection." + "Initial Catalog=dbCustomer" + ".Integrated Security=True". It is likely that the C# programmer will have a need to extract some data from a TextBox. either on a Windows or Web Form. SqlConnection connection = new SqlConnection(CON_STRING). and insert that value into a table.Close(). ACCESSING DATABASES The following code shows how to insert a row into a database. you would have the following statement in C#.Trim() + "’. String CON_STRING = @"Data Source=mname\sqlexpress. connection.ExecuteScalar().Integrated Security=True". connection). MyCmd.

12.Text = ex.Close().Message. MyCmd. try { connection.ExecuteScalar(). MyCmd. connection. } . } catch (Exception ex) { TextBox1. CATCH block for exception handling.ExecuteNonQuery().. SqlCommand MyCmd = new SqlCommand(MyString. EXAMPLES "WHERE fldCustName = ’Angus’". using a SQL DELETE command. This program uses a TRY. String MyString = @"DELETE FROM tblCustomer " + "WHERE fldCustName = ’Greg’". string CON_STRING = "Data Source=mname\\sqlexpress." + "Integrated Security=True". connection)." + "Initial Catalog=dbCustomer. } finally { connection. SqlCommand MyCmd = new SqlCommand(MyString.Open().Close(). SqlConnection connection = new SqlConnection(CON_STRING). 151 The following code shows how to delete data in a database.2. connection)..

cookies can be used.NET languages.aspx"). For the longer term storage of data. String strTmp = Request. This chapter outlines some additional code that is required when programming web applications. A Query String can be created using a HyperLink control. C# is perhaps the best language to write ASP. The code below shows how to save a variable using the Session object. 152 . The Query String can be retrieved by using the Request object.1 Introduction ASP. string strRetSess = Session["sessionTmp"].Chapter 13 ASP. string strTmp = "Some string".NavigateUrl = "default. The Session object can achieve this.NET applications. The following code retrieves the data from the Session object. Session["sessionTmp"] = strTmp. HyperLink1. Of all the available .NET Framework. Response. That leaves the problem of maintaining state between the Web Forms of a single application. 13.QueryString["name"].NET 13.ToString(). Below is some code for creating cookies.aspx?name=evan".2 State Management Web Forms can be thought of a seperate applications.Redirect("default2.NET is Microsoft’s Web technology built on the .

cookie.SelectedItem. //Set the cookies value (In this case from a DropDownList) cookie.Value. // Redirect to another Web Form Response.13.Cookies. . } A cookie can be deleted in the following manner.aspx").Write("Cookie not found. //Grab the cookie HttpCookie cookie = Request.Redirect("default2. PAGE LOAD //Create a new cookie.Cookies.Cookies[strCookieName].ToString().ToString().3.Value = DropDownList1.3 Page Load In the Page Load event.Expires = DateTime. <br><hr>"). 0. cookie. passing the name into the constructor HttpCookie cookie = new HttpCookie("Names"). TimeSpan tsMinute = new TimeSpan(0. we employ the following code to ensure that some code is only executed the first time a Web Form is loaded. } else { //Write the cookie value String strCookieValue = cookie.Add(cookie).Now. // Cookie name String strCookieName = "Names".Now. //Set the cookie to expire in 1 minute DateTime dtNow = DateTime.AddDays(-1). //Add the cookie Response. Response.Add(cookie). //Check to make sure the cookie exists if (null == cookie) { Response. 0). Data from a cookie is retrieved using the Request object.Expires = dtNow + tsMinute. 153 13. 1.

StateDropDownList.154 CHAPTER 13. ASP. } .Items.NET if(!IsPostBack) { // Code in this block will only execute once StateDropDownList.Add{"Northern Province"}.Add{"Gauteng"}.Items.

codeproject.Bibliography [1] http://www.com/csharp [2] C# Language Specification 155 .

3 Process. 67 Pointer. 150 Using.Index ADO. 45 156 Namespace. 11 UPDATE. 146 Arrays of Strings. 8 Delegate. 24 Client server model.NET. 26 Arrays. Contextual. 148 Atomic.NET. 26 Arrays. 153 Data Provider. 2 Inheritence. 152 Recursion. 62 INSERT. 45 SELECT. 69 DELETE. 27 Boxing. 151 Dereferencing. 18 Enumeration. 152 Sealed. 104 Query String. 115 binary representation. 127 Cookies. 83. 12 Identifiers. 7 Null character. 100 Exception Handling. 25 Keywords. 2 Keywords. 150 Integer division. 153 Cookies. 81 Session Object. 146 . 29 by reference. 19 Request Object. 68 Event. One-Dimensional. 12 Interface. 25 ASP. 146 Data Types. 40 Type conversion. 116 XML. Multidimensional. 68 Thread. 105 Thue-Morse sequence. Jagged. 11 Operator overloading. 3 Maths. 7 Floating point division. Deleting. 152 Structures. 148 Serialization. 64 Jagged arrays. 18 Preprocessor Directives. 27 Bitwise operation. 6 Worker threads. 37 Arrays.