Vous êtes sur la page 1sur 914

All Rights Reserved To EaglesGroup

Introduction
C# is Microsofts branded new language, designed for its brand new platform, the .NET Framework. As such as, C# is likely to be the language of choice for developing applications in the Microsoft world. That alone would make C# a great choice as a first language to learn. But, perhaps more importantly, C# is a very elegantly designed language, which encountered good programming practice (in particular with regard to object oriented programming). C# is descended directly from the powerful but complex C++ language, and inherits most of the power without the complexity. C# has also been deeply influenced by other languages, including Java and Delphi, and its fans believe that it has been able to take the best of these languages while avoiding their mistakes. C# is a C- based language that gives developers a language choice for developing with the .NET Framework. Some C, Java, And C++ development will move to C# to take advantage of the .NET features. Visual Basic programmers looking to learn a C language might also move to C#. Visual Basic.NET and C# both support Object Oriented development with the .NET Framework. No matter what language you choose for developing, being able to read code in either language will double your access to Microsoft Visual Studio documentation. And this book will also help you to guide you through step by step examples. The C# language is disarmingly simple, with only about 80 keywords and a dozen builtin datatypes, but C# is highly expressive when it comes to implementing modern programming concepts. C# includes all the support for structured, component-based, object-oriented programming that one expects of a modern language built on the shoulders of C++ and Java. The C# language was developed by a small team led by two distinguished Microsoft engineers, Anders Hejlsberg and Scott Wiltamuth. Hejlsberg is also known for creating Turbo Pascal, a popular language for PC programming, and for leading the team that designed Borland Delphi, one of the first successful integrated development environments for client/server programming. At the heart of any object-oriented language is its support for defining and working with classes. Classes define new types, allowing you to extend the language to better model the problem you are trying to solve. C# contains keywords for declaring new classes and their methods and properties, and for implementing encapsulation, inheritance, and polymorphism, the three pillars of object-oriented programming. In C#, everything pertaining to a class declaration is found in the declaration itself. C# class definitions do not require separate header files or Interface Definition Language (IDL) files. Moreover, C# supports a new XML style of inline documentation that simplifies the creation of online and print reference documentation for an application.

All Rights Reserved To EaglesGroup

C# also supports interfaces, a means of making a contract with a class for services that the interface stipulates. In C#, a class can inherit from only a single parent, but a class can implement multiple interfaces. When it implements an interface, a C# class in effect promises to provide the functionality the interface specifies. C# also provides support for structs, a concept whose meaning has changed significantly from C++. In C#, a struct is a restricted, lightweight type that, when instantiated, makes fewer demands on the operating system and on memory than a conventional class does. A struct can't inherit from a class or be inherited from, but a struct can implement an interface. This book has been designed to teach you C# form first principles, without assuming any prior programming experience. Well give you a through grounding in the syntax of the C# language itself, and then well look at the most common different types of application you can build with C# - Windows applications, ASP.NET web applications, and web services. Its important to stress from the outset that C# programming cannot be separated from .NET Programming (in fact, the C# compiler comes as part of the .NET Framework), and everything you do in C# will rely very heavily on the .NET Framework. Therefore, this book goes beyond the more syntax of the C# language and shows you how to use the .NET classes from within C# to build real applications. As a result, once, youve learned C#, you wont have too much difficulty picking up other .NET languages, such as Visual Basic. NET or Managed C++. This book has been written to be your complete Visual Studio (either 2003 or 2005 or 2008) support package. It has been designed to be the one you turn to first, the one that gives you more of what you want than any other. Weve crammed as much Visual C# into this book as possible, broken down into hundreds of easily accessible topics, each short and to point, and each with an example and the example with step by step guidance. The format here is like no other computer book series, and its deigned to give you exactly what you want, when you want it. And thats not an easy job, because the subject of this book, Visual C# is huge, Theres much more material here, in grater depth, and there are many more of the programming nuggets that programmers what to see.

All Rights Reserved To EaglesGroup

About this Book


This book is aimed at relatively inexperienced programmers who want to learn how to build applications using C#. Developers who have a little experience with earlier languages such as Visual Basic will also find this book helpful as hand on tutorial to C#. This book is for everyone whose tires of C# books that assume youve got five plus years experience of witting C++ programs! This book has been designed to give you the Visual C# coverage you just wont find any other book. Other books often omit not only the lager topics, like deploying you program after youve created it, but also the smaller ones like covering just about every Windows and Web Controls that comes with Visual C# such as the text box control to three state checkboxes from date time picker to hot tracking tab controls, and from web page validation controls to ad rotors. And the advanced topics are here too, and mostly some of the new software produces which are created by the C#.NET can also find in the CD along with this book, like creating your Windows and Web controls, writing Windows and Web services, distributed data applications, multithreading, security, remoting, deploying application, and more. In this book you will be get to knowing the both versions of the .NET 2003 and 2005 Versions but not in all the chapters in some of the chapters you will be able to learn the both versions of the Visual Studio.NET 2003, and 2005 This book will be ideal for two types of users: Youre a fresher to programming and youve choose C# as your first language. As we said earlier, C# is an excellent language to learn programming through, and this book will help you through the challenge of learning some strange new concepts! You have some experience programming in another language, but youre a fresher to .NET programming. .NET programming represents a revolution in programming concepts, and the fundamental importance of Object Oriented Programming (OOP) to .NET can be confusing if youre not familiar with this technique. If youre coming to C# from a language which doesnt support (or only partially supports) OOP, you will appreciate the entire section dedicated to OOP in this book. The task based format we use in this book is the one many programmers appreciate, because programming is task based business. Rather than reading about subjects in the order us might thing best, you can go directly to your topic of interest and find the bite sized nugget information you need.

All Rights Reserved To EaglesGroup

And best of all, theres a working example in code for almost every programming topic in the book. The actual process of programming is not abstract; its very applied, and so instead of vague generalities, we get down to the specifies all the specifies that give you everything you need to understand and use C#. Programmers are most interested in performing useful tasks , like adding buttons,
menus, list boxes, or ToolStrip to window; creating graphics animation; creating dialog boxes; creating setup programs; working with files; linking to Web pages; multi- threading and so on. And this book is written for programmers.

Because this book is written for programmers, each chapter is broken up into dozens of practical programming tasks. After selecting the chapter you want, you can turn to the Table of Contents, the Summary of Contents in the chapter to find the task youre interested in. Hundreds of tasks are covered in this book chosen specifically for programmers.

What Does This Book Cover?


This book was written using Version 2005 of the .NET Framework, and Version 1.0, 2.0 and 3.0 of Visual Studio.NET English Version. These versions are the release of these products, and no major changes are excepted in the near feature. This book is divided into seven main sections:

Getting Started In the first two chapters we quickly introduce the major concepts you need to understand
before witting a C# application, and then go on to create a very simple C# program using Visual Studio.NET 2005 to do most of the hard works for us.

C# Language Basics Some of the Chapters in this book will be introduce the basic building blocks of the C#
language. This section looks at how we store data, in C# variables, how we control the flow of our program with conditional branches and loops, and how we structure code with functions.

Programming with objects Objects and the principles of Object Oriented Programming (OOP) play a
fundamental role in C#, so we will introduce the notation of OOP and the philosophy behind it, and look at how we use objects with our C# code.

All Rights Reserved To EaglesGroup

Working with Windows Forms The First sections concentrate mostly on creating simple Console applications and
simple Windows Application in order to give you a through grounding in the C# language itself. In this section, we go beyond those to look in detail at how we create real Windows Application in C#

Programming on the .NET Framework As already mentioned, almost everything we do in C# is totally dependent on the .NET
Framework. This section looks at some important topics where we need to use classes form the .NET Framework, including accessing database and working with files to use classes from the .NET Framework, including accessing databases and working with files on the local machine or network. We also take a more detailed look at two features specific to .NET programming assemblies (the actual unit of deployment of .NET program), and attributes (a features of .NET that allows us to provide additional information about parts of our program).

C# and the Web Once weve come so far, well take a quick look at a whole new topic, but one thats
integral to the whole idea of the .NET Framework programming for the Internet. In this section of the book we look as ASP.NET and web services. ASP.NET allows us to write dynamic web pages in C#, and web services enable applications to exchange information across the internet.

Things Need to Use This Book The most important thing you need to write C# programs in the C# compiler itself.
This comes with the .NET Framework SDK, which, can be downloaded from the Microsofts site the following URL: http://msdn.microsoft.com/downloads/default.asp?URL=/code/sample.asp?url=/MSDNFILES/027/000/976/msdncompositedoc.xml

However, in this book we will be making heavy use of the Visual Studio.NET
development environment, which simplifies writing C# code in many years, but is particularly useful for writing Windows applications because it contains a visual from designer. If you are not using Visual Studio.NET (either 2003, or 2005, or 2008), then you will not be able to get full value from this book.

All Rights Reserved To EaglesGroup

System Requirements
Youll need the following hardware and software to complete the examples and to learn the stuff form this book: Microsoft Visual Studio.NET 2003, 2005 or 2008 edition or Microsoft Visual C # 2005 Express Editions. You must purchase it separately and install it before you can complete the examples in this book. A computer capable of running Microsoft Visual Studio.NET. The following hardware configuration is recommended by the Microsoft Visual Studio.NET Web site, at http://msdn.microsoft.com/vstudio/nextgen/ Computer/Processor PC with a Pentium II class processor, 450 megahertz (MHz); Pentium III- class processor, 600 MHZ or above recommended. Operating System Microsoft Windows 2000, 2003, 2008 Server, or Professional Microsoft Windows XP Home or Professional Microsoft Windows Vista Microsoft Windows NT 4.0 Server Memory Windows 2000, 2003, 2008 Professional, 96 megabytes (MB) or higher of RAM; 256 MB recommended Windows 2003, 2003, 2008 Server, 192 MB of RAM; 512 MS recommended Windows XP Professional, 128 MB or RAM; 256 Recommended Hard Disk 1 GB on System Drive and 3.0 gigabyte (GB) on the installation drive Drive CD-ROM or DVD-ROM Drive Display VGA or higher resolution monitor Input Device Microsoft Mouse or Compatible pointing device

All Rights Reserved To EaglesGroup

Conventions
There are a few conventions in this book that you should know about. Weve used a number of different styles of text and layout in this book to help different between the differentiate between the different kinds of information. Here are examples of the styles we used and expiation of what they mean. Code has several styles. If its a word that were talking about in the text for example, when discussing a for () loop, its in this font. If its a block of code that can be typed as a program and run, then its also in a gray box: private void btnMessage_Click(object sender, EventArgs e) { MessageBox.Show ("Hello! Eagles", "EaglesGroup",MessageBoxButtons.OK, MessageBoxIcon.Information ); } Some times well see code in mixture of styles, like this: private void btnMessage_Click(object sender, EventArgs e) { this.lblDisplay.Text = "Hello Eagles!"; } In case like this, the code with a white background is code we are already familiar with; the line highlighted in gray is a new addition to the code we last looked at it. Tips, DENOTES, and background information comes in this type of font. Important pieces of information come in like this Happy Programming Bullets appear indented, with each new bullet marked as follows: Using in the Table for the controls Important words are in this type

All Rights Reserved To EaglesGroup

Customer Support
We always value hearing from our readers, and we want to know what you think about this book; what you liked, what you didnt like, and what we can do better next time. You can send us your comments, either by returning the replay card in the book, or by e mail to eaglesbookfeedback@hotmail.com. Please be sure to mention the book title in your message

E-Mail Support
If you wish to directly query a problem in the book with an expert who knows the book in details then e mail eaglessbook@hotmail.com, eaglessiddhu@hotmail.com, with the title of the book and the number which is you e-name of the book printed in you book in the subject field of the e mail. The e name of the book can be found like this : QWERTY 12345 some thing like this

The email should contain like this:


Your name, contact information, and the problem in the body of the message For Your own safety we wont send you junk mail. We need to details to save your time and ours. When you send an e mail message, it will go through the following chain of support: Customer Support You message is delivered to our customer support staff; probably they are the first people to read it. They have files on most frequently asked questions and will answer anything general about the book. Editorial Deeper queries are forwarded to the technical editor responsible for that book. They have experience with the programming language or particular product, and are able to answer detailed questions on the subject. The Authors Finally, in the unlikely event the editor cannot answer your problem; they will forward the request to the author of the book. We do try to protect the author from any distractions to their writing; however, we are quite happy to forward specific requests to them. Once the e mail reaches to the author they will probably answer the quires to you e mail.

All Rights Reserved To EaglesGroup

Advantages of both languages

10

All Rights Reserved To EaglesGroup

Advantages of both languages

The choice between C# and VB.NET is largely one of subjective preference. Some people like C#'s terse syntax, others like VB.NET's natural language, case-insensitive approach. Both have access to the same framework libraries. Both will perform largely equivalently (with a few small differences which are unlikely to affect most people, assuming VB.NET is used with Option Strict on). Learning the .NET framework itself is a much bigger issue than learning either of the languages, and it's perfectly possible to become fluent in both - so don't worry too much about which to plump for There are, however, a few actual differences which may affect your decision

All Rights Reserved To EaglesGroup

11

C# XML documentation generated from source code comments. (This is coming in VB.NET with Whidbey (the code name for the next version of Visual Studio and .NET), and there are tools which will do it with existing VB.NET code already.) Operator overloading again, coming to VB.NET in Whidbey.

VB.NET Support for optional parameters very handy for some COM interoperability.

Support for late binding with Option Strict off - type safety at compile time goes out of the window, but legacy libraries which don't have strongly typed interfaces become easier to use. Support for named indexers.

Language support for unsigned types (you can use them from VB.NET, but they aren't in the language itself). Again, support for these is coming to VB.NET in Whidbey. The using statement, which makes unmanaged resource disposal simple.

Various legacy VB functions (provided in the Microsoft.VisualBasic namespace, and can be used by other languages with a reference to the Microsoft.VisualBasic.dll). Many of these can be harmful to performance if used unwisely, however, and many people believe they should be avoided for the most part.

12

All Rights Reserved To EaglesGroup

Explicit interface implementation, where an interface which is already implemented in a base class can be re-implemented separately in a derived class. Arguably this makes the class harder to understand, in the same way that member hiding normally does. Unsafe code. This allows pointer arithmetic etc, and can improve performance in some situations. However, it is not to be used lightly, as a lot of the normal safety of C# is lost (as the name implies). Note that unsafe code is still managed code, i.e., it is compiled to IL, JITted, and run within the CLR

The with construct: it's a matter of debate as to whether this is an advantage or not, but it's certainly a difference.

Simpler (in expression - perhaps more complicated in understanding) event handling, where a method can declare that it handles an event, rather than the handler having to be set up in code.

The ability to implement interfaces with methods of different names. (Arguably this makes it harder to
find the implementation of an interface, however.)

The VB.NET parts of Visual Studio .NET compiles your code in the background. While this is considered as an advantage for small projects, people creating very large projects have found that the IDE slows down considerably as the project gets larger.

All Rights Reserved To EaglesGroup

13

Programming Difference between C# & VB.NET Keyword Differences Programming Difference Operators Differences Data types Differences

14

All Rights Reserved To EaglesGroup

Programming Difference between C# & VB.NET

Keyword Differences Programming Difference Operators Differences Data types Differences

All Rights Reserved To EaglesGroup

15

Keyword Differences

Purpose Declare a variable

VB.NET

C#

Private, Public, declarations (keywords Friend, include user-defined types Protected, and built-in types) Static1, Shared, Dim const new void

Declare a named constant Const Create a new object New, CreateObject()

Function/method does not Sub return a value Overload a function or method (Visual Basic: overload a procedure or method) Overloads

(No language keyword required for this purpose)

Refer to the current object Me Make a nonvirtual call to MyClass a virtual method of the current object Retrieve character from a GetChar string Function

this n/a

[]

16

All Rights Reserved To EaglesGroup

Declare a compound data Structure struct, class, interface type (Visual Basic: <members> End Structure) Structure Initialize an object (constructors) Terminate an object directly Sub New() Constructors, or system default type constructors n/a

n/a

Method called by the Finalize system just before garbage collection reclaims an object7

destructor

Initialize a variable where it is declared

Dim x As Long // initialize to a value: =5 int x = 123; Dim c As New _ // or use default // constructor: Car(FuelTypeE int x = new int(); num.Gas) AddressOf (For delegate class members, this operator returns a reference to a function in the form of a delegate instance) volatile

Take the address of a function

Declare that an object can n/a be modified asynchronously

All Rights Reserved To EaglesGroup

17

Force explicit declaration Option Explicit n/a. (All variables must be of variables declared prior to use) Test for an object variable obj = Nothing that does not refer to an object Value of an object variable that does not refer to an object Test for a database null expression Test whether a Variant variable has been initialized Nothing obj == null

null

IsDbNull

n/a

n/a

n/a

Define a default property Default Refer to a base class Declare an interface MyBase Interface

by using indexers base interface class C1 : I1

Specify an interface to be Implements implemented (statement) Declare a class

Class class <implementation >

18

All Rights Reserved To EaglesGroup

Specify that a class can only be inherited. An instance of the class cannot be created. Specify that a class cannot be inherited Declare an enumerated type

MustInherit

abstract

NotInheritable

sealed

Enum enum <members> End Enum const (Applied to a field declaration) class C1 : C2

Declare a class constant Const Derive a class from a base Inherits C2 class Override a method Overrides

override abstract

Declare a method that MustOverride must be implemented in a deriving class Declare a method that can't be overridden

NotOverridable sealed (Methods are not overridable by default.) virtual

Declare a virtual method, Overridable property (Visual Basic), or property accessor (C#, C++)

All Rights Reserved To EaglesGroup

19

Hide a base class member Shadowing in a derived class Declare a typesafe reference to a class method Delegate

n/a delegate

Specify that a variable WithEvents can contain an object whose events you wish to handle

(Write code - no specific keyword)

Specify the events for Handles (Event n/a which an event procedure procedures can will be called still be associated with a WithEvents variable by naming pattern.) With objExpr Evaluate an object expression once, in order <.member> <.member> to access multiple End With members Structured exception handling n/a

Try <attempt> try, catch, finally, throw Catch <handle errors> Finally <always execute> End Try Select Case ..., switch, case, default, goto, Case, Case Else, break End Select

Decision structure (selection)

Decision structure (if ... If ... Then, if, else then) ElseIf ... Then, Else, End If

20

All Rights Reserved To EaglesGroup

Loop structure (conditional)

While, Do do, while, continue [While, Until] ..., Loop [While, Until] For ..., [Exit for, foreach For], Next For Each ..., [Exit For,] Next Dim a() As Long int[] x = new int[5];

Loop structure (iteration)

Declare an array Initialize an array Reallocate array

Dim a() As int[] x = new int[5] { Long = {3, 4, 5} 1, 2, 3, 4, 5}; Redim n/a public

Visible outside the project Public or assembly Invisible outside the assembly (C#/Visual Basic) or within the package (Visual J#, JScript) Visible only within the project (for nested classes, within the enclosing class) Accessible outside class and project or module Friend

internal

Private

private

Public

public

All Rights Reserved To EaglesGroup

21

Accessible outside the class, but within the project Only accessible within class or module

Friend

internal

Private

private protected

Only accessible to current Protected and derived classes Preserve procedure's local Static variables Shared by all instances of Shared a class Comment code ' Rem

n/a

static

//, /* */ for multi-line comments /// for XML comments Yes

Case-sensitive? Call Windows API Declare and raise an event Threading primitives Go to

No

Declare <API> use Platform Invoke Event, RaiseEvent SyncLock Goto event

lock goto

22

All Rights Reserved To EaglesGroup

Programming Difference
Purpose Declaring Variables Comments C# int x; int x = 10; VB.NET Dim x As Integer Public x As Integer = 10 ' comment x = 1 ' comment Rem comment nVal = 7 If nCnt <= nMax Then ' Same as nTotal = ' nTotal + nCnt. nTotal += nCnt ' Same as nCnt = nCnt + 1. nCnt += 1 Else nTotal += nCnt nCnt -= 1 End If Select Case n Case 0 MessageBox.Show ("Zero") ' Visual Basic .NET exits ' the Select at ' the end of a Case. Case 1 MessageBox.Show ("One") Case 2 MessageBox.Show ("Two") Case Else MessageBox.Show ("Default") End Select
23

// comment //Siddhu /* multiline comment Siddhu*/ Assignment nVal = 7; Statements Conditional if (nCnt <= nMax) Statements { nTotal += nCnt; nCnt++; } else { nTotal +=nCnt; nCnt--; } Selection switch(n) Statements { case 0: Console.WriteLine(" Zero"); break; case 1: Console.WriteLine(" One"); break; case 2: Console.WriteLine(" Two");

All Rights Reserved To EaglesGroup

break; default: Console.WriteLine(" ?"); break; } for (int i = 1; i <= 10; i++) Console.WriteLine( "The number is {0}", i); foreach(prop current in obj) { current=42; } public class BaseCls { // The element to be hidden public int Z = 100; public void Test() { System.Console.Writ eLine( "Test in BaseCls"); } }

FOR Loops

For n = 1 To 10 MessageBox.Show("The number is " & n) Next For Each prop In obj prop = 42 Next prop

Hiding Base Class Members

Public Class BaseCls ' The element to be shadowed Public Z As Integer = 100 public Sub Test() System.Console.WriteLine( _ "Test in BaseCls") End Sub End Class

Public Class DervCls Inherits BaseCls ' The shadowing element. Public Shadows Z As String = "*" public class DervCls : public Shadows Sub Test() BaseCls { System.Console.WriteLine( _ // The hiding "Test in DervCls") element End Sub
All Rights Reserved To EaglesGroup

24

public new string Z = "*"; public new void Test() { System.Console.Writ eLine( "Test in DervCls"); } } public class UseClasses { // DervCls widens to BaseCls BaseCls BObj = new DervCls(); // Access through derived //class DervCls DObj = new DervCls(); public void ShowZ() { System.Console.Writ eLine( "Accessed through "+ "base class: {0}", BObj.Z); System.Console.Writ eLine( "Accessed through"

End Class Public Class UseClasses ' DervCls widens to BaseCls. Dim BObj As BaseCls = New DervCls() ' Access through derived ' class. Dim DObj As DervCls = New DervCls() Public Sub ShowZ() System.Console.WriteLine( _ "Accessed through base "&_ "class: " & BObj.Z) System.Console.WriteLine(_ "Accessed through derived "&_ "class: " & DObj.Z) BObj.Test() DObj.Test() End Sub End Class

All Rights Reserved To EaglesGroup

25

+ " derived class:{0}", DObj.Z); BObj.Test(); DObj.Test(); } } while (n < 100) n++;

WHILE Loops

Parameter Passing by Value

Parameter Passing by Reference

' Test at start of loop While n < 100 . ' Same as n = n + 1. n += 1 End While ' /* DENOTE that ' The argument Y is there is 'passed by value. no way to pass Public Sub ABC( _ reference ByVal y As Long) types (objects) strictly 'If Siddhu changes y, the by value. You can changes do not affect x. choose End Sub to either pass the reference Siddhu(x) ' Call the (essentially a procedure. pointer), or ' You can force parameters to a reference to the ' be passed by value, reference ' regardless of how (a pointer to a ' they are declared, pointer).*/ ' by enclosing // The method: ' the parameters in void siddhu(int x) extra parentheses. { Siddhu((x)) ... } // Calling the method: siddhu(i); /* DENOTE that Public Sub Siddhu(ByRef y there is no As Long) way to pass reference ' The parameter y is declared
All Rights Reserved To EaglesGroup

26

Structured Exception Handling

types (objects) strictly by value. You can choose to either pass the reference (essentially a pointer), or a reference to the reference (a pointer to a pointer).*/ // Note also that unsafe C# //methods can take pointers //just like C++ methods. For //details, see unsafe. // The method: void siddhu(ref int x) { ... } // Calling the method: siddhu(ref i); // try-catch-finally try { if (x == 0) throw new System.Exception( "x equals zero"); else throw new System.Exception( "x does not equal zero");

'by referece: ' If ABC changes y, the changes are ' made to the value of x. End Sub Siddhu(x) ' Call the procedure.

Try If x = 0 Then Throw New Exception( _ "x equals zero") Else Throw New Exception( _ "x does not equal zero") End If Catch err As System.Exception MessageBox.Show( _ "Error: " &

All Rights Reserved To EaglesGroup

27

} catch (System.Exception err) { System.Console.Writ eLine( err.Message); } finally { System.Console.Writ eLine( "executing finally block"); } o = null;

Err.Description) Finally MessageBox.Show( _ "Executing finally block.") End Try

Set an Object Reference to Nothing Initializing System.DateTime dt Value = Types new System.DateTime( 2001, 4, 12, 22, 16, 49, 844);

o = Nothing

Dim dt as New System.DateTime( _ 2001, 4, 12, 22, 16, 49, 844)

28

All Rights Reserved To EaglesGroup

Operators Differences
Purpose Integer division Modulus (division returning only the remainder) Exponentiation Integer division Assignment Concatenate Modulus Bitwise-AND Bitwise-exclusiveOR Bitwise-inclusiveOR Equal Not equal Compare two object reference variables Compare object reference type Concatenate strings Shortcircuited Boolean AND Shortcircuited Boolean OR Scope resolution Array element Type cast Postfix increment Postfix decrement C# / % n/a /= += %= &= ^= |= == != == x is Class1 + && || . and base [] (type) ++ -VB.NET \ Mod ^ \= &= NEW n/a n/a n/a n/a = <> Is TypeOf x Is Class1 & AndAlso OrElse . () Cint, CDbl, ..., CType n/a n/a

All Rights Reserved To EaglesGroup

29

Indirection Address of Logical-NOT One's complement Prefix increment Prefix decrement Size of type Bitwise-AND Bitwise-exclusiveOR Bitwise-inclusiveOR Logical-AND Logical-OR Conditional Pointer to member

* (unsafe mode only) & (unsafe mode only; also see fixed) ! ~ ++ -Sizeof & ^ | && || ?: . (Unsafe mode only)

n/a AddressOf Not Not n/a n/a n/a And Xor Or And Or If Function () n/a

30

All Rights Reserved To EaglesGroup

Data types Differences


Purpose/Size Decimal Date (varies) 1 byte 2 bytes 2 bytes 4 bytes 8 bytes 4 bytes 8 bytes C# decimal DateTime string byte bool short, char (Unicode character) int long float double VB.NET Decimal Date String Byte Boolean Short, Char (Unicode character) Integer Long Single Double

All Rights Reserved To EaglesGroup

31

Chapter 01

32

All Rights Reserved To EaglesGroup

Introduction to Visual C# 2005


Visual C# 2005 has been greatly improved for Visual C# developers as it now includes new compiler features, new language constructs, and improved debugging. It also contains various new productivity features, like IntelliSense code snippets, Windows forms designer updates and Exception assistant. Beside these improved features, Visual C# 2005 introduces several language extensions, such as Generics, Anonymous Methods, Iterators, partial types, and Nullable types, all of which are discussed in later chapters.

Now lets see some of the new productivity features of Visual C# 2005

1.1 New Productivity Features in Visual C# 2005


In Visual C# 2005, the following new features have been added to increase the productivity of Visual C# developers. These new features help the developers to create C# applications easily and efficiency. Following is the list of new features added of Visual C# 2005. Features Intellisence code snippets features Description This new features allows a user to right click in the Visual C# code editor and choose a task from a hierarchical list. After the user selected a task form the hierarchical list, predefined code corresponding to the selected task is inserted into the source file. With this features, you can changes the code at the time of debugging, back up the code instruction pointer and execute the modifies code. Even in the Break mode, Visual C #developers can modify a code and debug the errors. This is a change in Visual C# 2005 that has been welcomed by all Visual C# developers. Visual C# 2005 now includes the AutoCorrect features that allow users, to identify the reason for non compilation of erroneous code. While using the AutoCorrect features, users can select an option from the multiple options, which are presented to them, to fix the erroneous code.

Edit and Continue

AutoCorrect

All Rights Reserved To EaglesGroup

33

Exception assistant

Snap lines

XML code comments

Use this feature to handle runtime exceptions in Visual C# 2005. The Exception assistant provides standard information about the runtime exception and suggests the methods that can be used to handle them. It may at most time provide the location of the line of code that has caused the runtime exception to occur. This is new feature that has been added to Windows Forms in Visual C# 2005. With snap lines features, you can easily align controls according to the alignment of other controls in Windows forms. Visual C# 2005 provides support for inserting XML based comments in a source code file. You can easily extract, parse, and convert these XML code comments into documentation.

1.2 Visual C# 2005 Language Improvements


A variety of new features have been incorporated in Visual C# 2005 programming that synchronizes the Visual C# with .NET Framework and makes it al leading programming language to be used for application development. Following is a list of these new features: Features Operator overloading Description This features of Visual C# 2005 allows Visual C# developers to overload operators, such as =,-,*, and /. Visual C# developers can use the operators features to use operators that include functionality, which has been overloaded by a particular class. Use Generics to parameterize classes, Structs, interfaces and methods by the types of data stored and manipulated by them. Generics are very useful when you want to parameterize common classes and structures in an application. The .NET Framework provides a set of generic collection classes as part of the System.Collections.Generic namespaces.

Generics

34

All Rights Reserved To EaglesGroup

Supporting of unsigned Integer Types

Partial Classes

Background Worker Object

With the support for unsigned Integer Types in Visual C# 2005, you can create and use .NET Framework unsigned types and also perform mathematical operations on the values of unsigned Integer Type. Visual C# 2005 not, only supports unsigned Integers Types fully, but also allows conversions between them. Use partial class features to split a single class into multiple files. This feature of the Visual C#2005 is most useful for code generators, such as Visual Studio that generate code in a file instead of as user written code. This feature helps handle asynchronous processing and ensure that the callback procedure runs in the correct thread. Background Worker Object is a component in Visual C# 2005 that you can easily drag from the Toolbox and drop it on the design surface to run slow running processes as background tasks.

1.3 The .NET Framework 2.0 and the Common Language Runtime
Visual C# 2005 is a component of revolution in Windows the .NET Framework. This framework provides the new support for softwares development and operating system support in Windows, and its more extensive than anything we have seen in Windows before. The .NET Framework wraps the operating system with its own code, and you Visual C# 2005 programmers actually deal with .NET code instead of dealing with the operating system itself. And it is specially designed to male working with the internet easy. At the base of the .NET Framework is the Common language Runtime (CLR). The CLR is the module, that is actually runs your .NET Application. When you create a Visual C# 2005 application, what really happens is that you r code is complied into the CLRs Intermediate Language (named MSIL, or IL for short), much like byte codes in Java. When you run the application, the IL code is translated into binary code that your code into something that your machines hardware, (or other software), can deal with directly. In this way, Microsoft may create a CLR for operating systems other than Windows, and your Visual C# 2005 applications, compiled into IL, will run on other platforms also.

All Rights Reserved To EaglesGroup

35

The .NET Framework class library is the second major part of the .NET Framework. The class library holds an immense amount of prewritten code that all the applications you create with Visual Basic, Visual C++, C #, and other Visual Studio languages are build on. The class library gives you program the support it needs for example, your program may create several forms, and as there is a class forms from scratch. All your code has to do is declare a new form, and the CLR compilers can get the actual code that supports forms from the .NET Framework class library. In this way, your programs can be very small compared to the earlier Windows applications because you can rely on the millions of lines of code already written in the class library not everything has to be in your applications executable (EXE) file.

All this assumes that you are working on a machine that has the .NET Framework, and therefore the CLR and the .NET Framework class library, installed. The code for elements we use in a Visual C# 2005 application forms, buttons, menu, and all the rest comes from the class library. And other programming, even in the same application. Also, distributing applications is easier, because all the support you need is already on the machine you installed you application to.

As mentioned, the .NET Framework organizes its classes into namespaces. For example, the .NET Framework includes the namespaces Microsoft.VisualBasic, Microsoft.Jscript, Microsoft.CSharp, and Micorsoft.Win32. In fact, these namespaces contain relatively few classes; the real way well interact with the .NET Framework class library in this book is through the System namespace.

1.4 So what Kind of Applications we can write Using the .NET Framework?
Writing an application using the .NET Framework means writing code (using any of the languages that support the framework) using the .NET code library. In this book well be using Visual Studio 2003 and 2005 for our development, which is powerful Integrated development environment that supports C# as well as managed and unmanaged C++, Visual Basic .NET, and some other languages. The advantages of this environment are the ease with which .NET features may be integrated into our code. The code that we will create will be entirely C#, but will use the .NET Framework throughout, and well make use of the additional tools in VS where necessary. In order for C# code to execute it must be converted into a language that the target operating system understands, know as native code. This conversion is called compiling code, an act that is performed by a compiler. Under the .NET Framework, however, this is a two stage process. 36
All Rights Reserved To EaglesGroup

1.5 MSIL and JIT


When we compile code that uses the .NET Framework library, we dont immediately create Operating System specific native code. Instead, we compile our code into Microsoft Intermediate Language (MSIL) code. This code isnt specific to any operating system, and isnt specific to C#. Other .NET languages - for example, Visual Basic.NET also compile to this language as a first stage. This compilation step is carried out by Visual Studio.NET when we use it to develop C# applications. Obviously, in order to execute an application more work in necessary. This is the job of Just In time (JIT) compiler, which compiles MSIL into native code that is specific to the OS and machine architecture being targeted. Only at this point can the OS execute the application. This Just In Time part of the name here reflects the fact that MSIL code is only compiled as and when it is needed. In the past it has often been necessary to compile your code into several applications, each of which targets a specific operating system and CPU architecture. Often this was a form of optimization (in order to get code to run faster on an AMD chipset, for example), but at times it was critical (for applications to work on both Win9x and WinNT/2000 environments, for example). This is now unnecessary, as JIT compilers (as their name suggests) use MSIL code, which is independent of the architecture, and the appropriate one will be used to create the native code required. The beauty of all this is that it required a lot less work on our part in fact we can just forget about system dependent details, and concentrate on the more interesting functionality of our code.

1.6 Assemblies
When we compile an application, the MSIL code created is stored in an assembly. Assemblies include both executable application files that we can run directly form Windows without the need for any other programs (these have an .exe file extension), and libraries for use by other applications (which have a .dll extension). As well as containing MSIL, assemblies also contain Meta information that information about the information contained in the assembly, also known as metadata and optional resources additional data used by the MSIL, such as sound files and picture. This Meta information allows assemblies to be fully self descriptive. We need no other information in order to use an assembly, meaning that we avoid situations such as failing to add required data to the system registry and so on, which was often a problem when developing using other platforms.

All Rights Reserved To EaglesGroup

37

You combine assemblies to form .NET application and, although we wont deal with them directly very often, we need to get the terminology down. An assembly holds the Intermediate Language (IL) modules for your application. When you create an Application in Visual C# 2005 and run it, Visual C# 2005 creates one or more assemblies, which are run by the CLR. That is, assemblies are how applications are interacting with the .NET Framework, instead of the EXE or DLL files of Visual C # 2005. Heres what in the .NET Assembly first is the manifest, which is similar to a table of contents, giving the name and version of the assembly. The manifest also lists the other assemblies needed to support this one, and explains how to handle security issues. The actual meat of the assembly is made up of modules, which are internal files of IL code, ready to run. Thats how Visual C# 2005 stores the IL is create. In module inside assemblies. Each module, in turn, contains types the classes and interfaces that you e code has denied, and that the assembly has to know about to let the various modules interact with each other. Although a lot happens behind the scenes with CLR and the .NET Framework takes care of most of the issues, getting most out of .NET and understanding how .NET works requires a through understanding of assemblies. This means that deploying applications is often as simple as copying the files into a directory on a remote computer. Since no additional information is required on the target systems, we can just run an executable file form this directory and assuming the .NET CLR is installed away we go. Of course, we wont necessarily want to include everything required to run an application in one place. We might write some code that performs tasks required by multiple applications. In situations like this, it is often useful to place this reusable code in a place accessible to all applications. In the .NET Framework, this is the Global Assembly Cache (GAC). Placing in the cache is simple we just place the assembly containing the code in the directory this cache but we will be looking more about the Assemblies in the Detailed Chapter named .NET Assemblies.

1.7 The System Namespaces


You cant build a Visual C# 2005 application without using the classes form the .NET System namespaces, as well see over and over again in this book. When you want to use a windows form, for example, you must use the System.Windows.Forms.Form class. A button in a Windows form comes from the System.Windows.Forms.Button class, and so on. There are many such classes organized into various namespace, like System.Windows.Forms. Heres an overview of some of those namespaces:

38

All Rights Reserved To EaglesGroup

Name System

System. Collections

System.Data

System.Data.OleDb System.Data.SqlClient System.Data.OracleClient System.Data.Odbc System.Diagnostics

System.Drawing System.Drawing.Drawing2D System.Drawing.Imaging System.Drawing.Printing System.Drawing.Text

Description It includes essential classes and base classes that define commonly used data types, events and event handlers, interfaces, attributes, exceptions, and so on. This namespace includes interfaces and classes that define various collections of objects, including such collections as lists, queues, hash tables, and dictionaries. It includes classes that make up ADO.NET; ADO.NET Lets you build data handling components that manage data from multiple distributed data sources. It includes classes that support the OLE DB.NET data provider. This namespace includes classes that support the SQL Server .NET data provider. It includes classes that support namespace in the .NET Framework data provider for ODBC This namespaces includes classes that support namespaces in the.NET Framework data provide for ODBC. It includes classes that allow you to debug your application and to step through your code. It also includes code to start system processes, read and write to event logs, and monitor system performance. It is used to provide access to the GDI+ graphical packages that give you access to drawing methods. It includes classes that support advanced two dimensional and vector graphics. It includes classes that support advances GDI+ imaging. It includes classes that allow you to customize and perform printing. It includes classes that support advanced GDI+ typography operations. The classes in this namespace allows user to create and use collections of fonts.

All Rights Reserved To EaglesGroup

39

System. Globalization

It includes classes that specify culture related informatics, including the languages, the country / region, calendars, the format patterns for dates, currency and numbers, the sort order for string, and so on. This namespace includes types that support synchronous and asynchronous reading from and writing to both data streams and files. This namespaces provides an interface to many protocols used on the Internet. This namespaces includes classes that support the Windows Sockets interface. If you have worked with the Winsock, API, you should be able to develop applications using the Socket class. It includes classes and interfaces that return information about types, methods and fields, and also have the ability to dynamically create and invoke types. It provides classes and interfaces that allow developers to create and configure distuburted applications. Well use the classes in the namespace heavily in .NET Assemblies chapter. It includes classes that support the structure of the Common Language Runtime (CLR) security system. It contains classes that can be used for serializing and deserialization objects. Serialization is the process of converting an object or a graph of objects into a liner sequencing of bytes for either storage of transmission to another location. Deserialization is the process of taking in stored information and recreating objects form it. It includes classes and interfaces that enable multithread programming.

System.IO

System.net System.net.Sockets

System. Reflection

System.Runtime.Remoting

System.Security System.Runtime.Serialization

System.Threading

40

All Rights Reserved To EaglesGroup

System. Web

System.Web.Security System.Web.Services

System.Windows.Forms

System.Xml

It includes classes and interfaces that supports browser/server communication. This namespace includes such as that manages HTTP output to the client; and the HTTPServerUtility class that provides access to server side utilities and processes. You can also use cookies, support file transfer, etc, with these classes. This namespace includes classes that are used to implement ASP.NET security in Web Server applications. This namespaces includes classes that let you to build and use Web services, programmable entities on the Web Server that the code can communicate with using standard Internet protocols. It includes classes for creating Windowsbased forms that make use of the user interface controls and other features available in the Windows operating system. It includes classes that support processing of XML

These, along with the many other System classes, from the foundation on which Visual C# 2005 applications rest. Its time now to start taking a look at how to build these applications. DENOTE: in todays scenario, organizations are faced with the growing demand for typical applications which requires user friendly interface that support 2D and 3D graphics. These applications should be based on process. Oriented architecture and address the problems of digital identities and support checking for phishing scams and communication with applications bases on other platforms using Service Oriented Architecture (SOA). To overcome all the problems of complex application requirements. Microsoft has introduced .NET Framework 3.0, which comprises of four different foundations with support of .NET 2.0. Try checking out these new foundations discussed at Chapter named called Overview of .NET Framework 3.0 Architecture

All Rights Reserved To EaglesGroup

41

1.8 Managed Code


The role of the CLR doesnt end once we have compiled our code to MSIL and JIT Compiler has compiled this to native code. Code writing using the .NET Framework is managed when it is executed (this stage is usually referred to as being at runtime). This means that the CLR looks after our applications, by managing memory, handling security, allowing cross language debugging, and so on. By contrast, applications that do not run under the control of the CLR are said to be unmanaged and certain languages such as C++ can be used to write such applications that, for example, access low level functions of the operating system. However, in C# we can only write code that runs in a managed environment. Well make use of the managed features of the CLR and allow .NET itself to handle any interaction with the operating system.

1.9 Garbage collection


One of the most important features of managed code is the concept of garbage collection. This is the .NET method of making sure that the memory used by an application is freed up completely when the application in no longer in use. Prior to .NET this has mostly been the responsibility of programmers, and a few simple errors in code could result in large blocks of memory mysteriously disappearing as a result of being allocated to the wrong place in memory. This usually meant a progressive slow down of you computer followed by a system crash. .NET garbage collection works by inspecting the memory of your computer every so often, and removing anything from it that is no longer needed. There is no set timeframe for this; it might happen thousands of times a second, once every few seconds, or whenever, but you can rest assured that it will happen. There are some implications for programmers here. Since this work is done for you at an unpredictable time applications have to be design with this in mind. Code that requires a lot of memory to run should tidy itself up rather waiting for garbage collection to happen, but this isnt anything like as tricky as it sounds. One big difference between C# and its predecessor, C++, is that C# implements true garbage collection in its runtime environment. To you, the programmer, the language, no longer requires you to remember the clean up of your allocations when you are done with them. This situation is a hug benefit over older languages, such as C and C++, because garbage collection eliminates many bugs in code. Memory leads and corrupted are both problems of the past in C#.

42

All Rights Reserved To EaglesGroup

DENOTE: C and C++ programmers take note: A destructor is not necessarily called when an object goes out of scope but when it is garbagecollected (which may happen much later). This is known as nondeterministic finalization. Java also implements garbage collection, but in a slightly different way. In Java, you must let the system to decide when to collect orphaned memory. This requirements leads to problems, such as slowing down of the system and then bogging down a time- critical section of code that is begin executed. In addition, because Java waits until the garbage collection is absolutely necessary, gathering up all the memory being freed can take some time, resulting in a wait for allocations. C# gets around these problems by allowing programmers to decide whether they want to force the issue of collecting the garbage or decide on a good time to do so .C# works better with garbage collection because that process was well thought out to begin with. C# implements the idea of generations in the code, which allow the classes to segment themselves so that garbage collection is done more easily. The memory and resources management has become very easy with the .NET Framework. Garbage collection is one such feature of the .NET technology that managess and allocates the resources. In all object oriented languages including C#, every type need to be allocated some memory space and requires some resources like screen, buffer, and memory network connections and so on. To use a resources, you first need to allocate memory so that the type thats need resources can be represented. A resource can be accessed by using the following steps:

Allocate memory for the type that represents the resource Initialize the instance members of that type to use the resource become usable Access the instance members of that type to use the resources Clean up and stake of resources And finally free the memory

With the Garbage Collector, the user does not have to worry about tracking how much memory is in use and when can it be free. Since memory id finite, some sort of collection is required to free the memory. The optimizing engine of the Garbage Collector determines when a collection should be preformed. It checks for the objects that are not being used by the application when a collection should be performed. It checks for the objects that are not being used by the application and then frees that part of the memory for being allocated to some other objects. The Microsoft .NET CLR (Common Language Runtime) allocates resources from managed heap, so that the user does not need to free the objects. It is done automatically when the application does not need the objects anymore. The Garbage Collector can know which objects are not in use by Metadata. Metadata describes the data type being used. With Metadata the CLR knows the layout of the objects in the memory which helps the Garbage Collector performs collection, it checks the object in managed heap that are no longer being used by the

All Rights Reserved To EaglesGroup

43

application and then reallocates that portion of memory to some other object. Most of the work done by the garbage collection mechanism is done through the System.GC object. DENOTE: The garbage collector destroys objects on the stack sometime after the stack frame they are declared within ends. Typically a stack frame is defined by a function. Thus, if you declare a local variable within a function, the object will be marked for garbage collection after the function ends. .NET Frameworks garbage collection implicitly keeps track of the lifetime of the objects that an application creates, but fails when it comes to the unmanaged resource (example a file, a window or a network connection) that objects encapsulate. In case of unmanaged resources encapsulated by objects, Object.Finalize method is used. This object contains a large number of methods that allow you to do things, such as force immediate garbage collection throughout the system (GC.Collect). You can suppress the call to Finalize for a given object (probably because it was called immediately) in the GC.SuppressFinalize method. Finally, you can call ReRegisterForFinalize method, which allows you to undo the result of SuppressFinalize for the given object. DENOTE: Unlike in Java, the call to Finalize ( ) in C# is actually guaranteed to happenunless the programmer explicitly permits it to be skipped. The garbage collector maintains a list of objects that have a destructor. This list is updated every time such an object is created or destroyed. When an object on this list is first collected, it is placed on a queue with other objects waiting to be destroyed. After the destructor executes, the garbage collector then collects the object and updates the queue, as well as its list of destructible objects.

1.10 File Extensions used in Visual C# 2003 and 2005.


When you save a solution, its given with the file extension .sln such as Eagles WindowsApplication.sln and all the projects in the solution are saved with the extension .csproj. The table which we will be going to see will list of the types of the file extensions youll see with files in Visual C# 2005 and as well as 2003 and the kind of files they correspond to. The most popular file extension is .cs. This is a useful list, because if Visual C# 2005 has added files to you solution that you havent excepted, you often can figure them out by their file extensions.

44

All Rights Reserved To EaglesGroup

File Extension .cs

Description If can be a basic Windows form or a code file for storing functions, a user control, a data form, a custom control, an inherited form, a Web custom control, an inherited user control, a Windows service, a custom setup file, an image file for creating a custom icon, or an AssemblyInfo file used to store assembly information such as version and assembly name. It is an XML schema provided to crate typed datasets. It is an XML document file It is an HTML document It is a text file. It is an XSLT stylesheet file, to transform XML document and XML schemas. It is a cascading style sheet file. It is a Crystal Report It is a bitmap file. It is a JScript file(Microsofts version of JavaScript) It is Windows scripting file. It is a Web form It is an active server pages It is a Web service class It is a dynamic discovery project; .vsdisco provides a means to enumerate all Web services and all schemas in a Web project.
All Rights Reserved To EaglesGroup

.xsd .xml .htm .txt .xslt .css .rpt .bmp .js

.wsf .aspx .asp .asmx .vsdisco

45

.web .asax .resx .config

It is a Web configuration file; .Web configures Web settings for a Web project It is a global application class, used to handle global ASP.NET application level events. It is a resource file used to store resource information These are application configuration files and contain settings specific to an application. This file contains configuration settings that the common language runtime reads (such as
assembly binding policy, remoting objects, and so on), and setting that the

application can read.

1.11 Solutions and Projects


When you create applications in Visual Studio 6.0, you created projects. Each project held the code and data for an application, ActiveX controls, or whatever else you wanted to build. If you wanted to combine projects together, you created a project group. In Visual C# 2005, however, project groups have become far more integral to the development process, and now theyre called solutions. By default, when you create a new project in Visual C# 2005, Visual C# will create a new solution first, and then add a project to that solution. For example, look at the Solution Explorer window, at right in the following picture:

46

All Rights Reserved To EaglesGroup

Above the properties window in that case, we have created our Visual C# project called Eagles WindowsApplication and you can see the project in the Solution explorer but note that Visual C# has also placed that project inside a solution with the same name, Eagles WindowsApplication. If we were to add new projects to the current solution which you can do with the New Project dialog box), those new properties would appear in the Solution Explorer as part of the current solution. This is a change from the previous version, where each project, such as the files form a form, items. So the terminology here is that solutions contain projects, and these in turn the projects contain items.

1.12 Debug and Release Versions


Note that so for we started our program from the Debug menus Start Option. This cause Visual C# to launch the program while staying in the background; if theres a problem, Visual C# will reappear to let you debug the programs code. Thats useful for development, of course, but when your program is ready to be used by others, your hardly want to launch your program form the Visual C#. Thats where the difference between debug and release versions of your program comes in. In a debug version of your program. Visual C# stores a great deal of data needed to

All Rights Reserved To EaglesGroup

47

interact with the debugger in you program when it runs, and this not only makes the corresponding assembly larger, but also slower. In the release version of your program, the program doesnt have all that added data, and can run as a stand alone program, without needing to be launched form Visual C# although it still needs the .NET Framework, of course. When you create a new solution, Visual C# creates it in Debug mode, meaning that you launch it from the Debug menu as we have been doing. However, you can switch to release mode in several ways like many things in Visual C# 2005, theres more than one way to do it. Select the Configuration Manger option in the Build menu. Then select Release in the Active Solution Configuration list box and click Close.

Select the solution you want to set the mode for by clicking it in the Solution Explorer, and find its Active Configuration property in the Properties Window.

48

All Rights Reserved To EaglesGroup

When you click the right handed column in the Properties window next to this property, a drop down list box will appear; select Release in that list box. Select the Solution you want to set the mode for by clicking it in the Solution Explorer, and select the Properties option in the Project menu, opening the solutions Property pages. Select the Configuration Properties node in the box at the left, and the Configuration item in that node.

Then select Release from the drop down list box in the Configuration column of the table that appears, and then click Close. Probably, the easiest way to set the Solution mode to release or Debug is simple to use the drop down list box that appears in the Visual C#.NET standard toolbar, at the top of the IDE. When you create a new solution or project, this list box displays the word Debug and all you need to do to switch to Release mode is to select Release instead. When you have set mode for a solution to Release, you build it using the Build menus Build option (the build option causes Visual C# to compile only the items it thinks have been newly changed. To force it to compile all items in the solution, choose the Rebuild All option, instead of Build). This builds the solution in a way so that others can use it, and you can deploy your program this way usually with the help of deployment project that you build in Visual C#, as well do later in the book. Now that we have the background we need on Visual C# 2005 solutions and projects, we can move ahead into the following chapters, where well assume this knowledge and put it to work. Well also take for granted that you know your way around Visual C# 2005 itself, so in this introductory chapter, well also take at the Visual C# Integrated Development Environment the Visual C# IDE.

All Rights Reserved To EaglesGroup

49

1.13 The Visual C# 2005 Integrated Development Environment


The IDE shown in the following picture, has become more complex that it was in the previous versions of Visual C#, and being able to use it, or at least knowing what the various parts are called, is a skill well need in the coming chapters. Part of the reasons more complex is that the same IDE is now shared by all Visual Studio languages, such as VB, C# (something Microsoft has promised for many years, but only implemented now).

There are so many independent windows in the IDE thats likely that you might misplace them if you try to rearrange them inadvertently. The IDE windows are docking windows, which means that you can use the mouse to move windows around as you like; when the windows are near an edge, theyll dock adhere to that edge, so you can reconfigure the IDE windows are you like. If you want the IDE windows inadvertently, dont panic; just use the mouse to move them back. Also note that the windows in the IDE come with a Close button (X) button at the upper left window. Dont click these buttons when we dont mean to, otherwise a window we wanted disappears. Its easy to panic: The toolbox is gone! Well have to reinstall everything, oh my god what I did to my self? In fact, in such a situation, all you have to do is to find that window in the View menu again (such as View | Toolbox or press Ctrl + Alt + X you will be having the toolbox in the Visual Studio.NET to make it reappear.

50

All Rights Reserved To EaglesGroup

DENOTE: That some windows are hidden in the View | Other Windows menu item, which opens a submenu of additional windows there are simple too many windows to fit them all into one menu without needing to use a submenu. Theres so much packed into the IDE that Microsoft has started to make windows share space, and you can keep them separate using tabs such as those you can see above the form at the center of picture above. If you click the Form1.cs[Design] tab, you see the form itself as itll appear when the program runs; if you click the Form1.cs, tab youll the forms code and if you click the Start Page tab, youll see the Start page, which lets you select from among the recent solutions to open. Also not that at the lower right Properties window and Dynamic Help windows a Visual C# 2005 feature are sharing the same space, and you can select between them using tabs. The IDE is a very crowded place, and in an effort to uncluttered the cluttered IDE a little, Visual C# 2005 adds a new button in doable IDE windows a little Thumb tack button at the upper right as you see in the various windows in the above picture, next to the Close button (X). This is the auto hide feature, which lets you reduce a window to tab connected to the edge its docked on.

As we see in the above picture, the Solution Explorer which lets you explore data sources on servers window is hidden and has become a tab in the IDE. If we click that tab, the full Solution Explorer window will glide open, covering most of the Toolbox. You can auto hide most windows like this; for example, if we were to click the Thumb tack button in the Toolbox, it would close and become a tab under the Server Explorer tab in the IDE. To restore a window to stay open status, just click the Thumb tack again. And, of course, you can customize the IDE as well. For example, to customize IDE options, such as the fonts and color used to display code, select the Tools | options option and use the various items in the Environment node. As shown in the below picture. To customize menus and toolbars, such as specifying the toolbars to display, or what toolbars, use to Tools | Customize option.

All Rights Reserved To EaglesGroup

51

DENOTE: The Visual Studio.NET 2005 works only with the .NET Framework 2.0. IF you need to develop applications for the .NET Framework Version 1.1 you need to Installed which means you need to have Visual Studio 2003 on your machine. Visual C# 2.0 language version for creating a Visual C# 2005 0 based application. But in case you have a project or an application which has been created using the Visual Studio 2003 .NET Environment. No problem here the Visual Studio 2005 will over come the problem for you by automatically when you try to open the Project version of 2003 in 2005 the Visual Studio 2005 Will automatically open the Upgrade wizard to you so you can use the Wizard for the upgrade the 2003 to 2005. For more familiar please follow the following steps:

1.14 Upgrading Project Form Visual C# 2003 to Visual 2005


The difference between Version 2003 and Version 2005 is great, and to help you upgrade. Visual C# 2003 projects to Visual C# 2005, Microsoft created the Visual C# 2005 Upgrade Wizard. This wizard is automatically invoked when you try to open the Visual C# 2003 project in Visual C# 2005, and you can see it in the Following Picture: And follow the Steps:

52

All Rights Reserved To EaglesGroup

Step1:
Click the File | Open | Project/Solution and select the project version of Visual C# 2003 and in the select the .sln file

Step2:

Select the file with the extension of .sln and then click OK button.

All Rights Reserved To EaglesGroup

53

Step3:
You should probably see the Visual Studio Conversion Wizard which will automatically convert the Visual 2003 Version of project to Visual C# 2005 Project.

54

All Rights Reserved To EaglesGroup

Step4:
The Wizard will ask you to create a back up or not you can either select on you choice, if click ye, create a back up you will can see the back up files in the exact folder where you the old version project you choose. There will be a folder called Backup so you still have a back up of the old version Visual C# 2003. But if you choose the Wizard will not create the Backup in the folder it will go the next procedure

All Rights Reserved To EaglesGroup

55

Step5:
Following by the step 4 after you click the Next button the wizard should show the complete summary of the conversion of the file which you selected to convert. The Visual C# 2003 Version of project which you have selected has almost converted

56

All Rights Reserved To EaglesGroup

Step6:
Now the Visual Studio Conversion Wizard will ask you either you want to see the logs of the conversion or not by providing the check box, if you click the check box the wizard will show you the logs which has been created while the Visual Studio Conversion Wizard running. If you didnt click the check box and press the Close button and you r Visual C# 2003 Version project now open in the Visual 2005 IDE.

All Rights Reserved To EaglesGroup

57

1.15 The Start Page


We have already seen the Start page, which is what you se when you first start Visual C#. You can use the Start page to select form recent projects; by default, the Getting Started item is selected in the Start page at upper left. You can also create a new project here by clicking the New Project button. The Start page has other useful aspects as well for example, because you use the Same IDE for all Visual Studio languages, itll also search through all those languages when you search the help files. To make it search only pertinent help files, you can select the My Profile item in the Start Page, and select either Visual C# or Visual C# related in the Help Filter drop down list box. DENOTE: The Start page is actually being displayed in a browser. Its URL us vs:/default.htm, as you can see in a drop down list box above the Start Page. Entering a new URL in that drop down list box and pressing Enter navigates to that new URL, replacing the Start page. And if you have an URL in your code a quoted sting that beings with http://, Visual C# 2005 will turn that text into a hyperlink, underline it, and allow you to click that URL to bring up the corresponding web pages in place of the Start page.

58

All Rights Reserved To EaglesGroup

1.16 The Menu


After you started Visual C# and have seen the Start Page, you often turn to the menu to processed, as when you want to create a new project and use the File | New | Project option to bring up the New Project dialog box you can do the same thing by clicking the New Project Button in the Start Page. The IDE menu is very involved, with many items to choose from you dont even see it all at once. The menu system changes as you make selections in the rest of the IDE, example the Project menu will display 17 items if you first select a project in the Solution Explorer, but only 4 items if you have selected a Solution, and not a project. In fact, there is even more dramatic change, for example, try clicking a form under design and youll see a Data menu in the menu bar use to generate datasets. If you then select not the form but the forms code, however example, double click the form to open the Code window, the Data menu disappears. There are hundreds of menu options here, and many useful ones that will quickly become favorites, such as File | Project that you use to create a new project, or the most recently used (MRU) list of files and projects that you can access from the Recent Files or Reset Projects options neat the button of the File Menu.

All Rights Reserved To EaglesGroup

59

1.17 The Toolbars


The toolbars features are another handy aspect of the IDE. These appear near the top of the IDE, as shown in the below picture. There are plenty of toolbars to choose from, sometimes Visual C# 2005 will choose for you, as and when it displays the Debug toolbar when you have launched a program with the Start in the Debug menu.

Because the IDE displays tool tips those small yellow windows with explanatory text that appears when you let the mouse reset over controls such as buttons in a toolbar, its easy to get to know what the buttons in the toolbars do. As mentioned, you can also customize the toolbars with the IDE, selecting which toolbars to display or customizing which buttons to appear in which toolbars with Tools | Customize option, or you can right click a toolbar itself to get a menu of the possible toolbars to display the bottom item in this popup menu is Customize which lets you customize which buttons go where, or you can open the toolbars submenus in the View menu to do the same thing as is often in Visual C#, theres more than one way to do it. Toolbars provide a quick way to select menu items, and although we usually stick to using the menu system, theres no doubt that toolbar buttons can be quicker. For example, to save the file you are currently working on, you only need to click the Diskette button in the Standard toolbar as you seen in the above picture.

60

All Rights Reserved To EaglesGroup

1.18 The New Project Dialog Box


When you want to create a new project, you turn to the New Project dialog box. We have used the New Project dialog box quite a bit. In addition to letting you select from all the possible types of projects you can create in Visual C#, you can also set the name of the project, and its location; for Windows projects, the location is a folder on disk, but for Web projects, you specify a server running IIS. The following picture shows the IIS information.

All Rights Reserved To EaglesGroup

61

1.19 Graphical Designers


When you are working on a project that has user interface elements, such as forms, Visual C# 2005 can display what those elements will look at runtime, and, of course, thats what makes Visual C# visual. For Example, when you are looking at a Windows Forms, you can actually looking at Windows Form Designer, as what you see in the following Screenshot and you can manipulate the form, as well as add controls to it and so on. There are several different types of Graphical designers, including:

Windows Form Designers Component Designers XML designers You can have noticed or, may already know that Windows forms display a grid of dots around the form. To set the grid spacing, whether or not the controls should snap to the grid thats the position their corners on grid points, you can use the Tools | Options, options to open the Options dialog box, and select the Windows Form Designer node, displaying the possible options for you to set.

62

All Rights Reserved To EaglesGroup

1.20 Code Designers


Code Designers, let you edit the code for a component, and you can see a Code Designer in the below picture.

You can use the tabs at the top center of the IDE to switch between Graphical Designer, such as tabs Form1.cs[Design] that will display a Graphical Designer, and the Form1.cs tab that display the corresponding Code designer. You can also switch between Graphical and Code Designer using the Designer and Code options in the View menu, or you can use the top two buttons at left in the Solution Explorer. Note the two drop down list boxes at the top of the Code designer the one on the left lets you select what objects code you are working with, and the one on the right lets, select the part of the code that you want to work on, letting you select between the declarations are, functions, and method all of which well see on the Chapter 2,. The declarations area, which you select by selecting the Declarations item in the right handed list box, is where you can put declaration of objects. When you double click a control in a Graphical designer, its Code designer will open and Visual C# creates an event handler for its default such as Click event for button which is a procedure that is called when the event occurs. To add code to a different event handler, select the object you want to work with in the left handed drop down list box in the Code designer, and the event you want to add code to in the right hand drop down list box; Visual C# will create an event handler for the event. Which you are see in the below picture
All Rights Reserved To EaglesGroup

63

Also note the + and -boxes in the Code designers text area, at the left. Those are new in Visual C# 2005, and were introduced Visual C# 2005 now writes a great deal of code for your forms and components automatically. You can use the + and buttons to show or hide that code.

64

All Rights Reserved To EaglesGroup

1.21 IntelliSence
One of the best and useful features of Visual C# 2005 Code Designers is Microsoft IntelliSence. IntelliSence is whats responsible for those boxes that open as you start to type or write you code, listing all the possible options and even completing youre typing for you. IntelliSence is one of the first things you encounter when you use Visual C# 2005, and you can see an example of this in the following screenshot. Where we are looking at all the members of a text box object. DENOTE: If you enter some code that Visual C# 2005 consider as syntax error, it will underline the error with a wavy red line. You can rest the mouse over the underlined text to see a tool tip explaining what Visual C# 2005 thinks is wrong. Thats not part of the IntelliSence package, although it also useful.

IntelliSence is made up of number of options, including the following feature: List Members It lists the members of an object. Parameter Info It lists the argument of procedure calls. Quick Info It display information in tool tips as the mouse resets on element in your code. Complete Word It completes types word. Auto Brace Matching It adds parentheses or braces as needs.

All Rights Reserved To EaglesGroup

65

Theres also a Visual C# - specific IntelliSence, which offers tips that displays the syntax of the statement you are typing. Thats grate if you know what statement you want to use but dont recall its exact syntax, because its syntax is automatically displayed. IntelliSence is particularly useful when you cant remember what arguments a built in Visual C# procedure accepts, because itll display those arguments as you type in the call to the procedures. IntelliSence is something you quickly get used, to, and come to rely on. However, you can turn various parts of IntelliSence off id you want just select the Tools | Options option, and then select the Text Editor node, then the C# item and finally the General item. Youll see a number of IntelliSence options you can turn on and off with the Check boxes.

DENOTE: IntelliSence has improved in the new Version of .NET such as Visual Studio .NET 2003, IntelliSence provided you the list of possible options from the very first item in the list. Now it remember you preferred to choice once you make a selection and start from there only the next time it appears.

66

All Rights Reserved To EaglesGroup

1.22 The Object Browser:

IntelliSence is useful because it tells you what syntax is correct automatically, or lists all the members of an object that are available. Another useful tool thats often overlooked by Visual C# programmer is the Object browser. This toll lets you look at all the members of an object at once, which is invaluable to pry into the heart of objects you have added to your code. The Object browser helps open up any mysterious object that Visual C# has added to your code so you can see whats going on inside. To open the Object Browse, Select View | Object Browser can see the above picture. The Object Browser shows all the objects in your program and gives you access to whats going on in all of them. For example, in the above picture, we are looking at a Windows form, Form1 and all its internal members and the parameters they are made visible. To close the Objects browser, just click the Close button at its upper right.

All Rights Reserved To EaglesGroup

67

1.23 The Toolbox


The Toolbox contains a selection of all the controls available to you as a .NET developer. And Visual C# developers are familiar with, and you can see it in the Following Picture. Microsoft has crammed more into the Toolbox with each successive version of Visual C#, and now the Toolbox uses tabs to divide its contents into categories. You can see these tabs, marked such as All Windows Forms, Common Controls, Containers
Menus and Toolbars, Data, Components, Printing Dialogs Crystal Reports and General in the toolbox.

With the help of the advanced toolbox the programmer or the user can choose what controls they want to have it in the proper manner so they either no need to confuse.

The tabs available as you might guess depend on the types of project you are working on and even the types of designer you are working with. The All Windows Forms,
Common Controls, Container, Menu & Toolbars, Data, Components, Printing, Dialogs, Crystal Reports. Appear when you are working with the Windows Form

Designer only. However when you are in the Code Designer you can use the Toolbox as a clipboard to copy and past the codes.

68

All Rights Reserved To EaglesGroup

As what we can see in the following picture:

When you working on a Web Application, you will able to see the Standard, Data,
Validation, Navigation, Login, WebParts, HTML, General.

All Rights Reserved To EaglesGroup

69

The Data tab displays tools for creating datasets and making data connection the All Windows forms tab displays tools for adding controls to Windows Forms the Standard tab display tools for adding server control and so on. The General tab is empty by default, and is a place to store general controls, and fragments of code in. Even you can add more tabs to the Toolbox by right clicking the Toolbox and selecting the Add Tab option. In fact, there are many controls that even when you click a tab in the Toolbox, youll still mostly likely get a list that you have to scroll to see everything thats available.

70

All Rights Reserved To EaglesGroup

1.24 The Solution Explorer


This Window gives you an overview of the solution you are working with, including the entire project in it, and the items in that project. As you can see the Solution Explorer in the Following picture:

This tool displays a hierarchy with the solution at the top of the hierarchy, the projects one step down in the hierarchy, and the items in each projects as the next step down. You can set the properties of various items in a project by selecting them in the Solution Explorer then setting their properties in the Properties Windows. And you can set properties of solution and projects by right clicking them, and selecting the Properties option in the menu that appears, or you can select an item and click the Properties button which is the right most buttons at the top of the Solution Explorer. There is an option called Show All Files in the Solution Explorer. If you click the option it will show all the Files in the Project.

All Rights Reserved To EaglesGroup

71

If you are working on an object that has both a user interface and code, you can switch between the Graphical and Code Designer by using the buttons appears at the top left in the Solution Explorer when that object has been selected. You can right click a solution and add a new project to it by selecting the Add | New Project option in the popup menu that appears. And you can specify which of the multiple project to run first the startup project or projects by right- clicking the project and selecting the Set As Startup Object option, or by right clicking the solution and selecting the Set Startup Projects option. Much of what goes in the Visual C# 2005 IDE depends on which solution or project is the current one, and you set that by selecting it in the Solution Explorer. For example, you can specify what icon you want to an application to use in Windows if you dont like the plain default one. To do that, you select its project in the Solution Explorer, select Properties option in the Project Menu, open the Application tab, then browse to the .ico file you want and click OK.

72

All Rights Reserved To EaglesGroup

The Solution Explorer tracks the items in your project to add new items you can use the menu items in the Project menu such as Add Windows form and Add User Control. To add new interface, user control, or class to a project. But we will be seeing more in details in the coming chapters, you can use the Project | Add New option.

All Rights Reserved To EaglesGroup

73

The Solution Explorer see things in terms of files, as you can see in the following picture. There, the References node holds the currently referenced item such as namespaces in a project, Assembly Info.cs is the file that holds information about the assembly you are creating, and Form1.cs is the file that holds the code for the form under design. However theres another way of looking at Object Oriented Programs in terms of classes and the Class View window does that. The data in AssemblyInfo.cs gives all kinds of information about the assembly, such as its version number. To set the version number of the assembly you are creating. Open the AssemblyInfo.cs and edit the line which is highlight in the Gray color box using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Eagles WindowsApplication")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("EaglesGroup")] [assembly: AssemblyProduct("Eagles WindowsApplication")] [assembly: AssemblyCopyright("Copyright EaglesGroup 2008")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("88cade17-f410-412d-8963-062518acafef")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]

74

All Rights Reserved To EaglesGroup

1.25 The Class View Window


If you click the Class View tab under the Solution Explorer or select View | Class View, youll see the Class View Windows as shown in the below picture:

This View presents solution and projects in terms of the classes they contain, and the members of these classes. Using the Class View Window gives you an easy way of jumping to a member of class that you want to access quickly just find it in the Class View Window and double click it to bring up in a Code designer.

All Rights Reserved To EaglesGroup

75

1.26 The Properties Window

The Properties window as shown in the above picture is another old favorite in Visual C#, although now it shares its space with the Dynamic Help Window. You set the properties of various objects in Visual C# to customize them. For example, we have set the Text property of a the Form1 to Eagles Form1 to do that we need to right click the Window Form and look for the Text property and the Type the Eagles Form1 so it will appear in the Form1.cs. To set object properties when you are designing your program in Visual C# - called design time as opposed to runtime you can select that object by clicking a control or form, or project, or a solution and then set the new property values you want in the Properties window. The Properties Window is divided in to two columns of text with the properties on the left, and their settings on the right. The object you are setting properties for appear in the drop down list box at the top of the Properties window, and you can select from all the available objects using that list box. When you select a property, Visual C# will give you an explanation of the property in the panel at the bottom of the Properties Window, as you see in above picture.

76

All Rights Reserved To EaglesGroup

You can display the properties alphabetically by clicking the second button from the left at the top of the Properties window, or in categories by clicking the left most buttons. To change a propertys setting, you only have to click the right handed column next to the name of the property, and enter the new setting. Often properties can have only a few specific values, in which case Visual C# will display a drop down list box next to the propertys name when you click the right- handed column, and you can select values from the list, Sometimes, Visual C# requires more information, say to create data connection, instead of list box, a button with an ellipsis (..) appears. In that case when you click that button, Visual C# will usually walk you through the steps it needs to get that information. Note also that, as usual with properties and methods in Visual C#, not all properties of a form or control will be available at design time in the Properties window when you are designing your code some will be available only at runtime. In fact, there arent many changes in the Properties window from previous versions of Visual C# something Visual C# programmers might be placed to hear, so if you have used it before, you are all set.

1.27 The Dynamic Help Window


The Window that shares the Properties windows space, however, is quite new the Dynamic Help window. Visual C# 2005 includes the useful Help menu with Contents, Index and Search Option, of course, but now it also support dynamic help, which looks things up for you automatically. You can see the Dynamic Help window by clicking the Dynamic Help tab under the Properties window or by Selecting Help | Dynamic Help.

All Rights Reserved To EaglesGroup

77

Visual C# 2005 looks up all kinds of help topics on the element you have selected automatically, for example, we have selected the Textbox on the Windows Form, and Dynamic Help Window has responded by displaying all kinds of helpful links to information on the buttons. This is more helpful than simply searching the whole system for the word TextBox. Because dynamic help will typically select introductory and overview help topics, not all the hundreds of topic with the word button in their text. If you click a help a help link in the Dynamic Help Window, the corresponding help topics is opened in the central space of the IDE where the designers appear you can switch between designers and help topics using tabs. Some times you may find it too cramped in the IDE to display help topics effectively. You can have Visual C# 2005 display help in an external IDE- Independent window instead. If you wish Select Tools | Options menu bar option and then Help option in the Environment node and the Click OK.

78

All Rights Reserved To EaglesGroup

1.28 Component Trays


In the Visual Studio 2003 Version, when you add a component to a form, and that component isnt visible at runtime such as a timer control timer would still appear on the form at design time. Thats changed in Visual C# 2005. Now when you add components that are invisible at run time, theyll be appearing in a component tray, which will appear automatically in the designer, as you can see in the following picture:

All Rights Reserved To EaglesGroup

79

1.29 The Server Explorer

By using the Server Explorer, which appears in the above picture, which will help to explore the things in the Server, and its great tool to help make distant servers feel less distant, because you can see everything you need in an easy graphical environment. You can do more than just look using the Server Explorer too you can drag and drop whole items onto Windows forms or Web forms the Server Explorer. For example, if you dragged a data table onto a form, Visual C# 2005 would crate the connection and command objects you need to access that table from the code.

80

All Rights Reserved To EaglesGroup

1.30 The Output Window


If you look at the bottom of the IDE, youll see two tabs for the Output and Breakpoints windows. Well look at the Breakpoints window when we discuss debugging, because it lets you manage the breakpoints at which program execution halts when you are debugging your code. The Output window, which you see in the following screenshot: You can also send messages to the Output window yourself if you use the System.Diagnostics.Debug.Wite method:

System.Diagnostics.Debug.Write("Welcome to EaglesGroup!");

All Rights Reserved To EaglesGroup

81

1.31 The Task List


The Task List is another useful window that not many Visual C# programmers know about. To see it, select the View | Task List the task list which you can see in the below screenshot. As its name implies, the Task List displays that Visual C# 2005 assumes you still have to take care of, and when you click a task, the corresponding location in a Code designer appears.

The Task List window helps create and manage programming tasks. For example, it allows you to enter notes on tasks to be done as Under Tasks. It also allows you to display comments to the lines in your code files where some work needs to be done by you. In fact, you can create your own custom controls that the Task List will track. To so, select Tools | Options then select Task List item in the Environment node and enter the name of your custom comments in the Comment Token area. For example if we entered Siddhu there, then any comments beginning with Siddhu will be tracked in the Task List.

82

All Rights Reserved To EaglesGroup

All Rights Reserved To EaglesGroup

83

1.32 The Error List


The Error List window, which is new, features in the Visual C# 2005 and also in the Visual C# 2008, which will display the program error and warning for you in the current project. For example you are suing a variable that has not been declared, and then error List window will display the error corresponding to it, lets have look in the following screenshot which will show the error in the Error List Window.

DENOTE: If the Error List is not displayed on you Visual Studio.NET 2005 then you can access it by selecting View | Error List, or by simply Pressing Ctrl + W, E. There are various columns in the Error List window like Description Filter Line and Column that help you to provide complete information about the errors and warning.

84

All Rights Reserved To EaglesGroup

1.33 The Command Window

There are plenty of other windows available and the Command window is one of them. Selecting View | Other Windows | Command Window opens the Command Window, as you can see the above picture. This window is little like the immediate window in previous version of Visual C#, because you can enter commands like Macros.Samples.AddDirAsSlnFolder.GenerateSlnFolderOnDirStructure, File.AddNewProject, File.AddNewWebPoject here. Visual C# 2005 will display the Add New project. For example if you enter the following Command Macros.Samples.AddDirAsSlnFolder.GenerateSlnFolderOnDirStructure it will ask you to enter Enter a folder path to import the macros as we can see it in the following picture:

All Rights Reserved To EaglesGroup

85

However, this window is not exactly like the immediate windows, because you cant enter Visual C# code in it and have it executed. There are other windows that well discuss later during debugging program section such as the Call Stack Window, and so on. The Break Points Windows, Watch, and Value display windows, Autos, and Locals macros to execute a series of commands in the Visual Studio Environment. If you want to give macros a try, take a look at the Macros in the Tools menu. Theres more to the IDE that bears its mention macros. You can use macros to execute a serious of commands in the Visual Studio environment. If you want to give a macros a cover here, but now we have gotten the foundation well need in the coming chapters.

86

All Rights Reserved To EaglesGroup

Summary
In this chapter, we have covered an introduction of Visual C# and the improvements and added new features such as: Visual C# 2005 Introduction Productivity features of Visual C# 2005 Visual C# 2005 Language Improvements .NET 2.0 and CLR Applications Which can Support Using the .NET Framework MSIL and JIT Assemblies The System Namespace Managed Code Garbage Collection File Extension of Visual C# 2003 and Visual C# 2005 Solutions and Projects Debug and Release Version Visual C# 2005 IDE Upgrading Form Visual C#2003 to Visual C# 2005 The Start Page The Menu The Toolbars The New Project Dialog box Graphical Designers Code Designers IntelliSence The Object Browser The Solution Explorer The Class View Window The Properties Window The Dynamic Help Window Component Trays The Server Explorer The Output Window The Task List The Error List The Command Window

All Rights Reserved To EaglesGroup

87

Chapter 02

88

All Rights Reserved To EaglesGroup

Writing a C# Program in 2003 Visual Studio.NET


Now weve spent some time in discussing what C# is and the difference between the Visual Basic and C#. And how it fits into the .NET Framework, its time to get our hands dirty and write some code. First lets us look about the Visual Studio.NET 2003, and 2005 (VS) throughout this book, so this first thing to do is to have a look at some of the basics of this development so in this chapter we will be looking about the Visual Studio.NET 2003 development environment. VS are an enormous and complicated product, and can be daunting to first time users, but using it to create simple application can be surprisingly simple. As we start to use VS in this chapter, we will see that we dont need to know a huge amount about it in order to start playing with C# code. Later on in the book we will see some of the more complicated operations that VS can perform, but for now a basic working knowledge is all that is required. Once weve had a look at VS, well put together two simple applications. We wont worry too much about the code in these for now, well just prove that things work and run through the application creation procedures that will becomes nature before too long. The first application well create will be simple Console Application. Console Application are those that dont makes use of the graphical window environment, so we wont have to worry about buttons, menus, interaction with the mouse pointer, and so on. Instead, we will run out application in a command prompt window, and interact with it in a much simpler way. The second application will be a Windows Forms Application. The look and feel of this will be very familiar to Windows users, and (surprisingly) the application doesnt require much more effort to create. However, the syntax of the code is more complicated, even though in many cases we dont actually have to worry about details. Well be using both types of application over the next two section of this book, with slightly more emphasis on Console Application to start with. The additional flexibility of Windows Application allows us to concentrate on learning the syntax and dont worrying about the look and feel of application. So, without further ado, its time to get started amigos!

All Rights Reserved To EaglesGroup

89

2.1 The Visual Studio .NET Development Environment


When Visual Studio .NET (VS) is first loaded, it immediately presents us with a host of windows, most of which are empty, along with an array of menu items and toolbar icons. We will be using most of these in the course of this book, and you can reset assured that they will be look far more familiar before too long. If this is the first time you have run Visual Studio you will presented with a list of preferences indented for users with experience of previous release of this development environment. The previous of version of the Visual Studio 2003 is 2002 which is released in late January 2002 and Version 1.0 of Visual Studio .NET, released in February 2002. The defaults setting for these are fine, so just accept them for now there is nothing here that cant be changed later. The Visual Studio .NET 2003 environment layout is completely customizable, but again the default is fine for us. It is arranged as follows:

90

All Rights Reserved To EaglesGroup

The main window, which display an introductory start page when the Visual Studio is started, is the one where all our code will be displayed. This window is tabbed so that we can switch between several files with ease by clicking on their filenames. It also has other functions: it can display graphical user interfaces that we are designing for our projects, plain text files, HTML, and various tools that are built into Visual Studio. Well describe all of those as we come across them in the course of this book. Above the main window, we have toolbars and the Visual Studio menu. There are several different toolbars that can be placed here, with functionality ranging form saving and loading files, to building and running projects, to debugging controls. Again, well discuss these as and when we need to use them. Here are brief description s of each of the main features of Visual Studio. NET 2003 that you will use the most: The Server Explorer and toolbox pop us when the mouse over them, and provide various additional capabilities, such as providing access to server setting and services, and access to the user interface building blocks for Windows applications. The Solution Explorer window displays information about the currently loaded solution. A solution is Visual Studio .NET terminology for one or more projects along with their configuration. The Solution Explorer window displays various views of the projects in a solution, such as what files they contain, and what is contained in those files. The Properties window allows a more detailed view of the of the contents of a project, allowing us to perform additional configuration of individual elements. For example, we can use this window to change the appearance of a button in a Windows form. The same window is also used to display dynamic help information. The Task List and Output window displays information when projects are compiled, along with tasks to be completed (in similar kind of display as is found in the task list in Microsoft Outlook). These tasks might be entered manually, or may be automatically generated by the Visual Studio.NET.

This may seem like a lot to take in, but dont worry, it doesnt take long to get used to.
Lets start building the first of our example projects, which will involve the use of many of the Visual Studio.NET elements described above.

All Rights Reserved To EaglesGroup

91

2.2 Console Applications


We will be using Console Application particularly to start off with, so lets step through the creation of a simple one.

Example Try it Out Creating a Simple Console Application Step by Step Example:
1. Create a new Console Application project by selecting the File | New | Project... menu item:

2. Select the Visual C# Projects folder from the Project Types: pane of the windows that appears, and Console Application projects type in the Templates: pane (youll have to scroll down a bit.) Change the Location: text box to C:\EaglesVisualCSharp\Chapter 2 (this directory will be created automatically if it doesnt exist), and leave the default text in the Name: text box as it is:

92

All Rights Reserved To EaglesGroup

3. Click the OK button. 4. Once the project is initialized, add the following line of code to the file displayed in the main window. using System; namespace ConsoleApplication1 { /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // You need to add the coding after this line // where ever you see the like TODO: start you coding after the green color line // the green color line are the comments //EaglesGroup //Siddhu //Sri jayesh Console.WriteLine ("Welcome to The EaglesGroup C# Programming!");

} } } 5. Select the Debug | Start without Debugging menu item or Press Ctrl + F5. After a few movements you should see the following:

All Rights Reserved To EaglesGroup

93

6. Press a key to exit the application.

Now Lets See how the program exactly works


For now, we wont dissect the code we have used in the project, as were more concerned with how to use Visual Studio.NET 2003 to get code up and running. As you can see, Visual Studio.NET 2003 does an awful lot for us and makes the process of compiling and executing code very simple. In fact, there are multiple ways of performing even these simple steps. For example, creating a new project can be achieved using the File | New | Project menu item as above, or by pressing Ctrl + shift + N, or by clicking on the corresponding icon in the toolbar. Similarly, our code can be compiled and executed in several ways. The process we used above, selecting the Debug | Start Without Debugging menu items, also has a keyboard shortcut (Ctrl + F5) and a toolbar icon. We can also run code in debug mode using the Debug | Start menu item (also possible by pressing F5 or clicking on corresponding toolbar icon, or compile our project without running it (with debugging on or off) using Build | Build, Ctrl + shift + B, or another toolbar icon. Once we have compiled our code, we can also execute it simply by running the .exe file produced in Windows Explorer, or form the command prompt. To do this, wed open a command prompt window, change the directory to C:\EaglesVisualCSharp\Chapter 2 \ConsoleApplication1\bin\Debug\,type ConsoleApplication1 and hit return. In future examples, Ill just say create a new console project or execute the code, and you can choose whichever method you wish to perform these steps. Unless otherwise stated, all code should be run with debugging enabled. One point to not here is that the Press any Key continue prompt that we say in the example only appears if you execute code without debugging. If we run our projects in debug mode, then the console window it runs in will close as soon as the code has executed. In general this is fine, but the last example it was helpful to have this prompt so that window didnt disappear as soon as it popped up, which would have made it difficult to see the results. Now weve created a project we can take a more detailed look at some of the regions of the development environment.

94

All Rights Reserved To EaglesGroup

2.3 The Solution Explorer


The first window to look at is the Solution Explorer / Class View window in the top right of the screen, shown below in both modes of operation (you can toggle between them by clicking on the tabs at the bottom of the window):

The Solution Explorer view shows the files that make up our ConsoleApplication1 project. This file we added code to, Class1.cs, is shown along another code file, AssemblyInfo.cs. (All C# code files have a .cs file extension.) This other code file isnt one we have worry about for the moment; it contains, which initially contains a default icon for use with our application (since we are using console application, however, this icon will not be used in the rendering of the start bar tab the default console application icon will be used instead). We can use the window to change what code is displayed in the main window by double clicking on files, right clicking on them and selecting View Code, or selecting them and clicking on the toolbar button that appears at the top of the window. We can also perform other operations on files here, such as renaming them or deleting them forms our project. Other types of files can appear here as well, such as project resources (resources are files used by the project that might not be C# files, such as bitmap images and sound files, as well as the icon file App1.ico). Again, we can manipulate them through the same interface. The References entry contains a list of the .NET libraries we are using in our project. Again, this is something well look at later, as the standard references are fine for us to get started with.

All Rights Reserved To EaglesGroup

95

The other view, Class View, presents an alternative view of our project by looking at the structure of the code we have created. Well come back to this later in the book, so for now the Solution Explorer display is our display of choice. As you click on files or other icons in these windows, you may notice that the contents of the window below changed. This is another window that has multiple views, but most important of these is the Properties view.

2.4 The Properties window

This window shows additional information about whatever we select in the window above it. For example, the above view is displayed when the Class1.cs file form our project is selected. This window will also display information about other things that might be selected, such as user interface components as we will see in the windows application of this chapter. Often, changes we make to entries in the Properties window will effect our code directly, adding lines of code or changing what we have in our files. With some projects, well spend as much time manipulating things through this window as making manual code changes. Next, lets take a look at the Output window. When we execute our example code you probably noticed that a section of text appeared here before the console window created by our application appeared. On my computer this appeared:

96

All Rights Reserved To EaglesGroup

------ Build started: Project: ConsoleApplication1, Configuration: Debug .NET -----Preparing resources... Updating references... Performing main compilation... Build complete -- 0 errors, 0 warnings Building satellite assemblies...

---------------------- Done ---------------------Build: 1 succeeded, 0 failed, 0 skipped As you can probably guess, this is showing us a status report as our files compiled. This is also where we will get reports of any errors that occur during compilation. As an example, try removing the semicolon from the line of code we added in the last section and recompiling. This time you should see: ------ Build started: Project: ConsoleApplication1, Configuration: Debug .NET -----Preparing resources... Updating references... Performing main compilation... c:\eaglesvisualcsharp\chapter 2\consoleapplication1\class1.cs (24, 68): error CS1002: ; expected Build complete -- 1 errors, 0 warnings Building satellite assemblies...

---------------------- Done ---------------------Build: 0 succeeded, 1 failed, 0 skipped

All Rights Reserved To EaglesGroup

97

This time the project wont run. DENOTE: In the next chapter, when we start looking at C# syntax, we will see how semicolons are excepted throughout our code at the end of most lines in actual fact. Since we have something to do now in order to get the code working, Visual Studio .NET 2003 automatically adds a task to the task list that shares with the Output window:

This window will help us eradicate bugs in our code, as it keeps track of what we have to do in order to compile projects. If we double click on the error shown here, the cursor will jump to the position of the error in our source code (the source file containing the error will be opened if it isnt already open), so we can fix it quickly. We will also see red wavy line at the positions of the errors in the code, so we can quickly scan source code to see where problem lie. Note that the error location was specified as a line number. By default line numbers arent displayed in the Visual Studio .NET 2003 text editor, but this something that is well worth turning on. To do this, we need to tick the relevant check box in the Options dialog, obtained through the Tools | Options... menu item. The check box is called Line Numbers, and is found in the Text Editor | C# | General category, as shown below:

98

All Rights Reserved To EaglesGroup

There are many useful options that can be found through this dialog, and we will use several of them throughout this book.

2.5 Windows Form Applications


It is often easier to demonstrate code by running it as part of a Windows application rather than through a console window or via a command prompt. We can do this using user interface building blocks to piece together a user interface. For now, well just see the basics of doing this and show you how to get a Windows Application up and running, through we will not go into too much details about what the application is actually doing. Later on in the book, we will take a detailed look at Windows Applications.

Example Try it out Simple Windows Application Step by Step Example:


1. Create a new project of type Windows Application in the same location as before (C:\EaglesVisualCSharp\Chapter 2) with the default name WindowsApplication1. If the first project still open, then make sure the Close Solution option is selected in order to start a new solution.

All Rights Reserved To EaglesGroup

99

2. Move the mouse pointer to the Toolbox on the left of the screen, then to the Button entry of the Windows Forms tab, and double click the left mouse button on the entry to add a button to the main form of the application (Form1):

3. Double click on the button that has been added to the form. 4. The C# code in the Form1.cs should now be displayed. Modify it as follows (only part of the code in the files show here for brevity): private void button1_Click(object sender, System.EventArgs e) { MessageBox.Show ("Welcome to EaglesGroup Programming Happy Programming!"); } 5. Run the Application. 6. Click the button presented to open a message dialog box:

100

All Rights Reserved To EaglesGroup

Now Lets See how the program exactly works


Again, it plain that Visual Studio .NET 2003 has done a lot of works for us, and made it simple to create functional Windows applications with little effort. The application we have created behaves just like other window we can move it around, resize it, minimize it, and so on. We dont have to write the code to do that it just works. The same goes for the button we added. Simply by double clicking on it, Visual Studio .NET knew that we wanted to write code to execute when a use clicked on the button in the running application. All we had to do was to provide that code, getting full button clicking functionality for free. Of course, Windows applications arent limited to plain forms with buttons. If you have a look at the toolbar where we found the Button option you will see a whole host of user interface building blocks, some of which may be familiar, and some not. Well get of these at some point in the book, and youll find that they are all just as easy to use, saving us a lot of time and effort. The code for our application in Form1.cs may look a fair bit more complicated that the code in the last section, but in actual face, the main reason it looks more complicated is that theres more of it. Much of the code in this file is concerned with the layout of controls on the form, which is why we can view the code in design view in the main window, which is a visual translation of this layout code. A button is an example of a control that we can use, as are the reset of the UI building blocks found in the Windows Forms section of the Toolbox bar. Lets take a closer look at the button as control example. Switch back to the Design View of the form using the tab on the main window, and click once on the buttons to select it. When we do this, the Properties window in the bottom right of the screen will show the properties of the button control (controls have properties much like the files we say in the last example). Scroll down to the Text property, which is currently set button1, and change the value to Click Me:

All Rights Reserved To EaglesGroup

101

The Text written on the button in Form1 should also change to reflect this.

There are many properties for this button, ranging from simple formatting of the color and size of the buttons to more obscure settings such as data binding settings, which allow links to database. As briefly mentioned in to later and upcoming chapters change in properties often results in direct change to code, and this no exception. Switch back to the code view of Form1.cs, and well take a little peek at the change we just made. At a cursory glance, you might not notice anything different in the code at all. This is because the section of C# code that deal with the layout and formatting of controls on a form are hidden form us (after all, we hardly need to look at the code if we have a graphical of the results).

102

All Rights Reserved To EaglesGroup

Visual Studio.NET uses a system of code outlining to achieve this subterfuge. We can see this in the following screenshot:

Looking down the left hand side of the code (just next to the line numbers if youve turned them on), you may notice some gray line and boxes with + and symbols in them. These boxes are used to expand and contract regions of code. Around the middle of the file (line 48 in mine, although this may vary) is a box with a + in it and a box in main boy do the code reading Windows Form Designer generated code. This label basically is saying here is some code generated by Visual Studio.NET that you dont need to know about. We can look at it if we want, however, and see what we have done by changing the button properties. Simply click on the box within the + in it and the code will become visible, and somewhere in there you should see the following line: // // button1 // this.button1.Location = new System.Drawing.Point(112, 112); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(104, 32); this.button1.TabIndex = 0; this.button1.Text = "Click ME"; this.button1.Click += new System.EventHandler(this.button1_Click);

All Rights Reserved To EaglesGroup

103

Without worrying too much about the syntax used here, we can see that the text we typed in to the Properties widow has popped up directly in our code. This outlining method can be very handy when we are witting code, as we can expand and contract many other regions, not just those that are normally hidden from us. Just as looking at the table of contents of a book can help us by giving us a quick summary of the contents, looking at a serious of collapsed regions of code can make it much easier for us to navigate through what can be vast amounts of C# code.

Summary
In this chapter, weve introduced some of the tools that well using thought the rest of the book. We have has quick tour around Visual Studio.NET development environment, and used it to build two types of applications. The simpler of these, the console application, is quite enough for most of our needs, and allows us to focus on basics of C# programming. Windows application is more complicated, but is visually more impressive and intuitive to use to anyone accustomed to a Windows environment (and lets face it, thats most of us). Now we know how we can create simple applications, we can get down to the real task of leaning C#. The next section of this book will deal with basic C# syntax and program structure, before we moving on to more advanced object oriented methods later. Once weve covered all that, we can start to look at how we use C# to gain access to the power available in the .NET Framework.

104

All Rights Reserved To EaglesGroup

Chapter 03

All Rights Reserved To EaglesGroup

105

Variables and Expressions

3.0 Introduction to Variables and Expressions


Perhaps the most fundamental description of a computer program is that it is a series of operation that manipulate data. This is true even at the most complicated examples such as vast, multi featured windows applications like the Microsoft Office Suite. Although this is after completely hidden from the user of applications it is always going on behind the scenes. To illustrate this further, consider the display unit of your computer. What you see on screen is often so familiar that it is difficult to imagine it as anything other than a moving picture. In actual fact, however what you see is only a representation of some data, which in the memory of your computer. Anything you do as shown, then, whether it is mouse painter, clicking on an icon, or typing text into a word processor will result in the shunting around of data in memory. Of course, there are less abstract situations that show this just as well. If you use a calculation application, you are supplying data in the form of numbers and performing operations on these numbers in much the same way as you would do with piece of paper and a pencil, although a lot quicker ha ha ha. If computer programs are fundamentally performing operations as data, then this implies that we need some way of storing that data, and some methods of manipulating it. These two functions are provided by variables and expressions respectively, and in this chapter we will learn it both in general and specific terms.

106

All Rights Reserved To EaglesGroup

3.1 Basic C# Syntax


The look and feel of C# code is similar to that of C++ and Java. At first this syntax can look alike confusing, and is a lot less like written English than some other languages. However, you will find as you immerse yourself in the world of C# programming that the style used is a sensible one, and it is possible to write very readable code without too much trouble. Unlike the compiles of some other language C# compiles take no notice of additional spacing in code, whether made up of spaces, carriage return, as tab characters. These characters are known collectively as white space characters. This means that we have a lot of freedom in the way that we format our code although confirming to certain rules can help to make things easier to read. C# code is made up of series of statements, each of which is terminated with a semicolon. Since white space is ignored therefore, we can have multiple statements on one line, but for readability sake it is usual to add carriage return statements after semicolons. So we dont have multiple statements on one line, but for readability sake it is usual to add carriage return statements after semicolons. So we dont have multiple statements on one line. It is perfectly acceptable and quite normal, however to use statements that span several lines of code. C# is a block structured language, meaning that all statements are part of a block of code. These blocks which are delimited with curly brackets ({ and }), may contain any number of statements, as none at all. Note that the curly bracket characters do not need accompanying semicolons. So, a simple block of C# code could take the following form. { <code line 1, statement 1>; <code line 2, statement 2> <code line 3, statement 3>; }

All Rights Reserved To EaglesGroup

107

Here the <code line x, statement y> sections are not actual pieces of C# code. Ive just used this text as a place holder for where C# statements would go. Note that in this case, the second and third lines of code are part of the same statement, as there is no semicolon after the second line. In this simple section of code, I have also used indentation to clarify the C# itself. This isnt some random invention of mine. It is standard practice and in fact vs will automatically do this for you by default. In general, each of code has its own level of indentation, meaning how far to the right it is. Blocks of code may be nested inside each other that are; blocks may contain other blocks, in which case nested blocks will be indented further: { <code line 1>; { <code line 2>; <code line 3>; } } <code line 4>;

Also, lines of code that are continuations of previous lines are usually intended further as well as in the third line of code in the first example above.

3.2 Comment
To make out comments using the first method, we use / * characters at the start of the comment and */ characters at the end. These may occur on a single line, in which case all lines in between are part of the comment. The only thing we cant type in the body of a comment is */, as this is interpreted as the end marker. So the following are Ok.

108

All Rights Reserved To EaglesGroup

/* This is a comment Siddhu */ /* And so .. Shamu launch C# to EaglesGroup . */ But the following will cause problems: /* Comments after end with */ Characters */

Here the end of the comment, the characters after * will be interpreted as C# code, and errors will occur. The other commenting approach involves starting a comment with //. Next we can write whatever we like as long we keep to on line!. The following is OK: // this is eagles Siddhu // Welcome to C#.net // Welcome to EaglesGroup

But the following will fail however, as the second line will be interpreted as C# code. // eagles Siddhu Welcomes you to C#.net

This sort of commenting is useful to document statements, as both can be placed on a single line: <A statement >; // Eagle Siddhu

There is a third type of comment in C# which allows you to document your code. They are single line comments that start with three / symbols instead of two like this. /// Welcome to Eagles group /// Welcome to Eagles Visual C#.NET

All Rights Reserved To EaglesGroup

109

Under normal circumstances, they are ignored by the compiler just like other comments, but you can configure vs to extract the text after these comments and create a specially formatted text file when a project is compiled, which we can then use to create documentation. Well look at this in detail. A very important point to note about C# code is that it is a case sensitive. Unlike some other languages, we must enter code using exactly the right case as simply using an upper case letter instead of a lower case one will prevent a project compiling.

3.3 Basic C# Console Application Structure


Lets work it out Using Console Application

Example 3-1.Using Simple Console Application

Example Try it out Eagles ConsoleApplication Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles Console Application in the directory C:\EaglesVisualCSharp\Chapter 3 Variables and Expressions\Example Using Console Application

110

All Rights Reserved To EaglesGroup

2. Now add the following code in the Program.cs as follows: namespace Eagles_Console_Application { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { static void Main(string[] args) { Console.WriteLine("Welcome to EaglesGroup Console Application in Eagles Visual C#.NET!"); } } } 3. Run the Application and you should have this output:

All Rights Reserved To EaglesGroup

111

We can immediately see that all the syntactic elements discussed in the last section are present here. We see semicolons, curly braces, and comments, along with appropriate indentation. The most important section of code as far as usre concerned at the moment is the following: static void Main(string[] args) { Console.WriteLine("Welcome to EaglesGroup Console Application in Eagles Visual C#.NET!"); }

This is the code that is executed when we run our console application, or to be more precise, the code block enclosed in curly braces is what is executed. The only line of code that will actually do anything here is the one we added to the automatically generated code, which is the only line in the code block that isnt a comment. This code simply outputs some text to the console window, though the exact mechanisms of this shouldnt concern us for now. For now we wont worry about the other code in the example, as the purpose of these first few chapter is to explain basic C# syntax, so that exact method of how the application execution gets to the point where Console.WriteLine() is called is not our concern. Later on the significance of this additional code will be made clear.

3.4Variables
As discussed in the introduction to this chapter, variables are concerned with the storage of data. Essentially, we can think of variables in computer memory as boxes sitting on a shelf. With boxes we can put things in and take them out again. Or we can just look inside a box to see if anything is there. The same goes for variables; we place data in them and can take it out or look at it, as required.

112

All Rights Reserved To EaglesGroup

Although all data in a computer is effectively the same thing a series of zero and ones, variables come in different flavors, known as types. Again using own box analogy we can imagine that our boxes come in different shapes and sizes and some things will only fit in certain boxes. The reasoning behind this type system is that different types of data may require different methods of manipulation and by restricting variables into individed type. We can avoid getting mixed up, it wouldnt for example, make such sense to treat the series of zeros and ones that make up a digital picture as an audio file. In order to use variables, we have to declare them. This means that we have to assign them a name and a type. Once we have declared variables we can use them as storage units for the type of data that we declared them to hold. The C# syntax for declaring variables simply involves specifying the type and variable name as follows : <type > <name> ;

If we try to use a variable that hasnt been declared, then our code wont compile, but in this case the compiler will tell us exactly what the problem was. So this isnt really a disaster error. In addition, trying to use a variable without assigning it a value will also cause an error, but again, the compiler will detect this. So, what is the type that we can use? Well, in actual fact there are an infinite number of types that we can use. The reason for this is that we can define our own types to hold whatever convoluted data use lime. Having said this, there are certain types of data that just about everyone will want to use at some point or another, such as a variable that stores a number, for example because of this there are a number of simple, pre-defined types that we should be aware of.

3.5 Simple Types


Simple types are those types such as numbers and Boolean (True or False) values that make us the fundamental building blocks for our application, and for other, more

All Rights Reserved To EaglesGroup

113

complex types. Most of the simple types available are numeric, which at first glance seems a bit strange surely we only need one type to store a number. The reason for the plethonce of numeric types is down to the mechanics of storing numbers as a series of zeros and ones in the memory of a computer. For integer values, we simply take a number of bits (individual digits that can be zero or one) and represents any number between 0 and (2n-1). Any number above this value will be too big to fit into this variable. As an early example, lets say we have variable that can store? Bits. The mapping between integers and the bit s representing those integers is therefore as follows: 0 = 00 1 = 01 2 = 10 3 = 11

If we want to be able to store more numbers, we need more bits. 3 bits will let us store the numbers from 0 to 7. For example, Instead, we have a number of different integers type that can be used to store various ranges of numbers, and take up different amounts of memory (up to 64 bits). The list of these is as follows: DENOTE: That each of these type make use of one of the standard type defined in the .net framework. As discussed in chapter 1, this use of standard type is what allows interoperability between languages. The names we use for this type in C# are allies for the defined in the framework.

114

All Rights Reserved To EaglesGroup

The table lists the names of these types are referred to in the .net framework library. Type byte sbyte short ushort int uint long Alies for system.byte system.sbyte system.int16 system.vint16 system.int32 system.vint32 system.int64 Allowed Values Integer between 0 and 255 Integer between -128 and 127 Integer between -32768 and 32767 Integer between 0 and 65535 Integer between -2147483648 and 214748347 Integer between 0 and 4294962795 Integer between -9223372036854775808 and 9223372036854775807 Integer between 0 and 18446744073709551615

ulong

system.vint64

The U s before some variables name are shorthand for unsigned meaning that we cant store negative numbers in variables of those types, as can been seen in the allowed values column of the table.

Type

Alias for

Minm

Max.

Mine

Max

Approx Min. Value 1.5X10-45 5.0X10324 1.0X10-28

Approx Max. Value 3.4X1038 1.7X10308 7.9X1028

Float Double

system.single system.double

0 0 0

224 253 296

- 149 - 1075 - 28

104 970 0

Decimal system.decimal

All Rights Reserved To EaglesGroup

115

In addition to numeric types there are three other simple types available. Type char Application system.char Allowed Values Single Unicode, character, stored as an integer between 0 and 65535. Boolean value, true or false A sequence of characters

bool string

system.boolean system.string

DENOTE: That there is no upper limit on the amount of characters making up a string as it can use varying amounts of memory. The Boolean type bool is one of the most commonly used variable types in C#, and indeed similar types are equally prolific in code in other languages. Having a variable that can be either true or false has important ramifications when it comes to the flow of logic in an application. As a simple example, consider how many questions there are, that can be answered with true or false as yes or no. Performing comparisons between variable values as validating input are just two of the programmatic uses of Boolean variables that will be examining very soon. Lets work it out Using Simple Type Variables

Example 3-2.Using Simple Type Variables

Example Try it out Eagles SimpleType Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles SimpleType in the directory C:\EaglesVisualCSharp\Chapter 3 Variables and Expressions\Example Using Simple Type Variables 2. Add the following in the Static void Main () method of the Program.cs as follows:

116

All Rights Reserved To EaglesGroup

namespace Eagles_SimpleType { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { static void Main(string[] args) { int myInteger; string myString; myInteger = 18; myString = "\" myInterger \" is"; Console.WriteLine("{0} {1}.", myString, myInteger); } } }

3. Run the Program and you will get the output like this:

All Rights Reserved To EaglesGroup

117

Now lets see how the above program works: The code we have added does three things. It declares two variables. It assigns values to those two variables. It outputs the value of the two variables to the console. Variable declaration occurs in the following code: int myinteger; string mystring; The first line declares a variable of type int with a name of myinteger, and the second line declares a variable at type string called mystring. DENOTE: That variable is restricted and we cant just use any sequence of characters will look at this in the section on naming variables below. The next two lines of code assign values: myinteger = 17; mystring = \ myinteger \ is;

118

All Rights Reserved To EaglesGroup

Here we assign two fixed values know as literal value in code to our variables using the = assignment operator. We assign the interfere value 18 to myInteger, and the string myInteger is including the quotes to enclose the string. Due to this, there are certain characters that may cause problems if they are included in the string itself, such as the double quote characters, and we must escape some characters by substituting a sequence of characters that represents the characters we want to use in the above example, we use the sequence \ to escape a double quote:

If we didnt use these escape sequence and tired coding this: myString = "" myInterger" is";

We would get a complier error: DENOTE: That assigning string literals is another situation where we must be careful with the line breaks the C# compiler will reject string literals that span more than one line. If we want to add a line break we can use the escape sequence for a carriage return in our string \, which is \n. For example, the following assignment: //myString = "This string has a\nline break.";

Would be displayed on two lines in the console view as follows: This string has a Line break

All escape sequence consit of the backslash symbol followed by one of a small set of characters well look at the full set a liter later. Because this symbol is used for this purpose there is also an escape sequence for the backslash symbol itself, which is simply two consecutive backslashes. \\. Getting back to the code, there is one more line that we havent looked at: Console.WriteLine("{0} {1}.", myString, myInteger);

All Rights Reserved To EaglesGroup

119

This looks similar to the simple method of writing out text to the console that we saw in our first example, but now we are specifying our variables. Now, we dont want to get ahead of ourselves here. The technique we will be using in the first part of this book to output to the console window. Within the brackets we have two things: A string A list of variables whose values we want to insert into the output string, separated by commas The string we are outputting {0} {1}. doesnt seem to contain much useful text. As you will have seen, however, this is not what you actually see when you run the code. The reason for this is that the string is actually a template into which we insert the contents of our variable. Each set of curly brackets in the string is a placeholder that we will contain the contents of each of the variables in the list. Each placeholder or format string is represented as an integer enclosed in curly brackets. The integers start at 0 and increment by 1, and the total number of placeholder should match the number of variables specified in the comma- separated list following the string. When the text is output to the console, each placeholder is replaced by the corresponding value for each variable. In this above example, the {0} is replaced with the actual value of the first variable, myString, and {1} is replaced with the contents of myInteger. This method of outputting text to the console is what we will use to display output from our code in the example that will follow:

3.6Variable Naming
As mentioned in the last section, we cant just choose any sequence of characters as a variable name. This isnt worrying as it might sound at first, however, as we are still left with a very flexible naming system.

120

All Rights Reserved To EaglesGroup

The basic variable naming rules are as follows: The first character of a variable name must be either a letter, an under score character (_) or @. Subsequent characters may be letters underscore characters or numbers. In addition, there are certain keywords that have a specialized meaning to the C# compiler, such as the using and namespace keywords we saw earlier. If you should use one of these by mistake, the compiler will complain and youll soon know youve done something wrong. So dont worry about this too much. For example the following variable names as fine: myBigVar VAR1 _test

These arent however 99Bottles of Beer namespace Its all over

And remember, C# is case sensitive, so we have to be careful not to target the exact casing used when we declare our variables. References to them made later in the program with even so much as a single letter in the wrong case will prevent compilation. A further consequence of this is the fact that we can have multiple variables whose names differ only in casing. For example the following are all separate names: myVariable MyVariable MYVARIABLE

All Rights Reserved To EaglesGroup

121

3.7 Naming Conventions


Variable names are something you will use a lot. Because of this, its worth spending a bit of time discussing the sort of names that you should use. Before we get started, though it is worth bearing in mind that this controversial ground. Over the years different systems have come and gone, and some develops will fight tooth and nail to justify their personal system. Up until recently the most popular system was what is known as Hungarian notation. This system involves placing a lower case prefix on all variable names that identifies the type. For example, if a variable was of type int then we must place an i (or n) in front of it. For example, iAge, using this system it is easy to see at a glance what type different variables are more modern languages. However, such as C# makes this system tricky to implement ok. So with the types weve seen so far we could probably come out with one or two letter prefix signifying each type. However, since we can create our own types and there are many hundreds of these more complex types in the basic .net framework, these quickly become unworkable with several people working on a project it can be easy for different people to come up with different and confusing prefixes with potentially disastrous consequences. Developers have now realized, that it is far better to name variable appropriately to their purpose. If any doubt arises it is easy enough to work out what the type of a variable is. In VS we just have to heave the mouse pointer over a variable name and a pop-up box will tell us what the type is soon enough. There are currently two naming conventions in use in the .net framework namespaces, known as pascalCase and camelCase. The casing used in the name is indicative of their usage. They both apply to names that are made up of multiple words, and specify that each word in a name should be in lower case except for its first letter, which should be upper case. In camel casing, there is an additional rule that the first word should start with a lower case letter.

122

All Rights Reserved To EaglesGroup

The following are camelCase variable name: age first Name time of Death

Then, the following are pascalCase: Age Last Name Winter of Discontent

For our simple variables we shall stick to camelCase, and use pascalCase for certain more advanced naming, which is the Microsoft recommendation. Finally, it is worth nothing that many part naming system involved frequent use of the underscore character, usually as separators between words of variable name, such as my-first-variable. This usage is now discouraged one thing i am eagle siddhu happy about is always though it looked ugly.

3.8 Literal Values


In the earlier example, we saw two examples of literal value, integer and string. The other variable types also have associated literal values as shown in the table below many of these involve suffixes. Where we add a sequence of characters to the end of the literal value in order to specify the type desired. Some literals have multiple types determined at compile time by the compiler based on their context.

Type(s) bool int, uint, ulong

Category Boolean long, Integer None None

Suffix

Example / Allowed Values True or False 100

All Rights Reserved To EaglesGroup

123

uint, ulong long, ulong ulong

Integer Integer Integer

u or V 1 or L

100 U 100 L

u1, uL, U1, UL, 100 UL 1U, 1u, or LU f or F d or D m or M None None 1.5 F 1.5 1.5 M a or escape sequence a a, mg include escape sequence

float double decimal char string

Real Real Real Character String

3.9 String Literals


Earlier on in this chapter, we a saw a few of the escape sequence that we can use in string literals. It is worth presenting a full table of these here for reference purpose. Escape Sequence \ \ \\ \0 \a \b \f \n Character Protected Unicode Value of Character

Single quote Double quote Back slash Null Alert cause a beep Back space Form feed New line

0 X 0027 0 X 0022 0 X 005C 0 X 0000 0 X 0007 0 X 0068 0 X 000C 0 X 000A

124

All Rights Reserved To EaglesGroup

\r \t \v

Carriage return Horizontal tab Vertical tab

0 X 000D 0 X 0009 0 X 000B

The Unicode value column of the above table shows the hexadecimal values of the character as they are found in the Unicode character set. As well as the above, we can specify any Unicode character using a Unicode escape sequence. This consists of the standard \ character followed by all and a four digit hexadecimal value. For example the four digits after X is the above table. This means that the following strings are equivalent: Siddhu\s string Siddhu \u0027s string

Obviously, we have more versatility using Unicode escape sequence. We can also specify strings verbatim. This means that all characters contained between two double quotes are included in the string, including end of line characters and characters that would otherwise need escaping. The only exception to this is the escape sequence for the double quote character, which must be specified in order to avoid ending the string. To do this, we place a @ character before the string. @ Verbatim string literal

This string could just as easily to be specified in the normal way, but the following requires this method: @ A short list item 1 item 2

All Rights Reserved To EaglesGroup

125

Verbatim string are particulary useful in filename, since these use plenty of backslash characters. Using normal strings we have to use double backslashes all the way along the string, for example: C:\\Eagles\\Siddhu\\eagles.doc

DENOTE: Remember that you will use this kind of command in ADO.NET section Verbatim string literals can make this more readable. The following verbatim string is equivalent to the above: @C:\Eagles\Siddhu\eagles.doc

DENOTE: That as well see later in this book string are reference types. Unlike the other types weve seen in this chapter which is value types. One consequence of this is that strings can also be assigned the value null, which means that the string doesnt reference a string. This will be explained in more detail later on this book.

3.10 Variable Declaration and Assignment


As a quick recap, recall that we declare variables simply using this type and name, for example: int age; When we assign values to variables using the = assignment operator age = 22

126

All Rights Reserved To EaglesGroup

Remember that variables must be initialized before we use them. The above assignment could be used as an initialization. There are a couple of other things we can do have that you are likely to see in C# code. The first, is declaring multiple variables of the same type at the same time, which we can do by separating this names with common after the type. For example int Xsize, Ysize;

Here Xsize and Ysize are both declared as integer types. The second technique you are likely to see is assigning value, to variables at the same time as declaring them, which basically means combining two limes of code: int age = 22;

We can use both these techniques together.

int Xsize = 4, Ysize = 5; Here both Xsize and ysize are assigned different values. Note that the following: int Xsize, Ysize = 5;

Will result in only ysize being initialized Xsize is just declared.

3.11 Expressions

All Rights Reserved To EaglesGroup

127

Now that weve seen how to declare and initialize variables, its time to look at manipulating them. C# contains a number of operators for this purpose, inducing the = assignment operators weve used already. By combining operators with variables and literal values together referred to as operand when used with operators, we can create expressions, which are the basic building blocks of computation. The operators available from range the simple to highly complex ones. Some of which you might never encounter outside of mathematical operators application. The simple ones include all the basic mathematical operations, such as the + operator to add two operands, and the complex ones include manipulations of variable content via the binary representation of this content. There are also logical operators specifying for dealing with Boolean values, and assignment operators like =. In this chapter, well concentrate on the mathematical and assignment operators leaving the logical ones to the next chapters. We will explain Boolean logic in the context of controlling program flow.

Operators can be roughly classified into 3 categories. They are as follows: Unary operators, which act as single operand. Binary operators, which act as two operands. Ternary operator, which act as three operands. Most operators fall into the binary category, with a few unary ones and a single ternary one called the conditional operators. The conditional operator is a logical one that is it returns a Boolean value, and well discuss it later.

3.12 Mathematical Operators


There are five simple mathematical operators, two of which have binary and unary forms. In the table below, Ive listed each of these operators along with a quick example of their use and results when used with simple numeric types integer and floating point.

128

All Rights Reserved To EaglesGroup

Operator Category + binary

Example Expression var1 = var2 + var3;

Result var1 is assigned the value that is the sum of var2 and var3 var1 is assigned the value that is the value of var3 subtracted from the value of var2 var1 is assigned the value that is the product of var2 by var3

binary

var1 = var2 - var3;

binary

var1 = var2 * var3;

binary

var1 = var2 / var3;

var1 is assigned the value that is the result of dividing var2 by var3

binary

var1 = var2 % var3;

var1 is assigned the value that is the remainder when var2 is divided by var3 var1 is assigned the value of var2 var1 is assigned the value of var2 multiplied by -1.

+ -

unary unary

var1 = + var2; var1 = - var2;

Ive shown examples using simple numeric types, since the result can be unclear when using the other simple type. What would you expect if you add two Boolean values together? For example, in this case nothing as the compiler will complain if you try to use + (or any of the mathematical operators) with bool variables. Adding char variables is also slightly confusing. Remember, char variables are actually stored as numbers, so adding two char variables together will also give you a number of type int, to be precise? This is an example of implicit conversion, and Ill have a lot more to say about this subject, and explicit conversion shortly, as it also applies to cases where var1, var2, and var3 are of. Having said all this, the binary + operator does make sense when used with string type variables. In this case, the table entry should read:

All Rights Reserved To EaglesGroup

129

Operator Category + binary

Example Expression var1 = var2 + var3;

Result var1 is assigned the value that is the concatenation of two strings stored in var2 and var3

The other two operators we should look at here are the increment and decrement operators, both of which are unary operators that can be used in two ways; either immediately before or immediately after the operand. Lets take a quick look at the results obtained in simple expressions and then discuss them. Operator Category ++ -++ -unary Example Expression var1 = ++ var2; Result Var1 is assigned the value of Var2 +1. Var2 is incremented by 1. Var1 is assigned the value of Var2. Var2 is decremented by 1. Var1 is assigned the value of Var2. Var2 is incremented by 1. Var1 is assigned the value of Var2. Var2 is decremented by 1.

unary

var1 = -- var2;

unary

var1 = var2 ++;

unary

var1 = var2 --;

The key factor here is that these operators always result in a change to the value stored in their operand. ++ Always results its operand being incremented by one. -- Always results in its operand being decremented by one. The differences between the results stored in var1 are a consequence of the fact that the placement of the operation determines when it takes effect. Placing one of these operators before its operand means that the operand is affected before any other computation takes place. Placing it after the operand means that the operand is affected after all other computation of the expression is completed.

130

All Rights Reserved To EaglesGroup

This merits another example. Consider this code: int var1, var2 = 5; var3 = 6; var1 = var2 ++ * var3; Lets work it out Using Mathematical Operators

Example 3-3.Using Mathematical Operators

Example Try it out Eagles MathematicalOperators Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles MathematicalOperator in the directory C:\EaglesVisualCSharp\Chapter 3 Variables and Expressions\Example Using Mathematical Operators 2. Add the Following code into the Program.cs as follows:

All Rights Reserved To EaglesGroup

131

namespace Eagles_MathematicalOperator { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// ALl Rights Reserved to EaglesGroup /// </Eagles> # endregion class Program { static void Main(string[] args) { double firstNumber, secondNumber; string userName; Console.WriteLine("Please Enter You'r Name:"); userName = Console.ReadLine(); Console.WriteLine("\n"); Console.WriteLine("Welcome {0} !", userName); // it will display the inputed name Console.WriteLine("Enter an a Number:"); Console.WriteLine("\n"); firstNumber = Convert.ToDouble(Console.ReadLine ()); Console.WriteLine("\n"); Console.WriteLine ("Enter an second number:"); Console.WriteLine("\n"); secondNumber = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("\t\n" + "******" + "Welcome!" + userName + "***************"); Console.WriteLine ("\n"); Console.WriteLine("The sum of the {0} and {1} is {2}. ", firstNumber, secondNumber, firstNumber + secondNumber); Console.WriteLine("\n"); Console.WriteLine("The Result of Subracting {0} and {1} is {2}, ", firstNumber, secondNumber, firstNumber - secondNumber); Console.WriteLine("\n"); Console.WriteLine("The Product of {0} and {1} is {2} . ", firstNumber, secondNumber, firstNumber * secondNumber); Console.WriteLine("\n"); Console.WriteLine ("The Reminder of {0} and {1} is {2} . ", firstNumber, secondNumber,firstNumber / secondNumber ); }

132

All Rights Reserved To EaglesGroup

3. Now Execute the program.cs and you will have the output like this:

4. Now Enter Your name and Press Enter button:

5. Enter an number and the again press the Enter button:

All Rights Reserved To EaglesGroup

133

6. Enter the second number and you will the see something like this:

Now lets see how the above code works: As well as demonstrating the mathematical operators, this code introduces two important concepts, which we will come across many times in our worked example; User Input Type Conversion User input uses a similar syntax to the Console.WriteLine () command weve already seen. We use Console.Readline (). This command prompts the user for input, which is stored in a string variable.

134

All Rights Reserved To EaglesGroup

string userName; Console.WriteLine("Please Enter You'r Name:"); userName = Console.ReadLine(); Console.WriteLine("\n"); Console.WriteLine("Welcome {0} !", userName); // it will display the inputed name

3.13 Assignment Operators


Up till now weve been using the simple = assignment operator, and it may come as a surprise that any other assignment operators exist at all, there are more, however, and the biggest surprise is probably that theyve quite useful. The entire assignment operator other than = work in a similar way. As with = they all result in a value being assigned to the variable on their left hand side based on the operands and operators on their right hand side. As we did before, lets look at the operators and their explanations in tabulated form. Operator Category = += -= binary binary Example Expression var1 = var2; var1 += var2; Result var1 is assigned the value of var2 var1 is assigned the value that is the sum of var1 and var2 var1 is assigned the value that is the value of var2 subtracted from the value of var1 *= /= %= binary var1 *= var2; var1 is assigned the value that is the value of multiplying var1 by var2 binary var1 /= var2; var1 is assigned the value that is the value of dividing var1 by var2 var1 is assigned the value that is the remainder when var1 is divided by var2

binary

var1 -= var2;

binary

var1 %= var2;

All Rights Reserved To EaglesGroup

135

As you can see, the additional operators result in var1 being included in the calculation so, code like: var1 += var2; Gives exactly the same result as: var1 = var1 + var2;

DENOTE: That the += operator can also be used with strings, just like +. Using these operators, especially when employing long variable names, can make code much easier to read.

3.14 Operator Precedence


When an expression is evaluated each operator is processed in sequence. However, this doesnt necessarily mean evaluating these operators from left to right. As a trivial example, consider the following:

var1 = var2 + var3;

Here, the + operator acts before the = operator. There are other situations where operator precedence isnt so obvious, for example:

var1 = var2 + var3 * var4;

136

All Rights Reserved To EaglesGroup

Here the * operator acts first, followed by the + operator, and finally the = operator. This is the standard mathematical order of doing things, and gives the same result as you would expect from working out the equivalence algebraic calculation on paper. Like such calculations, we can gain control over operator precedence by using parentheses, for example: var1 = (var2 + var3) * var4;

Here, the content of the parentheses is evaluated first, meaning that the + operator acts before the * operator. Of the operators we have encountered so for the order of precedence is as follows: when operators of equal precedence (such as * and /) are evaluated in a left to right manner.

Precedence Highest

Operators ++, -- (used as prefixes), +, - (Unary) *, /, % +, =, *=, /=, %=, +=, -=

Lowest

++, -- (used as suffixes)

DENOTE: that parentheses can be used to over do this precedence order as described above.

All Rights Reserved To EaglesGroup

137

3.15 Namespaces
Before we move, on, its worth spending some time on one more important subject namespace. These are the .Net way of providing containers for application code, such that code and its contents may be uniquely identified. Namespace are also used as a means of categorizing items in the .Net framework. Most of these items are type definitions such as the simple types detailed in this chapter (system Int32 and so on). C# code, by default, is contained in the global namespace. This means that items contained in this code are accessible from other code in the global namespace. Simply by referring to them by name, we can use the namespace keyword, however, to explicitly define the namespace for a block of code enclosed in curly brackets. Names in such a namespace must be qualified if they are to be used from code outside of this namespace. A qualified name is one that contains all of its hierarchical information. In basic terms, this means that if we have code in one namespace that needs to use a name defined in a different namespace, we must include a reference to this namespace. Qualified names use period character (.) between namespace levels. For example : namespace levelone { // code in level one namespace // name nameone defined } // code in global namespace

This code defines one namespace levelone, and a name in this namespace. Nameone note that I havent shown any actual code here in order to keep the discussion general; instead Ive placed a comment where this definition would go. Code written inside the levelone namespace can simply refer to this name using nameone. No classification is necessary. Code in the global namespace, however, must refer to this name using the classified name levelone.nameone.

138

All Rights Reserved To EaglesGroup

Within a namespace, we can define nested namespaces, also using the namespace keyword. Nested namespaces are referred to via this hierarchy, again using periods to classify each level of the hierarchy. This is best illustrated with an example. Consider the following namespaces: namespace levelone { // code in levelone namespace namespace leveltwo { // code in levelone.leveltwo namespace namespace leveltwo { // code in levelone.leveltwo namespace // name nametwo defined } } // code in global namespace

Here, nametwo must be referred to as levelone.leveltwo. Nametwo the global namespace, leveltwo.nametwo levelone namespace, and nametwo from the levelone.leveltwo namespace. The important point to note here is that names uniquely defined by this namespace. We could define the name namethree in the levelone and leveltwo namespaces. namespace levelone { // name namethree defined namespace leveltwo { // name namethree defined } }

All Rights Reserved To EaglesGroup

139

This define two separate names levelone.namethree and levelone.leveltwo.namethree, that can be used independently of each other. Once namespace we setup, we can use the using statement to simplify access to the names they contain. In effect, the using statement says OK, we need names from this namespace. So dont bother asking me to classify them every time. For example, in the following code we are saying that code in the levelone namespace should have access to names in the levelone.leveltwo.namespace without classification. namespace levelone { using leveltwo; namespace leveltwo { // name nametwo defined }

Code in the levelone namespace can now refer to leveltwo.nametwo by simply using nametwo.

140

All Rights Reserved To EaglesGroup

Summary:
In this chapter, weve covered a fair amount of ground on the way to create usable if basic C# applications. Weve looked at the basic C# syntax and analyzed the basic console application code that VS generated for us when we create a console application project. The major part of this chapter concerned the use of variables. We have seen what variables are, how we create them, how we assign values in them, and how we assign values in them, and how we assign values in them, and how we manipulate them and the values that they contain. Along the way, weve also looked at some basic user interaction, by showing how we can output text to a console application and read user input back in. We have also seen how we can assemble operators and operands into expressions, and looked at the way these are executed, and the order in which this takes place. Finally, we looked at namespace, which will become more and more important on the book progress. By introducing this topic in a fairly abstract way here, the ground work is completed for later discussions. So far all of our programming has taken the form of line-by-line execution. In the next chapter see how we can make out code more efficient by controlling the flow of execution using looping techniques and conditional branching. So we covered the following topics: 3.0Introduction to Variables and Expressions 3.1 Basic C# Syntax 3.2 Comment 3.3 Basic C# Console Application Structure 3.4Variables 3.5 Simple Types 3.6Variable Naming 3.7 Naming Conventions 3.8 Literal Values 3.9 String Literals 3.10 Variable Declaration and Assignment 3.11 Expressions 3.12 Mathematical Operators 3.13 Assignment Operators 3.14 Operator Precedence 3.15 Namespaces

All Rights Reserved To EaglesGroup

141

Chapter 04

142

All Rights Reserved To EaglesGroup

Flow control
4.0 Introduction to Flow control
All of the C# Code weve seen so for has had one thing in common. In each case, program execution has proceeded from one line to the next in top to bottom order, missing nothing. If all applications worked like this then we would be very limited in what we could do. The syntax of a language works in the first step toward understanding how the language is best incorporated into your application development environment. The next step in learning how the system works is to understand the tools built into the language that you could use to develop your application. These tools take from of programming concepts that all languages support, such as controlling flow, naming, interfacing to other systems, and extending the language. Nearly all modern programming languages can do all these things. C# is certainly no exception to this rule. In this chapter, well examine all the built in components that make the language successful. Well also explore the special extensions of the language that make specific programming problems easier to solve. Determining which way a program executes based on certain criteria is called flow control. It has five different areas they are as follows: Selection Iteration Conditional Logic. Branching Looping

4.1 Selection
Selection allows you to take a variety of paths based on a given input value. For section handling, the main method C# allows is the switch statement, whose general form is shown as follows: switch (expression) { case value: statement break; case other value: break; default: }

All Rights Reserved To EaglesGroup

143

Any programmer familiar with either C++ or Java should recognize this syntax. The difference in case of C# lie in the types of variables you an use in the expression statement, the way in which you break out of case, and the way in which you jump from one case to another. In C++ or Java, the switch statement can be used with integer or Boolean values. You may elect to test a value using the switch statement for virtually any data types, but the result must be an integer result. In C#, this restriction is not valid. You may elect to have string variables in the switch statement or use enumerated values. The one thing you cannot put in a switch statement is an object that does not equate to an integral value. Lets work it out Using the Switch Statement

Example 4-1 Using the Switch Statement

Example Try it out Eagles SwithcStatement Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles SwithcStatement in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the Switch Statement 2. Add the following code in the program.cs as follows: amespace Eagles_SwithcStatement { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program {

144

All Rights Reserved To EaglesGroup

public static void MakeADecision(string s) { switch (s) { case "Hello": System.Console.WriteLine("Hello yourself!"); break; case "Goodbye": System.Console.WriteLine("Goodbye!!"); break; default: System.Console.WriteLine("Huh?"); break; } } public static void MakeANumericDecision(string s) { int nVar = 0; if (s == "Hello") nVar = 1; if (s == "Goodbye") nVar = 2; if (s[0] == '#') { string temp = ""; for (int i = 1; i < s.Length; ++i) temp += s[i]; nVar = Convert.ToInt16(temp); } switch (nVar) { case 0: goto default; case 1: case 2: MakeADecision(s); break; default: System.Console.WriteLine("Number {0}", nVar); break; } }

3. Add the following code in the Static Void Main() as follows:

All Rights Reserved To EaglesGroup

145

static void Main(string[] args) { if (args.Length > 0) MakeADecision(args[0]); MakeANumericDecision("#0"); MakeANumericDecision("#1"); MakeANumericDecision("#2"); MakeANumericDecision("#3"); } 4. Now run the application and you should have the output something like this:

Now lets see how the above code works: As you can see from the below code switch (nVar) { case 0: goto default; case 1: case 2: MakeADecision(s); break; default: System.Console.WriteLine("Number {0}", nVar); break; }

146

All Rights Reserved To EaglesGroup

Switch statement allows you to jump around to different labels withing the switch. These statement s can also have muiliple labels that handle a single case. One interesting different between C++ and C# is that you can do the following: switch (x) { case 0 : Console.WriteLine(case 0); case 1: Console.WriteLine(case 1); }

4.2Iteration
Iteration, one of the most powerful forms of programming flow control, means repeating and repeating in a programming language means some from of loop construct. C# provides several different forms of loop constructs, including a new one, the foreach statement. Lets take a look at each from of loop construct, examines the reasons for its existence and the possible limitations of using it. The first loop construct is the for loop. The for loop in C# is closely related to for loops in C++ and Java; they permit you to initialize, text, and increment a variable within a single block. For loops were invented because the designers of the C programming language noticed a common them among programmers. When the designers of C# came along, they recognized the utility of the for loop and continued its existence in a way that was virtually unchanged from its C++ or Java cousins. Haha. The basic form from of for loop is follows: for (initial value statement; test statement ; increment statement ) Statement or bloc;

The major difference between the for loops in C++ and those in C# lies in the scope these loops have in these languages. In the original version of C++ and the one that Visual C++ still adhere to, the scope of the variables defined in a for loop went until it hit, the end of the block that contained the for loop; in other words: For (int I = 0; I < 10; ++I) Console.WriteLine (I = {0}, ,) // but the I is still valid here

All Rights Reserved To EaglesGroup

147

In C# however, the for loop index counter would go out of scope immediately following the end of the for loop so that when the for loop is terminated by hitting one of its termination values, the variables would no longer be Valid.

4.3Conditional Logic
One of the most necessary aspects of the programming world is the ability to choose among different options in source code. The way this choice is usually accomplished is via an if statement. An if statement permities you to compare, contrast, or otherwise differentiate between two different choice after the comparison has been made, an if statement allows you to take the path that makes the most sense to you, giving the values of certain variables. C# allows you to use two different forms of if statement. First, it permits any variation of the standard if then else logic block. Secondly, it implements the C++ conditions also called the ternary operator. Both these constructs allow you to make choices based on variables types. As with the loop constructs, C# require that the content of an if statement be only a Boolean Type. In other word, you can do the following? If (I != 0) {}

But you cannot do as follows: If (I) {}

4.4Branching
Where we execute code conditionally, depending on the outcome of an evaluation, such as only execute this code if my value is less that 10

4.5Looping
Looping is repeatedly executing the same statements for a certain number of times or until a test condition has been reached. Both of these techniques involve the use of Boolean logic. In the last chapter we saw the boll type, but didnt actually do much with it. In this chapter will be using it a lot and so we will start by discussing what we mean by Boolean logic so that we can use it in flow control Scenarios.

4.6Boolean Logic
The bool type introduced in the last chapter can hold one of only two values, true or false. This type is often used to record the result of some operation, such that we can act on this result. In particular, boll types are used to store the result of a comparison.
All Rights Reserved To EaglesGroup

148

DENOTE: As an historical aside, it is worth remembering and respecting the English mathematician George Boole, whose work in the mid nineteenth century forms the basis of Boolean logic. As an example, consider the situation (as mentioned in the introduction to this chapter) that we want to execute Code based on whether a variable, myVal, is less that 10. In order to do this we need some indication of whether the statement myVal is less than 10 is true or false, that is. We need to know the Boolean result of a comparison. Boolean comparisons require the use of Boolean comparison operators (also know as relational operators) which are shown in the table below. In all cases here var. l is 9 bool type variable, while the types of var. 2 and var. 3 my value.

Operator == != > = >=

Category binary binary binary binary binary binary

Example Expression Var.1 = var.2 = var.3 Var.1= var.2 ! = var.3 Var.1= var.2 = var.3 Var.1= var.2 > = var.3 Var.1= var.2 = = var.3 Var.1= var.2 > = = var.3

Result for the above Example Expression Var.1 is assigned the value true if var.2 is equal to var.3 or false otherwise Var. 1 is assigned the value true if var.2 is not equal to var.3 or false otherwise. Var. 1 is assigned the value true if var.2 is less than var.3 or false otherwise. Var. 1 is assigned the value true if var.2 is greater than var.3 or false otherwise.

All Rights Reserved To EaglesGroup

149

Var. 1 is assigned the value true if var.2 is less than or equal to var.3 or false otherwise. Var. 1 is assigned the value true if var.2 is greater than or equal to var.3 or false otherwise. We might use operators such as these on numeric values in code such as: bool isLessThan 10 ; islessThan 10 = myVal. < 10;

This code will result is LessThan10 being assigned the value true if my val.1 stores a value less than 10, or false otherwise. We can also use these comparison operators on other types, such as string: bool isSiddhu ; isSiddhu = myString == Siddhu,

Here isSiddhu will only be true if myString stores the string Siddhu We can also focus on Boolean Values:bool isTrue ; isTrue = my Bool == true ; Although here we are limited to use if == and! = operators. DENOTE: That a common code error occurs if you unintentionally assume that because Val1 Val 2 is false, then Val1 > Val 2 is true. If Val 1 == Val.2 than both these statements will be false. Im mentioning this here as its a mistake, Ive mad in the past!

150

All Rights Reserved To EaglesGroup

There are some other Boolean operators that are intended specifically for working with Boolean values:Operator ! $ Category binary binary binary binary Example Expression Var.1 = ! var.2 Var.1= var.2 $ = var.3 Var.1= var.2 1 = var.3 Var.1= var.2 = var.3

Result for the above Example Expression Var1 is assigned the value true if Var2 is false or false if Var2 is true. (Logical Not) Var1 is assigned the value true if Var2 and Value are both true and false otherwise. (Logical AND) Var1 is assigned the value true if either Var2 or Var3 (or both) are true or false otherwise. (Logical OR) Var1 is assigned true if either Var2 or Var3, but not both, are true, or false otherwise. (Logical XOR, on exclusive OR)

All Rights Reserved To EaglesGroup

151

So the last code snippet above could also be expressed as:bool isTrue ; isTrue = my bool $ true ;

The & and | operators also have two similar operators:-

Operator

Category

Example Expression

Result

$$

binary

Var1 =! Var.2 $$ var.3;

||

binary

Var1= Var.2 || = var.3

Var1 is assigned the value true if var.2 and var.3 are both true, or false otherwise (Logical AND) Var1 is assigned the value true if either Var2 are Var3 (on both) are true, or false otherwise (Logical OR)

The result of these operators is exactly the same as & and |, but there is an important difference in the way this result is obtained, which can result in better performance. Both at these look at the value of their first operand Var2 in the table above, and based on the value of this operand may not need to process the second operator Var3 above at all. If the value of the first open and of the && operator is false then there is no need to consider the value of the second open and, as the result will be false regardless. Similarly, the || operator will return true if its first open and is true, regardless of the value of the second operator. This isnt the case for the & and | operator. We saw above with these, both operands will always be evaluated. Because of this conditional evaluation of operands we will see a small performance increase if we use && and |. This will be particularly apparent in application that uses these operators a lot. As a rule of thumb, always use && and || where possible.

152

All Rights Reserved To EaglesGroup

4.7 Bitwise operators


In the light of the discussion in the last section, you may be asking why the & and | operators exist at all. The reason is that these operators may be used to perform operations on numeric values. In fact, they operate and the series of bits stored in a variable rather than the value of the variable. Lets consider these in turn, starting with &. Each bit in the First operand is compared with the bit in the same position in the second operand, resulting in the bit in the same position in the resultant value being assigned a value as follows: Operand 1 bit 1 1 Operand 2 bit 1 0 1 0 $ Result bit 1 0 0 0

0 0

| is similar, but the result bits are different, as follows: Operand 1 bit 1 1 Operand 2 bit 1 0 1 0 | Result bit 1 1 1 0

0 0

All Rights Reserved To EaglesGroup

153

For example, consider the operation shown in the following code int result, op1, op2 op1 = 4; op2 = 5; result = op1 & op2 ; Here we must consider the binary representations of op1 and op2; which are 100. And 101 respectively. The results are obtained by comparing the binary digits in equivalent positions in these two representations as follows: The left most bit of result is | if the left most bit of op1 and op2 are both | as 0 otherwise. The next bit of result is 1 if the next bit of op1 and op2 Continue for all remaining bits.
are

both 1 as 0 otherwise.

In the example the leftmost bits of op1 and op2 are both |, so the left most bit of result will be |, too. The next bits are both 0, and the third bits are | and 0 respectively. So the second and third bits of result will be O. The final value of result in binary representation is therefore 100, so result is assigned the value 4. The following illustrate this: 1 & 1 1 0 0 0 0 1 0 & 4 5 4

The same process occurs if we use the | operator except that in this case each result bit is 1 if either of the operand bits in the same position is 1 1 | 1 1 0 0 0 0 1 1 | 4 5 5

154

All Rights Reserved To EaglesGroup

We can also use the operator in the same way, where each result bit is 1 one or other of the operand bits in the same. Position is one, but not both: Operand 1 bit 1 1 Operand 2 bit 1 0 1 0 ^Result bit 1 1 1 0

0 0

C# also allows the use of a unary bitwise operator , which acts on its operand by inverting each of its bits, such that the result is a variable having values of 1 for each bit in the operand that is 0, and vice versa ; Operand 1 bit 1 0 ~ Result bit 0 1

These bitwise operations are quite useful in certain situations; as they allow a simple method of making use of individual variable bits to stare information consider a simple representation of a color using three bits to specify red, green and blue content. We can set these bits independently to change the three bits to one of the following configurations.

All Rights Reserved To EaglesGroup

155

Bits 000 100 010

Decimal Representation 0 4 2

Meaning Black Red Green

Lets say we store these values in a variable of style int. Starting from a black color, that is an int. variable with the value of 0, we can perform operation like: int. my color = 0; bool contains Red ; my color = my color |2 ; || Add green bit, my color now my color = my color |4 ; || Add red bit, my color now contains Red = (my color $4) ==4; || check value of red bit The final line of code assigns a value of true to contains Red, as the red bit of my color is 1. This technique can be quite useful for making efficient use of information, particularly as the operations induced can be used to check the values of multiple bits simultaneously 32 in the case at int. value. However, they are better ways to storing extra information in single variables. In addition to these four bitwise operators there are two others that Id like to look at in this section. These are as follows: Operator Category binary Example Expression Var.1= var.2 var.3 Var.1= var.2 var.3

binary

156

All Rights Reserved To EaglesGroup

Result for the above Example Expression Var1 is assigned the value obtained when the binary content of Var2 is shifted Var3 bits to the rights Val1 is assigned the value obtained when the binary content of Var2 is shifted Var3 bits to the left. This operator commonly called bitwise shift operands are best illustrated with a quick example: int. var.1, var.2 = 10, var.3 =2 ; var.1 = var.2 var.3 ;

Here, var.1 is assigned the values 40. This can be explained by considering that the binary representation of 10 is 1010, which shifted to the left by two places is 101000, binary representation of 40. In effect what we have done is carried out a multiplication operation. Each bit shifted to the left multiplies the value by 2, so two bit shifts to the left results in multiplication by 4. Conversely each bit shifted to the right has the effect of dividing the operands by 2 with any integer remainder bring lost: int. Var1, Var2 = 10; Var1 = Var2 1;

In this example, Var1 contains the value 5, whereas the following code gives a value of 2; int. Var1, Var2 = 10; Var1 = Var2 2;

You are unlikely to use these operators in most code, but it is worth being aware of their existence. Their primary use is in highly optimized code, where the overhead of other mathematical operations just wont do. For this reason they are often used in, for example, device drives or system code.

All Rights Reserved To EaglesGroup

157

4.8Boolean Assignment operators


The last operators to look at in this section are those that combine some of the operators weve seen above with assignment, much like the mathematical assignment operators in the last chapter (+ =, * = etc.,). These are as follows:

Operator & |

Category binary binary binary

Example Expression Var.1&= var.2 ; Var.1|= var.2 ; Var.1= var.2 ;

Result for the above Example Expression Var1 is assigned the value that is the result of Var1 &ofVar2. Var1 is assigned the value that is the result of Var1|of Var2 Var1 is assigned the value that is the result of Var1 of Var.2

These work with both Boolean and numeric values in the same way as &, |, and. DENOTE: That & = and | = use & and |, not && and ||, and get the overhead associated with these simples operators. The bitwise shift operators also have assignment operator as follows:

Operator

Category

Example Expression

Result Var1 is assigned the value obtained when the binary content at Var1 is shifted Var2 bits to the right.

binary

Var1= Var2 ;

158

All Rights Reserved To EaglesGroup

==

binary

Var1= Var2 ;

Var1 is assigned the value obtained when the binary content at Var1 is shifted Var2 bits to the left.

Lets work it out Using the Boolean and Bitwise Operators

Example 4-2 Using the Boolean and Bitwise Operators

Example Try it out Eagles BooleanOperators Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles BooleanOperators in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the Boolean and Bitwise Operators 2. Add the following code in the Program.cs as follows: namespace Eagles_BooleanOperators { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { static void Main(string[] args) { Console.WriteLine("Enter an Interger:"); int myInt = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Interger less then 10? {0}", myInt < 10); Console.WriteLine("Integer between 0 and 5 ? {0}", (0 <= myInt) && (myInt <= 5)); Console.WriteLine("Bitwise AND of Integer and 10 = {0} ", myInt & 10); } }

All Rights Reserved To EaglesGroup

159

3. Now run the application and enter an integer when it is promoted.

Now lets see how the above code works: The first two lines of code prompt have and accept an integer value using techniques weve already seen: console.WriteLine("Enter an Interger:"); int myInt = Convert.ToInt32(Console.ReadLine());

We use convert To Int 32( ) to obtain an integer from the string input, which is simply another conversion command in the same family as the convert, To Double ( ) command we used previously. The remaining three lines of code perform various operations on the number obtained and display results, will work through this code assuming that the user enters 9, as shown in the program execution.

4.9Operator precedence updated


Now we have a few more operators to consider we should update our operator procedure table from the last chapter to include them.

160

All Rights Reserved To EaglesGroup

Precedence

Operators + +, - - (used as prefixes); ( ), +, -, (unary) !,^ *, /,

Highest

+, , , , =, =

& | Lowest && || =, *=, /=, =, + =, - =, =, =, &=, =, | = ++, - - (Used as suffixes)

All Rights Reserved To EaglesGroup

161

This adds quite a few more levels, but explicitly defines how expressions such as the following will be evaluated. Var1 = Var2 = 4 & & Var2 = 2; Where the && operator is processed after the = and = operators. One point to note here is that it doesnt hurt to add parentheses to make expression such as this one clearer. The compiles knows what order to process operators in, but we humans are prove to forget such things and we might want to change the order. writing the above expression as : Var1 = (Var12 = 4) & & (Var2 = 2) ; Solves this problem by being explicit about the order computation.

4.10The goto statement


C# allows us to label lines of code and then jump straights to them using the go to statement. This has its benefits and problems. The main benefit is that it is a very simple way of controlling what code is executed when. The main problem is that excessive use of this technique can result in difficult to understand eagles " code Now lets look at how we use this technique to clarify this The goto statement is used as follows: goto labelName;

And labels are defined in the following way: labelName;

For example, consider the following: int myInteger = 5; goto myLabel ; my Integer + = 10; myLabel ; Console.WriteLine (myInteger = {0}, myInteger);

162

All Rights Reserved To EaglesGroup

Execution proceeds as follows: my Integer is declared as an int type and assigned the value 5 The go to statement interrupts normal execution and transfers control to the line marked myLabel: The value of my Integer is written to the console The line of code highlighted below is never executed; int myInteger = 5 ; go to myLabel ; myInteger + = 10; myLabel : Console.WriteLine(myInteger = {0}, myInteger);

In fact, if you try this out in an application you will see that this is noted in the task list as a warning when you try to compile the code, labeled unreachable code detected along with a line number. goto statement have their uses, but they can make things very confusing indeed. As an example of some eagles code arising from the use of go to, consider the following start : int myInteger = 5; goto addVal; writeResult ; Console.WriteLine (my Integer = {0}, my Integer); goto start ; addVal: myInteger + = 10; goto writeResult ;

This is perfectly valid cod, but very difficult to read! You might like to try this out for yourself and see what happens. Being doing that, thoughts, try and work out what this code will do by looking at it, so you can give yourself part on the back if youre right.

All Rights Reserved To EaglesGroup

163

4.11Branching
Branching is the act of controlling which line of code should be executed next. The one to jump to is controlled by some kind of conditional statement. This conditional statement will be based on a comparison between a test value and one as more possible value using Boolean logic. In this section we will look at the three branching technique available in C#: The ternary operator The if statement The switch statement.

4.12The ternary operator


The simplest way of performing a comparison is to use the ternary or conditional operator mentioned in the last chapter. Twelve already seen ternary operators that work on one operand, and binary operators that work on two operands, so it may come as no surprise that this operator works on three operands. The syntax is as follows: test? resultIfTrue : resultIffalse

Here, test is evaluated to obtain a Boolean value, and the result of the operator is either resultIfTrue or resultIfFalse based on this value We might use this as follows: String result string = (my Integer 10)? Less than 10 :Greater than or equal to 10; Here the result of the ternary operator is one of two strings, both of which may be assigned to result string. The choice of which string to assign is made by comparing the value of my Integer to 10, where a value of less than 10 result in the first string being assigned, and a value of greater than or equal to 10th second string.

For example, if my integer is 4 then result string will be assigned the string Less than 10.

164

All Rights Reserved To EaglesGroup

This operator is fine for simple assignment such as this, but isnt really suitable for executing larger amounts of code based on a comparison. A much better way of doing this is to use the if statement.

4.13The if statement
The if statement is a far more versatile and useful way of making decisions. Unlike? Statements, if conditionally execute other statements. The simple use of on if statement is as follows: if ( test) code executed if testis true;

Where test is evaluated it must evaluate to a Boolean value for the code to compile and the line of code shown below the statement is executed if test evaluates to true. After this code is executed, or if it isnt executed due to test evaluating to false, program execution resumes at the nest line of code. We can also specify additional code using the else statement in combination with an if statement. This statement will be executed if test evaluate to false: if test code executed if testis true; else code executed if testis false;

Both sections of code can span multiple lines using blocks in braces: if ( test); { code executed if testis true; } else { code executed if testis false; }

All Rights Reserved To EaglesGroup

165

As a quick example, lets rewrite the code from the last section that used the ternary operator: String result string = (My Integer 10); Less than 10 : Greater than 10; Since the result of the if statement cannot be assigned to a variable we have to assign a value to the variable in a separate step: String result string; if (My integer 10); result string = Less than 10; else result string = Greater than or equal to 10; Code such as this, although more verbose, if far easier to read and understand than the equivalent ternary form, and allows far more flexibility. Lets work it out Using the if Statement

Example 4-3 Using the if Statement

Example Try it out Eagles IFStatement Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles IFStatement in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the if Statement 2. Add the following code in the Program.cs as follows: namespace Eagles_IFStatement { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EalgesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program

166

All Rights Reserved To EaglesGroup

{ static void Main(string[] args) { string comparison; Console.WriteLine("Enter a Number:"); double var1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("Enter another number:"); double var2 = Convert.ToDouble(Console.ReadLine()); if (var1 < var2) comparison = "less then"; else { if (var1 == var2) comparison = "equal to"; else comparison = "greater than"; } Console.WriteLine ("The First number is {0} the second number .",comparison); } 3. Now run the application and enter two number at the runtime when it is promoted:

All Rights Reserved To EaglesGroup

167

Now lets see how the above code works: The first section of code is familiar, and simply obtaining two double values from lesser input. string comparison; Console.WriteLine("Enter a Number:"); double var1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("Enter another number:"); double var2 = Convert.ToDouble(Console.ReadLine());

Next we assign a string to the string variable comparison. Based on the values obtained for Var1 and Var2. First we check to see if var.1 is less than var.2: if (var1 < var2) comparison = "less then";

If this isnt the case then Vr1 is either greater than as equal to Vr2. In the else section of the first comparison. We need to rest a second comparison: else { if (var1 == var2) comparison = "equal to";

The else section of this second comparison will only be reached if Var1 is greater than Var2. else comparison = "greater than";

Finally we write the value of comparison to the console: Console.WriteLine ("The First number is {0} the second number .",comparison);

168

All Rights Reserved To EaglesGroup

The resting we have used here is just one way of doing this. We could equally have written: if (var1 < var2) comparison = "less then"; else { if (var1 == var2) comparison = "equal to"; else comparison = "greater than"; }

The disadvantage with this method is that we are performing these comparisons regardless of the value of Var1 and Var2 with the first method we only perform one comparison. If Var1 Var2 is true and two comparisons otherwise we also perform the Var1 == Var2 comparison, resulting in fewer lines of code being executed. The difference in performance here will be slight, but would be significant in application where speed of execution is social.

4.14More conditions using if statements:


In the last code we checked for three conditions involving the value of Var1. This covered all possible values for this variable. At other times we might want to check for specific values, say if var.1 is equal to 1, 2, 3 or 4, and so on. Using code such as that above can result in annoying rested code, for example:

if (Var1 ==1) { // do something } else { if (Var1 ==2) { // do something else } else

All Rights Reserved To EaglesGroup

169

{ if (Var1 ==3 || Var| = = 4) { // do something else } else { // do something else } } } DENOTE: That it is a common mistake to write conditions such as the third condition as if (var.1 ==3) || 4). Her, owing, to operator precedence, the == operator is processed first, leaving the || operator to operate on a Boolean and a numeric operand. This will cause an error. In these situations it can be worth using a slightly different indentation scheme and contracting the block of code for the else blocks that is, using a simple single line of code after the else blocks rather than a block of code 1. When we do this we end up with a structure involving else if statements: if (Var1 == 1) { // do something } else if (Var1 ==2) { // do something else } else if (Var1 ==3 || Var1 ==4) { // do something else } else { // do something else }

170

All Rights Reserved To EaglesGroup

These else if statement are really two separate statements, and the code is functionally individual to the above code. However, this code is much easier to read. When making multiple comparisons such as this, it can be worth considering the switch statement as an alternative branching structure.

4.15The switch statement


The switch statement is very similar to the if statement code conditionally based on the value of a test. However, switch allows us to test for multiple values of a test variable in one go, rather than just a single condition. This test is limited to discrete values, rather than closes such greater than x, so it is use is slightly different, but it can be a powerful technique. The basic structure of a switch statement is as follows: switch ( siddhuVar ) { case ( comparisonVa11 ): code to excrete if siddhuVar = = comparisonVar1) break; case comparisonVal2 ; code to excrete if siddhuVar = = comparisonVar2 break; ....... case comparison varN ; code to execute if siddhuVar = = comparisonValN break; default; code to execute if siddhuVar ! = = comparisonVals break; }

The value in siddhuVar is compared to each of the comparisonVal values specified wish case statements and if there is a match then the code supplied for this match is execrated. If there is no match then the code in default section is executed if this block exists. DENOTE: That this behavior is one area where C+ differs from C++, where the processing of case statements is allowed to run from one to another. The break statement here simply terminates the switch statements, and processing continues on the statement following the structure.
All Rights Reserved To EaglesGroup

171

There are alternative methods of preventing flow from one case statement to next in C# code. We can use the return statement, which results in termination of the current function rather than just the switch structure or goto statement as detailed earlier work jeer, since case statements in effect define in C# code. For example: switch (<testVar>) { case <comparisonVal>; <code to execute if <textVar> == <comparisonVal1> goto case <comparisonVal1>: <code to execute if <textVar> == <comparisonVal2>> Break; There is one execution to the rule that the processing of one case statement cant run freely into the next. If we place multiple case statement stack them before a single block of code, we are in effect checking for multiple conditions at once. If any of these conditions is met the code is executed, for example: switch (<testVar) { case <comparsionVal1>: case<comparsionVal2>: <code to execute if <textVar> == <comparsionVal1> or <testVar> == <comparsionVal1> break;

DENOTE: That these conditions also apply to the default statement. There is no rule saying that this statement must be the last in the list of comparisons, and we can stack it with case statement if we wish. But mostly rules are men to be broken. Adding a break point with break , goto, or return ensures that a valid execution path thought the structure in all cases. Each of the <comparsionValX> comparisons must be a constant value. One way of doing is to provide literal values, for example:

172

All Rights Reserved To EaglesGroup

switch (myInteger) { case 1: <code to execute if myInteger ==1> Break; case -1; <code to execute if myInteger == -1> break; default: <code to execute if myInteger != comparisons> break; } Another way is to use constant variables. Constant variables are just like any other variables, except for one key factor: the value contains never changes. Once we assign a value to a constant to a constant variable that is the value it will have for the duration of code execution. Constant variables can come in handy here, as it is often easier to read code where the actual values being compared are hidden from us at the time of comparison. We declare constant variables using the const keyword in addition to variable type, and must assign those values at this time, for example: Const int intTwo = 2;

This code is perfectly valid, but if we try: Const int intTwo; IntTwo = 2; We will get a compile error. This also happens if we try and change the values of a constant variables thought any other means after initial assignment:

All Rights Reserved To EaglesGroup

173

Lets work it out Using the Switch Statement

Example 4-4 Using the Switch Statement

Example Try it out Eagles SwithcStatment2 Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles SwithcStatement2 in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the Switch Statement 2. Add the following code in the program.cs as follows:
namespace Eagles_SwithcStatment2 { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { static void Main(string[] args) { const string myName = "siddhu"; const string dogName = "blacky"; const string phoneName = "sony"; string name; Console.WriteLine("What is you name?"); name = Console.ReadLine (); switch (name.ToLower ()) { case myName: Console.WriteLine("You have the same name as me!"); break ; case dogName : Console.WriteLine ("Oh Boy, My dog name!"); break ; case phoneName : Console.WriteLine ("Your Phone is Good"); break ; } Console.WriteLine ("Hello {0}!" , name ); }

174

All Rights Reserved To EaglesGroup

3. Now run the program and enter the name and you should have the output like this:

Now lets see how the above program works:

Our code sets up three constant strings, accepts a string from the user, and then out text to the console based on the string entered. In this case the strings are name. When we compare the name entered in the variable name to our constant value we first it into lower case with name.ToLower(). This is a standard command that will work with all string variables, and comes in handy when youre not sure what have been entered by the user. Using the technique the string Siddhu, SidDhuand siddhu, and so on will all match the test string siddhu. The switch statement itself attempts itself to match the string entered with the constant values we have defined. And writes out a personalized message, if successful, to greet the user. If no match is made we simply greet the user. Switch statement have no limit on the amount of case: section they contain, so you could extend this code to cover every name you can think have should you wish... But it might take a while!

All Rights Reserved To EaglesGroup

175

4.16Looping
Looping is where statements are executed repeatedly. This technique can come in very handy, as it means we can repeat operations as many times as we want without having to write the same code each time. As a simple example, consider the following code for calculating the amount of money in a bank account after 10 years, assuming that interest is paid each year and no other money flows into on out of the account

double balance = 1000; double interest Rate = 1.05; // 5% interest 1 year balance * balance * balance * balance * balance * balance * balance * balance * balance * balance * = = = = = = = = = = interest Rate; interest Rate; interest Rate; interest Rate; interest Rate; interest Rate; interest Rate; interest Rate; interest Rate; interest Rate;

Writing the same code out 10 times seems a bit wasteful, and what if we want change the duration from 10 years to some other value? We have to manually copy the line of code the revived amount of times, which would be a bit of a pain!

Luckily we dont have to do this. Instead we can just have a loop that executes the instruction we want the required number of timers. Another important type of loop is one where we loop until a certain condition is fulfilled. These loops are slightly simpler then the situation detailed above, so well start them.

176

All Rights Reserved To EaglesGroup

4.18Do loops
Do loops operate in the following way? The code we have marked out for looping is execrated, then 0; a Boolean test is performed, and the code executes again if this test evaluates to true, and so on. When the test evaluates to false the loop exists. The structure of a do loop is as follows: do { code to be looped } While ( Test );

Where Test evaluates to a Boolean value. The semicolon after the while statement is required, and its a common error to miss this out. For example. We could use this to write out the numbers from 1 to 10 in a column; int i = 1; do { console. write line ({0} ; i ++) ; } while (i T= 100);

Here we use the suffix version of the ++ operator to increment the value of i after it is written to the seen so we need to check for i = 10 in order to include ten in the numbers Lets use this for a slightly modification version of the code in the introduction to this section, where we calculate the balance in an account after 10 years. Here we will use a loop to calculate how many years it will take to get a specified amount of money in your account based on a stating amount and an interest.

All Rights Reserved To EaglesGroup

177

Lets work it out Using the do Loops

Example 4-5Using the do Loops

Example Try it out Eagles doloops Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles doloops in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the do Loops 2. Add the following code into the program.cs as follows:
namespace Eagles_doloops { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program static void Main(string[] args) { double balance, interestRate, targetBalance; Console.WriteLine("What is your current balance?"); balance = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("What is you current annual interest rate (in %) ? "); interestRate = 1 + Convert.ToDouble(Console.ReadLine()) / 100.0; Console.WriteLine("What balance would you like to have?"); targetBalance = Convert.ToDouble(Console.ReadLine()); int totalYears = 0; do { balance *= interestRate; ++totalYears; } while (balance < targetBalance); Console.WriteLine("In {0} year {1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance); }

178

All Rights Reserved To EaglesGroup

3. Now run the code and enter some values and you should see the output like this:

Now lets see how the above program works: This code simply replaces the simple annual calculation of balance with a fixed interest rate as many time as is necessary for the balance to satisfy the terminating condition. We keep count of how many years have been accounted for by incrementing a counter variable with each loop cycle: int totalYears = 0; do { balance *= interestRate; ++totalYears; } while (balance < targetBalance); We can then se this counter variable as part of the result output: Console.WriteLine("In {0} year {1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance); DENOTE: That is perhaps the most common usage of the? Ternary operator to conditionally format text with the minimum of code. Here we output ans after year if totallYears isnt equal to 1.

All Rights Reserved To EaglesGroup

179

But this code isnt perfect. Consider that the situation where the target balance is less than the current balance here the output will be along the lines of:

Do loops always execute at least once. Sometime, as in this situation, this isnt ideal. Of course, we could add an if statement: int totalYears = 0; if (balance < targetBalance) { do { balance *= interestRate; ++totalYears; } while (balance < targetBalance); }

180

All Rights Reserved To EaglesGroup

4.19WHILE LOOPS
While loops are very similar to do loops, but have one important difference. The Boolean test in a while loop takes place at the stand of the loop cycle, not the end. If the test evaluates to false then the loop cycles is never executed. Instead, program execution jumps straight to the code following the loop. While loops are specified in the following way: while (Test) { code to be looped }

And can be used in almost the same way as do loops; for example int i = 1 ; while (i = 10) { console. write line ({0}, i ++); } This codes gives the same result as the do loop we saw earlier, as it outputs the number 1 to 10 in a column.

Lets work it out Using the While Loops

Example 4-6Using the While Loops

Example Try it out Eagles Whileloops Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles Whileloops in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the While Loops 2. Add the following code in the program.cs as follows:

All Rights Reserved To EaglesGroup

181

namespace Eagles_Whileloops { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { static void Main(string[] args) { double balance, interestRate, targetBalance; Console.WriteLine("What is your current balance?"); balance = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("What is you current annual interest rate (in %) ? "); interestRate = 1 + Convert.ToDouble(Console.ReadLine()) / 100.0; Console.WriteLine("What balance would you like to have?"); targetBalance = Convert.ToDouble(Console.ReadLine()); int totalYears = 0; while (balance < targetBalance ) { balance *= interestRate; ++totalYears; } Console.WriteLine("In {0} year {1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance); }

3. Now run the program and when the output come enter a target balance less than the starting balance and see the output :

182

All Rights Reserved To EaglesGroup

Now lets see how the above code works:

This is simple change from the do loop to a while loop has solved the problem in the last example. By moving the Boolean test to the start we provide for the circumstance where no looping is required, and we can jump string to the result. There are, of course, other alternatives in the this situation. For example, we could check the user input to ensure that the target balnce is greater that the starting balance. In this situation like this we can place the user inputes section in a loop as follows:

This will reject the value that doesnt make sense, se we l l gets the output as follows:

All Rights Reserved To EaglesGroup

183

4.20FOR LOOPS
The last type of loop well look at in this chapter is the for loop. This type of loop is one that excretes a set number of times, and maintains its own counter. To define a for loop we need the following information: A starting value to initialize the outer variable A condition for containing the loop, involving the counter variable An operation to perform on the counter variable at the end of each loop cycle. For example, if we want a loop with a counter that increments from 1 to 10 in steps of an then the starting value is 1, the condition is that the counter is less than or equal to 10. And the operation to perform at the end of each cycle is to add one to the counter. This information must be placed into the structure of a for loop as follows: for ( initialization ; condition ; operation) } code to loop }

This works in exactly the same way as the following while loop: initialization while ( condition) { code to loop operation } But the format at the for loop makes the code easier to read, as the syntax involves the complete specification of the loop in one place, rather than being divided over several statements in different areas of the code. Earlier we used do and while loops to write out the numbers from 1 to 10. Lets look at the code required to do this using a for loop: int i ; for (i =1; i=10; ++i) { Console.WriteLine ({0},i); }

184

All Rights Reserved To EaglesGroup

The counter variable, an integer called i, starts with a value of 1, and is incremented by 1 at the end of each cycle. During each the value of i is written to the console. DENOTE: That when code resumes after the loop i has a value of 11. This is because at the end of the cycle where i was equal to 10, i gets incremented to 11. This happens belong the condition that i = 10 is processed, at which paint the loop ends. As with while coops, for loops only execute if the condition evaluates to true before the first cycle.So the code in the loop doesnt necessary run at all. As a final not, we can declare the counter variable as part of the for statement, rewriting the above code as: For (int i ; i=10; ++i) { Console.WriteLine ({0},i); }

If we do this, though, the variable; wont be accessible from code outside this loop (see the section on variable scope in the up coming chapter) Lets look at an example using for loops.Since we have used loops quite a bit now. Ill make this example a bit more interesting; it will display a Mandelbrot set using plain text characters, so it wont look that spectacular) Lets work it out Using the for Loops

Example 4-7Using the for Loops

Example Try it out Eagles forLoops Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles forLoops in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the for Loops\Eagles forLoops 2. Add the following code in the Program.cs as follows:

All Rights Reserved To EaglesGroup

185

namespace Eagles_forLoops { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { static void Main(string[] args) { {// Illustrate a simple for loop that counts from 1 to 5 for (int i = 0; i < 5; ++i) System.Console.WriteLine("I = {0}", i); // Illustrate two loops to first find a letter in a string // and then to print it out until a space is encountered. // This shows you how to skip initialization in the second // loop int nPos = 0; string s = "this is a test of the emergency broadcast system"; for (nPos = 0; nPos < s.Length; ++nPos) if (s[nPos] == 'b') break; for (; nPos < s.Length; ++nPos) { if (s[nPos] == ' ') break; System.Console.Write(s[nPos]); } System.Console.WriteLine("\n"); / Finally, illustrate how to use the for loop for something // other than an integer and how to change the increment int state = 0; for (double d = 0.0; d < 5.0; ) { System.Console.WriteLine("D = {0}", d);

186

All Rights Reserved To EaglesGroup

switch (state) { case 0: d += 0.1; break; case 1: d += 0.2; break; case 2: d += 0.5; break; } state++; if (state > 2) state = 0; } }

3. Now run the program and you should have the output like this:

Now lets see how the above code works: As you can see, the incrementing of a floating point number is a tad strange in C#, which is something to be aware of while working with floats. You can never be quite sure how the compiler will generate instructions to add fractional numbers. The printing of the word broadcast shows how you can easily parse a string in C#, of course, the first block illustrates the most basic use of a for loop.

All Rights Reserved To EaglesGroup

187

4.21FOREACH LOOP

The foreach loop allows programmers to quickly and easily work their way through array in order to process each element in the array. Although the foreach statement is new to C++ and Java programmers, it is quite familiar to VBScript programmers. This statement, a simple shorthand technique for loop, automatically uses the Get Enumerator interface to step through a given array or collection. The following example of iterating over one of the C# CLR collections the directory class. Lets work it out Using the foreach Loops

Example 4-8Using the foreach Loops

Example Try it out Eagles foreachLoops Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles foreachLoops in the directory C:\EaglesVisualCSharp\Chapter 4 Flow Control\Example Using the foreach Loops 2. Add the following code in the program.cs namespace Eagles_foreachLoops { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program {

188

All Rights Reserved To EaglesGroup

static void Main(string[] args) { // First, an array of integers int[] arrayOfInt = { 1, 2, 3, 4, 5 }; foreach (int i in arrayOfInt) { Console.WriteLine("Int {0}", i); } // Now, how about an array of strings? string[] arrayOfStr = { "Hello", "Goodbye", "Why me?" }; foreach (string s in arrayOfStr) { Console.WriteLine("String {0}", s); } / Finally, let's look at a dictionary collection System.Collections.Generic.Dictionary<string, string> d = new System.Collections.Generic.Dictionary<string, string>(); //the Dictionary class d.Add("100", "Science"); d.Add("200", "Math"); d.Add("300", "English"); d.Add("400", "History"); d.Add("500", "Gym"); foreach (System.Collections.Generic.KeyValuePair<string, string> de in d) { Console.WriteLine("Entry Key {0} Value {1}", de.Key, de.Value); } }

All Rights Reserved To EaglesGroup

189

3. Now run the program and you will have the following output:

Now lets see how the above program works: As you can see, the foreach statement is quite powerful. Because it is scripting shorthand for using the C# enumeration facilities, it allows you to create your own class that support a for each statement. All you need to do is to implement the Get Enumerator method in your class and provide the appropriate type of enumerator to retrieve data. Then, you can use foreach as if your class were built into the language.

4.22Interrupting Loops
There are times when we want fires grained control over the processing of looping code. C# provides four command that help us here, three of which we seen before in other situations. Break - causes the loop to end immediately continue - causes the current loop to end immediately (excretion continues with the next loop cycle) go to - allows jumping out of a loop to a labeled position not recommended if you want your code to be easy to read and understand) Return - jumps out of the loop and its containing function.

The break command simply exists the loop, and excretion continues at the first line at code after the loop for example

190

All Rights Reserved To EaglesGroup

int i ; while (i=10;) { if (i= =6) break; Console.WriteLine ({0},i++); } This code will write out the numbers from 1 to 5, as the beak command causes the loop to exit when i reach 6. Continue only stops the current cycle, not the whole loop, for example; int i ; for (i =1; i=10; ++i) { if (1i%2) ==0) continue; Console.WriteLine (i); } In the above example, whenever the remained of i divided by 2 is zero, the continue statement stops the excretion of the current cycle, and so only the numbers 1, 3, 5, 7, 9 are displayed. The third method of interrupting a loop is to use go to us we saw earlier, for example: int i =1 ; while (i=10) { if (i==6) go to exit point; Console.WriteLine ({0},i ++); } Console.WriteLine (This code will never be reached.); exit point Console.WriteLine (This code is run when the loop is exited using go to :);

DENOTE: That exiting a loop with go to is legal if slightly messy, but it is illegal to use go to jump into a loop from outside.

All Rights Reserved To EaglesGroup

191

4.23INFINITE LOOPS
It is possible, through both coding errors and design, to define loops that never end, so called infinite loops. As a very simple example, consider the following: While (true) { // code in loop }

This situation can be useful at times and we can always exit such loops using code such as break statements. However, when this occurs by accident it can be annoying. Consider the following loop, which is similar to the for loop in the last section: int i ; while (i=10) { if ((i %2) ==0) continue; Console.WriteLine ({0},i++); } Here i doesnt get incremented until the last line of code in the loop, which occurs after the continue statement. If this continue statement is reached which it will be when i is 2, the next loop gets will be using the same value of i, continuing the loop, testing the same value of i, and continuing the loop and so on. This will cause the application to freeze. Not that its still possible to quit the frozen application in the normal way, so you wont have to reboot your computer if this happens.

192

All Rights Reserved To EaglesGroup

4.24UNSAFE CODE
Perhaps this heading should be in a warring block. Do not use unsafe code, its unsafe. In C#, however the unsafe code label is applied whenever you want to use elements the new language does not allow, but in order to get your job done you need to use these elements. For example, if you want to call out to a Windows API function from C#, you might need to use a pointer to iterate through a returned block of structures. The problem is, of course, that C# does not have pointers. Only C++ has them. Yet, you need the ability to call that function to get your job done. This is where C# really shines. It helps you get your job done, as long as you understand the risk you are taking. The purpose of unsafe code is to accomplish something that is, by its nature, an unsafe thing to do. One good example is in using pointers. Another is in using memory that cannot be safely collected by the garbage collection mechanism in the C# runtime environment. Something worth nothing is that even in an unsafe environment; C# does not allow you to violate type safety with one notable exception: void pointers. Thus, you can write: unsafe { Int[] x = new int int [10]; Int*px = &x; }

In this, case you have defined an unsafe block that allows you to assign a pointer an array so that you can step through it in typical array fashion, by incrementing the pointer. However, you still cannot do the following: unsafe { Int *x = new int[10]; } An integer pointer is not array; therefore you cannot assign an array to it. You cannot delete the array under any circumvents you must allow it to be garbage collected. Sometimes, you need to be able to create a pointer to call an eternal function. The problem of course is that the pointer at a block level of memory that can be garbage collected or moved in the memory without your knowledge about it. In case like this C#

All Rights Reserved To EaglesGroup

193

provides for fixed statement, which allows you to pin a pointer in memory until you are done with it. Heres how you use it: Ussafe { Int [] x = new int [10]; Fixed (int xp = &x) { CallAFunctionwthAPointer(xp); } }

4.25Fixed size Buffers


A fixed size buffers is a structure which specifics a storage location for a fixed length buffer of variables of a given type. The objective of fixed size buffers is to create to struct in which the array element of the buffer can be stored. Fixed size buffers are useful while reusing the existing code written in existing DLLs, other applications or COM projects. In previous version of C#, declaring a fixed size structure in C++ was not easy. This is because normally stored within the struct. But, using a fixed size buffer allows you to store the entire array within the struct. C# 2.0 enables you to declare an array of fixed size in a struct but this is not possible in C#. 1.0 While using an unsafe code block.

Public struct Eagles Unsafe bloc { Public fixed char EmplyName[50]; Public int RmpID; }

4.26Extending the Language


No language is perfect; exactly like human beings none of us was perfect. No language is so well designed that it never encounters something, it need to be used for that is does not do well. In cases like these, the languages must be extended in some way to allow it to accomplish the tasks that need to be done in the real world. C# provides two different methods, managed C++ and COM components, and for doing tasks the languages does not intrinsically do.

194

All Rights Reserved To EaglesGroup

4.27Managed C++
First, a word of expiation, managed C++ is not really C#. it happens to be compiler that ships with Visual C# and allows, C++ development to use many of the same technique and library components as they fins in C#. However, managed C++ is a different compiler and is rally C++ in the .NET environment rather than a C# extension. The reason it covered in this section is that managed C++ is a natural extension of the use of the C# programming concepts in the .NET environment. Well what is managed C++? Simply, managed C++ is the way in which you can run C++ programs in a managed environment, as C# does, managed C++ gives you access to many C# extensions, such as garbage collection, the CLR, and exception handling from the ground up. Managed C++ does follow standard C++ rules, in that you can use the new operator to create objects. However, classes marked, as being available for garbage collection may not use the delete operator to delete those objects. C++ classes in a managed environment can also contain properties and use the managed components of the C# library, such as the String class. To utilize the managed C++ environment, you must use the newest version of the C++ compiler, which ships with the Visual Studio.NET and the .NET SDK Framework on it own. SDK versions of the compiler. You must further use the COM+ enchantments to the C++ language by using the /com+ comelier directive. Rather than going into greater detail here about managed C++ because it is not really a part of the C# system.

4.28COM Components
The Common Object Model (COM) and Windows is a topic that evokes greater emotion from developers. In general, people either love the idea or hate it. Bu no middle ground seems to exist. However, COM is here to say, whether you like it or not. Because the COM component is here to stay, you should leverage the capabilities it offers you whenever you can take advantage of them in you own development work. C# is built around a core of COM and exposes that functionality wherever it can,. Interfaces, binary components, and versioning are all obvious facets of the COM like nature of C#. C# makes creating COM components easy. It also makes utilizing existing COM component sin new application easy. This ease of use is important because many companies have best stake in their legacy COM components. Using a COM component in C# is a simpler matter of converting it into a type library that the C# runtime environment and compiler understand, and then linking the resulting metadata into your application, from there you simply use the COM library as if it were just another C# namespace.

All Rights Reserved To EaglesGroup

195

SUMMARY
In this chapter we have developed our programming knowledge by considering various structures, is essential when we start making more complex applications, and we will see them time and again through this book. First we spent some time looking at Boolean logic with a bitwise logic thrown in for good measure. Looking back on their after working through the rest of the chapter confirms the starting assumption that we made, which is that this topic is very important when it comes to implementing branching and looping code in our programs. It is essential to become very familiar with the operators and techniques detailed in this section. Branching enable us to conditionally create code, which, when combined with looping, allows us to create controlled structured in our C# code. When you have loops inside if structures inside loops, you start to see why code indentation is so useful! If we shift all our code to the left of the screen it instantly becomes difficult to purse by eye, and even more difficult to debug. It is well worth making youve got the hang of indentation at this stage - youll appreciate it later on! OK, so we do a lot of this for us. But its a good idea to indent code as you type it any way. So far we have been see the following topics: 4.0 Introduction to Flow control 4.1Selection 4.2Iteration 4.3Conditional Logic 4.4Branching 4.5Looping 4.6Boolean Logic 4.7Bitwise operators 4.8Boolean Assignment operators 4.9Operator precedence updated 4.10The goto statement 4.11Branching 4.12The ternary operator 4.13The if statement 4.14More conditions using if statements: 4.15The switch statement 4.16Looping 4.18Do loops 4.19WHILE LOOPS 4.20FOR LOOPS 4.21FOREACH LOOP 4.22Interrupting Loops 4.23INFINITE LOOPS

196

All Rights Reserved To EaglesGroup

4.24UNSAFE CODE 4.25Fixed size Buffers 4.26Extending the Language 4.27Managed C++ 4.28COM Components

All Rights Reserved To EaglesGroup

197

Chapter 05

198

All Rights Reserved To EaglesGroup

5. 1 Introduction to Functions

Functions

All the code we have seen so for has taken the Form of a block, perhaps with some looking to repeat lines of cook and branching to execute statements conditionally. It weve needed to perform an operation on own data then this has meant placing the code required right. Where we want it to work. This kind of code structure is limited. We will often find that some tasks for exam finding the highest value is an array may need to be performed at several paints in a program. We can just place identical as near identical sections of code in own application whenever necessary, but this is own problems changing even one minor detail

concerning a common task, to correct a code for example, may require change to multiple sections of code, which may be spread throughout the application. Missing one of these could have dramatic, and cause the whole applications to. In addition, the application could get very lengthily. The solution to this problem is to functions. Functions in C# are a means of providing blocks of code that can be executed at any point in an application. Functions of the specific type we are considering in this chapter are known as methods. However, this term has a very specific meaning in, Net programming that will only become clear later in the book, so for now well avoid the use of this term. For example we could have a function that calculates the maximum value in an array. We can use this function from any point in own code, and use the same lines of code in each case. Since we only need to sunny this one any changes we make to its will affect this calculation whenever it is used. This function can to thought of as containing reusable code. Functions also have the advantage of making over code more readable, as we can use then to related code together. If we do this then own application body it can be made very short, as the inner workings of the code are set out. This is similar to the way in

All Rights Reserved To EaglesGroup

199

which we can collapse regions of code together in visual studio. Net using the outline, view, and gives a mare logical structure to own application. Functions can also be used to create multi purpose code, allowing them to perform the same operations on varying data. We can supply a function in the form of return values. In the above example, we could supply a way to search as a parameter and obtain the maximum value in the array as a return value. This means that we can use the same function to work with a different array time. Two parameters and return value of a function collectively define the signature of a function. In this chapter well start by looking at the way in which we can define and use simple functions that dont accent on return and data. After this well move on to look at the way in which we active transfer of data to and form functions. Next well take a book at the issue at variable scope. This concerns the way in which data in a C# application is localized to specific regions of code an issue that becomes especially important when we are separating own code into multiple functions. After this, well take an in depth look at an important function in

C# applications main well see how are can use the built in behavior of this function to make use of command line arguments which enable us to transfer information into applications when we run them. Next, well take a look at an additional features of the struct type that we saw in the last chapter, the fact that you can supply functions as members of strut types.

Finally well turn own attention to two more advanced topics: 1. 2. Function own loading Delegates.

Function over loading is a technique that allows us to provide multiple functions with the safe none but different signatures. A delegate is available type that allows us to used
All Rights Reserved To EaglesGroup

200

functions indirectly. The same delegate can be used to call any function that matches a specific signature, giving the us the ability to choose between several functions at run time.

5. 2 Defining and Using Functions


The following code section will look at how we can add functions to own application and then use call them from own code. Well start with the basic, looking at simple functions that dont exchange any data with code, that calls, them, and them move on to look at more advanced function usage. Lets work it out Defining and Using a Basic Function

Example 5-1 Defining and Using a basic Function

Example Try it out Eagles BasicFunction Step by Step Example: Using Version 2005
1. Create a new Console application name it as Eagles BasicFunction in the directory C:\EaglesVisualCSharp\Chapter 5 Function\Example Defining and Using a basic Function 2. Add the following code in the Program.cs as follows: namespace Eagles_BasicFunction { # region EaglesGroup /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program static void Siddhu() { Console.WriteLine("Welcome to EaglesGroup!"); }

All Rights Reserved To EaglesGroup

201

static void Main(string[] args) { Siddhu (); }

3. Now Run the program and you should have the output like this:

Now lets see how the above program works: The following four lines of our code define a function called Write ();

Static void Siddhu () { Console.WriteLine (Welcome to EaglesGroup!.); }

The code contained here simply outputs some text to the Console window. However, this behavior isnt that important to us at the moment, as were more concerned with the mechanisms behind function definition and use.

202

All Rights Reserved To EaglesGroup

The function definition here consists of the following: Two keywords, static and void. A function name followed by parentheses, Write (). A block of code to execute enclosed in curly braces. The code that defines the Write () function looks very similar to the other code in our application: Static void Main (string [] args) { . }

This is because all the code we have written so far apart from type of a function. This function, Main (),is a suggested by the comment in the auto generated code the entry contains is called, and when this function completes the application terminates. All the C# executable code must have an entry point. The only difference between the main ( ) function and our writes ( ) function (apart form the liner of code they contain), is that there is some code inside the parentheses after the function name main. This is how we specify parameters, which well discuss in more detail shortly. As mentioned above, both main ( ) and write ( ) are defined using static and void keywords. The static keyword relates to object oriented concepts, which well come back to later in the book. For, now you only need to remember that all the functions well use in own applications in this section of the book must use this keyword. Void, on the other hand is much simpler to explain. This keyword is to indicate the function does not return a value. Later on in this chapter, well see. What we need to write when a function has a return value. Moving on, the code that calls our function is as follows: Siddhu();

All Rights Reserved To EaglesGroup

203

We simply type the name of the function followed by empty parentheses. When program execution reaches this point the code in the Write () function will run.

DENOTE: That the parentheses used, both in the function definition and where the function is called, are mandatory. Try removing them if you like the code wont compile.

5.2.1 Return values


The simplest way of exchanging data with a function is to make use of a return value. Functions that have return values evaluate to the value they contain when we use them in expression. Just like variables, return valves have a type. For example, we might have a function called get string ( ) whose return valve is a string. We called use this in code, such as: String my String; My String = get String ( );

Alternatively, we might have a function called get Val ( ) that returns a double valve, which we could use in a mathematical expression: Double my val ; double multiplier = 5.3 Myval = get val ( ) * multiplier ;

204

All Rights Reserved To EaglesGroup

When a function in two ways: Specify the type of the return valve in the function declaration instead of using the void keyword. Use the return keyword to end the function execution and transfer the return value to the calling code. In code terns this looks like the following in a console application function of the type weve been looking at: Static < return type > < function name > ( ) { return < return valve >; }

The only limitation here is that < return valve > most be a valve that is either of type < return type > as can be implicitly converted to that type. However, < return type > can be type we want, including the more complicated types well see. More complicated types weve see. This might be as simple as:Static double get val ( ) { return 3.2 ; } But, wait ; However value are usually the result of some processing carried out by the function; as the above could be achieved just as easily by using a cost variable.

All Rights Reserved To EaglesGroup

205

When the return statement reached the program execution return, to the calling code immediately, No lines of code after this statements will be executed. However this doesnt mean that return statements can only be placed on the last line of a function body. We can use return earlier in the code, perhaps after performing some branching logic. Placing return in for loop and it block, or any other structure causes the structure to terminate immediately and the function to terminate for example. Static double getVal ( ) { double checkVal ; //checkVal assigned a valve through some logic if (checkVal < 5) return 4.7; return 3.2; }

Here one of two values may be returned depending on the value of checkVal. The only restriction here is that a return statement must be processed before reaching the closing } of the function. The following is illegal:Static double getVal ( ) { double checkVal ; // checkVal assigned a valve through some logic if (checkVal < 5) return 4.7; }

206

All Rights Reserved To EaglesGroup

If checkVal is > = 5 then no return statement is met, which isnt allowed. All processing paths must reach return statements. As a final note, return can be used in functions declared using the void keyboard that dont have return value. If we do so, then the function will simply terminate. When we so return in this was, it is an error to provide to return valve in between the return keyword and the semicolon that follows.

5.3 Parameters
When a function is to accept parameter, we must specify the followings: A list of the parameters accepted by a function in its definition, along, with the type of those parameters. A matching list of parameters in each function call. We can have any number of parameter, each with a type and a name. The parameters are separated using commas. Each of these parameters is accessible from code within the function as a variable. For example, a simple function might take two double parameters and return their product:

Static double product (double param1, double parm2) { Return param1 * param2; } Lets work it out Using Exchanging Data with a Function

Example 5-2 Using Exchanging Data with a Function

Example Try it out Eagles ExchaningFunction Step by Step Example: Using Version 2005

All Rights Reserved To EaglesGroup

207

1. Create a new Console Application and name it as Eagles ExchaningFunction in the directory C:\EaglesVisualCSharp\Chapter 5 Function\Example Using Exchanging Data with a Function 2. Add the Following code in the Program.cs namespace Eagles_ExchaningFunction { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGrpoup> # endregion class Program { static int MaxValue (int [] intArray) { int maxVal = intArray [0]; for (int i = 1; i < intArray.Length; i++) { if (intArray [i] > maxVal ) maxVal = intArray [i]; } return maxVal ; } static void Main(string[] args) { int[] myArray = {0, 4, 2, 7, 2, 3, 1, 7, 3, 4, 3}; int maxVal = MaxValue (myArray ); Console.WriteLine ("The Maximum value in myArray is {0}", maxVal ); } }

208

All Rights Reserved To EaglesGroup

3. Now run the program and you will have output like this:

Now lets see how the above code works: This code contains a function that does what the example function discussed in the introduction to this chapter hoped to do, It extents an array of integers as a parameter and returns the highest number in the array. The function definition is as follow: static int MaxValue (int [ ] intArray) { int maxVal = intArry [ 0 ]; For (int i = 1; i < intArray. Length ; i++ ) { if ( intArray [ ; ] > maxVal) maxVal = intArray [ i ] ; } return maxVal ; }

All Rights Reserved To EaglesGroup

209

The function, MaxValve ( ), has a single parameter defined, an int, and array called int Array. It also is a return type of int. The calculation of the maximum valve is simple. A local integer variable called Max Val is initialized to the first valve in the array, and them Max Val, then this valve replaces the current valve of Max Value. When the loop finisher, Max Val contains the highest valve in the array, and is returned using the return statement. The code in Main ( ) declare and initializes a simple integer array to use with the Max Valve ( ) function: int[] myArray = {0, 4, 2, 7, 2, 3, 1, 7, 3, 4, 3}; The call to Max valve ( ) is used to assign a value to the int variable maxVal. int maxVal = MaxValue ( myArray ) ;

Next, we write thin value to the scan using Console.WriteLine (); Console.WriteLine (the maximum value in myArray is {0}; minVal}).

5.3.1 Parameter matching


When we call a function, we must match the parameters as specified in the function definition exactly. This means matching the parameter types, the number of parameters, and the order of the parameters. This means, for example that the following function. Static void my function (string, double mydouble) { }

210

All Rights Reserved To EaglesGroup

Cant be called using: myFunction (2, 6, Hello);

Here we are attempting to pass a double value, as the first parameter and a string valve as the second parameter, which is not the order is which the parameters are defined in the function definition. We also cant use: myFunction ( Hello) ;

Here we are only passing a single string parameter, where two parameters are required. Attempting to use either of the two function calls above will result in a combine error, as the compliers force us to match the signature, of the functions we use. Going back to our example, this means that MaxValue ( ) can only be used to obtain the maximum int in an array of int values. If we replace the code in main ( ) with the following code: static void Main (string [ ] args ) { double [ ] myArray = { 1, 3, 8, 9, 3.3, 6.5 } ; double maxVal = Max Value (myArray ) ; Console.WriteLine (The maximum value in myArray is {0} , maxVal); }

Then the code wont compile as the parameter type is wrong.

All Rights Reserved To EaglesGroup

211

5.3.2 Parameter arrays


C# allows us to specify one and only one special parameter for a function. This parameter which must be the last parameter in the function definition, is known as a parameter array, parameter arrays allow us to call functions using a variable amount of parameters, and are defined using the prams keyword. Parameter arrays can be a useful way to simplify our code, as we dont have to pass arrays from our calling code. In stead we pas several parameters of the same type that are placed in an array that we can use from within our function. The following code is required to define a function that uses a parameter array: static < returnType > < functionName > ( < p1Type > < p1Name > params < type > [ ] < name > ) { . return [ returnValue > ; } We can call this function using code like; < functionName > ( < p1 >, ., < val1 >, (val2), . ) Here, < val1)>, < val2) and so on are values of type < type > that are used to initialize the < name > array. There is no limit on the amount of parameters that we can specify here; the only restriction is that they are all of type < type >, we can even specify no parameters at all. This final point makes parameter arrays particularly useful for specifying additional information for function to use in their processing. For example, lets say we have a function called get word ( ) that takes a string value as its first parameters and returns the first word in the string;

212

All Rights Reserved To EaglesGroup

Here firstWord will be assigned the string this . string first word = getWord ( this is a sentence );

We might add a params parameter to getWord ( ) allowing us to optionally select alternative word to return by its index; String first word get word (This is a sentence., 2 );

We might also add the capability to limit the amount of characters returned in a third parameter, also accessible through the params parameter; string firstWord = getWord (Welcome to EaglesGroup, , 4, 3);

Here first word would be assigned the string siddhu. Lets work it out Using Exchanging Data with a Function Part2

Example 5-3 Using Exchanging Data with a Function Part 2

Example Try it out Eagles ExchaningFunction2 Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles ExhchaningFunction2 in the directory C:\EaglesVisualCSharp\Chapter 5 Function\Example Using Exchanging Data with a Function Part2 2. Add the following code in the program.cs as follows:

All Rights Reserved To EaglesGroup

213

namespace Eagles_ExchaningFunction2 { # region EaglesGroup Console Application /// <summary> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </summary> # endregion class Program { static int sumValue(params int[] vals) { int sum = 0; foreach (int val in vals) { sum += val; } return sum; } static void Main(string[] args) { int sum = sumValue (0, 5, 0, 9, 1, 9, 8,5); Console.WriteLine ("Summed Values = {0} ", sum ); } }

214

All Rights Reserved To EaglesGroup

3. Run the program and you will have the output like this:

Now lets see how the above code works: In this example, the function sumVals ( ) is defined using the params keyword to account any number of int parameters (and no other); static int sumValue(params int[] vals) { }

The code in this function simply iterates through the value in the vals arrays, and adds the valves, together, returning the result. In main ( ) w, call this function with five integer parameters:-

int sum = sumValue (0, 5, 0, 9, 1, 9, 8,5);

All Rights Reserved To EaglesGroup

215

However, we could just as easily have called this function with none, one, two, on a hundred integer parameters there is no limit to the amount we can specify.

5.4 Reference and value parameters


All the functions we have defined so far in this chapter have had valve parameters. What I mean by this is that when we have used parameters we have passed a value into a variable used by the function. Any changes made to this variable in the function have no effect on the parameter specified in the function call. For example, consider a function that double and display the valve of a passed parameter. static void show double (int val) { val* = 2; Console.WriteLine (val doubled = {0}, val); }

Here the parameter, val is doubled in this function. If we call it in the following way; int my number = 5, Console.WriteLine (myNumber = {0}, myNumber); showDouble (myNumber ) Console.WriteLine (myNumber = {0}, myNumber);

The text out put to the console is as follows

216

All Rights Reserved To EaglesGroup

My number = 5 val doubled = 10 my number = 15 Calling showDouble ( ) with my number as a parameter doesnt affect the vale of my number in main ( ), even through the parameter it is assigned to, val is doubled. This is all very well, but it if we want the valve of my number to change we have a problem. We could a function that returns a new valve for my number, and call it using.

It my number = 5 console writeline ( my number = { 0 }, my number ); my number = show double (my number); But this code is hardly intuitive and wont code with changing the value of multiple variable used as parameters as function have only one return value). Instead, we want to pass the parameter by reference. This means that the function will wont with exactly the same variable as the one used in the function call, not just a variable that has the same value. Any changes made to this variable will, therefore, be reflected in the value of the variable used as a parameter. To do this we simply have louse the ref keyword to specify the parameters. static void show double ( int val) {

val * = 2 Console.WriteLine (val doubled = { 0 } , val )

All Rights Reserved To EaglesGroup

217

And again in the function call (this is mandatory, as the fact that the parameter is ref parameter is part of the function signature) int my number = 5; console writeline ( my number = { 0 } my number ) showDouble (ref myNumber); Console.WriteLine (val doubled = {0}, val); Text output of the above code myNumber = 5 val doubled = 10 myNumber = 10

This time my number has been modified by showDouble ( ) There are two limitation on the variable used as a ref parameter. First, the function may result in a change to the value of a reference parameter so we must use a non-constant variable in the function all The following in therefore illegal const int my number = 5, Console.WriteLine (my number {0} my number) showDouble (ref my number) Console.WriteLine (my number = {0}

Second we must use an initialized variable doesnt allow is to assume that a ref parameter will be initialized in the function that use it. The following code is also illegal

218

All Rights Reserved To EaglesGroup

int myNumber show double (ref myNumber ) Console.WriteLine (my number = { 0 } myNumber )

5.5 Out parameter


In addition to passing valves by reference, we can also specify that a give Parameter is an out parameter using the out keyword, which is used in the same way as the ref keyword (as a modifiers to the parameter in the function definition and in the function call). In effect, this gives us almost exactly the same behavior as a reference parameter is that the value of the parameter at the end of the function execution is retuned to the variable used in the function call, however, there are important difference. Where it is illegal to use unassigned variables as a ref parameter, we can use an unassigned variable as an out parameter. In addition, as out parameter must be treated as an unassigned value it is permissible for calling code to use an assigned variable as an out parameter, the values stoned in this variable will be lost when the function executes. As an example, consider an extension to the max value function we saw earlier that returns the maximum value of an array, well modify the function slightly such that we obtain the index of the element with the maximum value within the array. To keep tings simple, well just obtain the index of the first occurrence of this value where there are multiple elements with the maximum value. To do this, we add an out parameter by modifying the function as follows:

All Rights Reserved To EaglesGroup

219

static int. maxValue (int. [ ] intArray, out int maxIndex) { int maxVal = intArray [0]; for (int i = 1; i intArray, Length i++) { if (int Array [i] maxVal) { maxVal = int Array [i] max Index = i; } } return maxVal; } We might use this function as follows: int [ ] my Array = { 1,8,3,6,2,5,9,3,0,2,} int max Index;

Console.WriteLine (The maximum value in my Array is {o} Maxvalue (my Array; o9ut max Index),} Console, write line (The first occurrence of this value is at element {o}; max Index +) The result is:

The maximum value in my Array is a The first occurrence of this value is at element 7

An important point to note here is that we must use the out key word in the function call, just as with the ref keyword.

220

All Rights Reserved To EaglesGroup

5.5.1 Variable scope


Throughout the last section, you may have been wondering why exchanging data with function is necessary. The reason is that variables in c are only accessible from localized regions of code. A given variable is said to have a scope from where it is accessible. Variable scope is an important subject, and one best introduced with an example.

Lets work it out Using Defining and using a basic Function

Example 5-4 Using Defining and Using a basic Function

Example Try it out Eagles DefiningbasicFunction Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles DefiningbasicFunction in the directory C:\EaglesVisualCSharp\Chapter 5 Function\Example Using Defining and using a basic Function 2. Add the Following code in the Program.cs as follows:
namespace Eagles_DefiningbasicFunction { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1979 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { static void Eagles() { Console.WriteLine("myString = {0}", myString); } static void Main(string[] args) { string myString = "String defined in Main ()" + " This is more fun haha"; Eagles(); } }

All Rights Reserved To EaglesGroup

221

3. Now run the Program and you should have the Following error as follows:

Now let see how the above program works and what went wrong? So, what went wrong? Well, the variable myString defined in the main body of our application the Main () function isnt accessible from the Eagles () function. The reason for this inaccessibility is that variables have a scope within which they are valid. This scope encompasses the code block that they are defined in and any directly nested code blocks. The blocks of code in functions are separated from the blocks of code from which they are called. Inside Eagles () the name myString in undefined, and the myString variable defined in Main () is out of the scope it can only be used from witching Main () In fact, we can have a completely separate variable in write ( ) called my string. Try modifying the code as follows: amespace Eagles_DefiningbasicFunction { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1979 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup>
# endregion class Program { static void Eagles() {

string myString = "String defined in Eagles () " + "This is the Proper "; Console.WriteLine("Now in Eagles()"); 222
All Rights Reserved To EaglesGroup

Console.WriteLine("myString = {0}", myString); } static void Main(string[] args) { string myString = "String defined in Main ()" + " This is more fun"; Eagles(); Console.WriteLine("\nNow in Main()"); Console.WriteLine("myString = {0}", myString);

4. Now Build the program and run the application and the program will run and you will see the output like this:

But, how the program runs what happen?


The operations performed by this code are as follows:-

All Rights Reserved To EaglesGroup

223

Main ( ) defines and initializes a string variable called my string. Main ( ) transfers control to write ( ) Write ( ) defines and initializes a string variable called my string, which is a different variable to the my string defined in main ( ) write ( ) outputs a string to the console containing the value of my string as defined in write ( ) Write ( ) transfer control back to main ( ) Write ( ) transfer control back to main ( ) Main ( ) out puts a string to the console containing the values of my string as defined in main ( ) Variables whose scope covers a single function in this way are knows as local variable. It is also possible to have global variables, whose scope covers multiple functions. Modify the code as follows:namespace Eagles_DefiningbasicFunction { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1979 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { static string myString; static void Eagles() { // string myString = "String defined in Eagles () " + "This is the Proper "; string myString = "String defined in Eagles()"; Console.WriteLine("Now in Eagles()"); Console.WriteLine("myString = {0}", myString); Console.WriteLine("Global myString = {0}", Program.myString); }
All Rights Reserved To EaglesGroup

224

static void Main(string[] args) { //string myString = "String defined in Main ()" + " This is more fun"; string myString = "String defined in main()"; Program.myString = "Global string"; Eagles(); Console.WriteLine("\nNow in Main()"); //Console.WriteLine("myString = {0}", myString); Console.WriteLine("Local myString = {0}", myString); Console.WriteLine("Global myString = {0}", Program.myString);

} Now run this program and the output will be like this:

Here we have added another variable called my string, this time further up the hierarchy of names is the code. This variable is defined as follows: static string myString;

All Rights Reserved To EaglesGroup

225

DENOTE: That again we require the static keyword have. Again, Im not going to say any more about this at this paint other than that in console applications of this form we must use either the static an const keyword for global variables of this form. It we want to modify the value of the global variable we need to use static, as const prohibits the value of the variable changing. In order to different between this variable and the local variables in main ( ) and write ( ) with the same name, we have to classify the variables name using a fully qualified name, as introduced in last 2 chart, Here we refer to the global version as Program. myString. Note that this is only necessary when we have global and local variables with the same name, if there was no local my string variable, we could simply use my string to refer to the global variable, rather than Program.myString. When we have a local variable is said to be hidden. The value of the global variable is set in Main ( ) with! Program.myString = "Global string";

And accessed in write ( ) with! Console.WriteLine("Local myString = {0}", myString); Console.WriteLine("Global myString = {0}", Program.myString);

Now you may be wondering why we shouldnt just uses this techniques to exchange data with functions rather than the parameter passing we saw earliest; there are indeed situations where this is the preferable way to exchange data, but there are just as many if not more where it isnt.

226

All Rights Reserved To EaglesGroup

5.5.2 Variable scope in other structures


Before we move on, it is worth nothing that one of the paints made in the last section has consequences above beyond Variable scope between functions. I stated that the scope of variables encompasses the code block that they are defined in any directly nested code blocks. This also applies to other code blocks, such as those in branching and looping structures. Consider the following code: int i? for (i = o; i 10 ; i ++) { String text = Line it convert. To string (i); Console. Write Line ({o}, text); } Console, write Line (Lat there out put in loop! {o} , text); Here the string variable text is local to the for loop. This code wont compile, as the call to Console.WriteLine ( ) that occurs outside of this loop attempts to use the variable text, which is out of scope outside scope outside of the loop. Try modifying the code as follows; int. i; String text; For (i = o; convert. To string (i); { text = Line ( {o} text); } Console, write line (Last text output in loop; { o}, text );

All Rights Reserved To EaglesGroup

227

This code will also fail. The reason for this is that variables must be declared and be initialized before use, and text is only animalized in the for loop. The value assigned to text is lost when the loop block is exited. However we can also make the following change:int. i; String text = , For (i = o; i 10; i ++) { text = Line + convert, To string (i); Console write Line (Last text output in loop; {o}, text);

This time text initialized outside of the loop, and we have access to its value. The result of this simple code is shown in the following screen short:-

For the above program in the CD Refer the Following Path: \\EaglesVisualCSharp\Chapter 5 Function\Example Using Defining and using a basic Function\ EaglesGroupText Here the last value assigned to text in the loop is accessible from outside t he loop.

228

All Rights Reserved To EaglesGroup

As you can see, this tonic require a bit of wore to get grins with. It is not immediately obvious why in the light of the earlier example, text, doesnt retain the empty string it is assigned before the loop in the code after the loop. The explanation for this behaviors concerns the memory allocation for the text variable, and indeed and variable. Simply declaring a simple variable type doesnt result in very much happening. It is only when values are assigned to the variable that values are allocated a place in memory to be stored. When this allocation takes place inside a loop, the value is essentially defined, as a local value, and goes out of scope outside of the loop. Even though the variable itself is not localized to the loop, the value it contains is. However, assigning a value outside of the loop ensures that the value is local to the main code, and is still in scope inside the loop. This means that the variable doesnt goose of scope before the main code block is existed. So we have access to its value outside of the loop. Luckily for us, the c compiles, will detect variable scope problems, and responding to the error messages it generator certainly helps us to understand the tonic of variable scope. As a final note, we should turn to best practice In general; it is worth declaring and initialing all variables before using them in any code blocks. An exaction to this is where we declare looping variables as part of a loop block example. For (int. i = o; 10; i++ ) { }

Here is localized to the looping code block, but this is fire as we will rarely require access to this counter from external code.

All Rights Reserved To EaglesGroup

229

5.6 Parameters and Return values versus Global Data


In this section, well take a closes look at exchanging data with functions via global data and via parameters and return values. To recap, considers the following code:class Siddhu { static void showDouble(ref int val) { val *= 2; Console.WriteLine("val doubled = {0}", val); } static void Main(string[] args) { int val = 5; Console.WriteLine("val = {0}", val); showDouble(ref val); Console.WriteLine("val = {0}", val); } } DENOTE: That this code is slightly different to the code we *** earlier in this chapter, where we used the variable name my number in main ( ). This illustrates the fact that local variables can have identical names and vet not interface with each other. It also means that the two code samples shown here are more similar, allowing us to focus more an the specific differences without worrying of above variables names.

230

All Rights Reserved To EaglesGroup

And compare it with this code:class Program { static int val;

static void showDouble () { val *= 2; Console.WriteLine ("val doubled = {0}", val ); } static void Main(string[] args) { val = 5; Console.WriteLine("val = {0}", val); showDouble(); Console.WriteLine("val = {0}", val); } The result of the above both program showDouble () function is same and the screen shot as follows:

All Rights Reserved To EaglesGroup

231

Now, there are no hard and fast rules for using one method rather than another, and both techniques are perfectly valid. However there are some guideline you might like to consider. To start with, as to mentioned when we first introduced this tonic, He show Double ( ) version that uses the global value will only use the global variable val, In order to use t his version, we must use this global variable. This limits the versatility of the function slightly, and means that we must continuously copy the global variable value into other variables if we intend on storing results, In addition, global data might be modified by code elsewhere in our application, which could cause unpredicted results (Values might change without us realizing until too late) Finally, it should be remembered that using global data isnt always possible. Later on in the boo,, we will see code writer in different files and / or belonging to difficult namespace communicating with each other via functions. In such case this. He code is often separated to such a degree that there is no obvious choice for a global storage location. So, to summarize, feel free to use either technique to exchange data. I would in general, urge, you to use parameters rather than global data, but there are certainly cases where global data might be more suitable, and it certainly isnt an error to use this technique.

5.7 The main ( ) function


Now weve covered most of the simple techniques used in the creation and use of functions, lets go back and take a closes look at the main ( ) function. Earlier on, we said that main ( ) is the entry paint for a c application and that of the execution. We also saw this function has a parameter, string [ ] but we havent as yet seen what this parameter represents. In this section well see what this parameter is, and how we use it.

232

All Rights Reserved To EaglesGroup

DENOTE: That there are four possible signatures that we can use for the main ( ) Function, static void Main ( ) static void main (string [ ] orgs) static int main ( ) static int main (String [ ] orgs) We can, if we wish, omit the args argument discussed her. The reason weve used the version with this argument up till now, is that it is the version that is generated automatically for us when we create a console application in visual studio (VS) The may well have come across command line parameters already. When we execute an application from the command Line we are often able to specify information directly such as a file to load an application execution. As an example, consider the notepad application in windows. We can run this application simply by ***** Notepad in a command prompt window, on in the window that appears when we select the run option from the windows start menu. We can also type something like notepad my file.txt in there locations. The result of this is that notepad will load the file myfile.text when it runs, us or offer to create this file if it doesnt already exist. Here, myfile.txt is a command line argument. We can unite console application that worm in much the same way by making use of the args parameter. When a console application is executed any command line parameters that are specified are placed in this args array. We can then use these parameters in our application as required. Lets work it out Using Command Line Arguments

Example 5-5 Using Command Line Arguments Example Try it out Eagles CommandArguments

Step by Step Example: Using Version 2005

All Rights Reserved To EaglesGroup

233

1. Create a new Console Application and name it as Eagles CommandArguments in the directory C:\EaglesVisualCSharp\Chapter 5 Function\Example Using Command Line Arguments 2. Add the following code in the Program.cs as follows:

namespace Eagles_CommandArguments { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { static void Main(string[] args) { Console.WriteLine("{0}command line arguments were specified;", args.Length); foreach (string arg in args) Console.WriteLine(arg); } } 3. When you run the Program it will have the output like this:

234

All Rights Reserved To EaglesGroup

But this is not the output we are excepting 4. Now open the property page of the Eagles CommandArguments in the Solution Explorer window and select Properties. 5. Select the Configuration Properties | Debugging and add what ever command line argument you want to the Command Line Argument setting as shown in the below screen shot:

6. Run the application and you will get the output as shown in the above command prompt Now lets see how the above program works: The code used here is very simple Console.WriteLine("{0}command line arguments were specified;", args.Length); foreach (string arg in args) Console.WriteLine(arg);

All Rights Reserved To EaglesGroup

235

We are just using the args parameter like we would any other string array. Were not doing anything ferry with the arguments. Were just writing whatever is specified to the screen. In this example, we supplied the arguments via the project properties dialog in VS. This is a handy way of using the same command line arguments when ever you run the application from VS rather than having to type them at a command Line prompt every time. The same result as above could be obtained by opening a command prompt every time. The same result as above could be obtained by opening a command prompt window in the same directory as the project output. Note that each argument is separated from the next by spaces, but we can also enclose arguments this is necessary if the argument includes spaces. So as not to be interpreted as multiple arguments.

5.8 Struct Functions


In the last chapter we looked of struct types far storing multiple data elements in one place, structs are actually capable of a lot more than this one important extra capability they often is the ability to contain functions as well as data. This is something that may seem a little strange at first, but is in fart very useful indeed. As a simple example, consider the following struct. Struct customer Name { Public string first Name, Last Name } If we have variables of type customer Name, and we want to output a full name to the console, we are forced to build the name from its component parts, we might use the following syntax for a customer Name variable called my customer, for example:-

236

All Rights Reserved To EaglesGroup

customer Name my customer my customer, First Name = Siddhu my customer, last Name = Eagle console. write line ({ o } { 1 }, my customer, First Name, my customer, last Name); By adding function to structs, we can simplify this by centralizing the processing of common tasks such as this; we can add a suitable function to the struct type as follows: struct customer Name { Public string firstName, lastName { return first Name + + Last Name; } }

This looks much like any other function weve looked at in this chapter, expert that we havent used the static modifies. The reasons for this will become clear later in this book, for now it is enough to know that this keyword isnt required for struct functions. We can use this function as follows. Customer Name my customer my customer, first Name = Siddhu; my customer, Last Name = eagle Console Write Line (my customer, Name )

This syntax is much simples, and much easier to understand, than the earlier one.

All Rights Reserved To EaglesGroup

237

An important paint to note here is that the name ( ) function has direct access to the first Name and last Name struct members. Within the customer Name struct they can be thought of as global.

238

All Rights Reserved To EaglesGroup

5.9 Over loading Functions


Earlier on in this chapter, we saw how we must match the signature of a function when we call it. This implied that we would need to have separate functions to operate on different types of variable. Function overloading provides VS with the ability to create multiple functions with the same name, but each working with different parameter types. For example, we used the following code earlier that contained a function called Max Value ( );

class Program { static int MaxValue(int[] intArray) { int maxVal = intArray[0]; for (int i = 1; i < intArray.Length; i++) { if (intArray[i] > maxVal) maxVal = intArray[i]; } return maxVal; } static void Main(string[] args) { int[] myArray = { 1, 8, 3, 6, 2, 5, 9, 3, 0, 2 }; int maxVal = MaxValue(myArray); Console.WriteLine ("The maxium value in myArray is{0}", myVal); }

This function can only be used with arrays of int values. Now, we could provide different parameter types, perhaps renaming the above function such as Double Array Max value ( ) to work with other types. Alternatively, we could just add the

All Rights Reserved To EaglesGroup

239

class Program { static double MaxValue(double[] doubleArray) { double maxVal = doubleArray[0]; for (int i = 1; i < doubleArray.Length; i++) { if (doubleArray[i] > maxVal) maxVal = doubleArray[i]; } return maxVal; }

The different here is that we are using double values. The function name. Max Value ( ), is the same, but (crucially) its signature is different. It would be an error to define two functions with the same name and signature, but since these two functions have different signatures, this is file. The beauty of this type of code is that we dont have to explicitly specify which of these two functions we wish to use. At this point, it is worth nothing another feature of the IntelliSence feature in Visual Studio .NET. If we have two function shown above in an application, and then proceed to type the name of the function in for example Main (), Visual Studio.NET will show us the available overloads for the function. If we type the following:

Visual Studio .NET gives us information about both version of MaxValue (), which we can scroll between using the up and down arrow keys:

240

All Rights Reserved To EaglesGroup

All aspects of the function signature are included when overloading functions. We might, for example, have two different functions that take parameters by value and by reference respectively. static void showDoubwl (ref int val) { ... }

static void showDouble (int val) { ... }

The choice as to which of these versions to use is based purely on whether the function call contains the ref keyword. The Following would call the reference versions: showDouble(ref val);

And the following would cal the value versions: showDouble( val);

All Rights Reserved To EaglesGroup

241

5.10 Delegates
A Delegate is a type that enables us to store references to functions. Although this sounds quite involved, the mechanism is surprisingly simple. The most important purpose of delegates wont become clear until later in this book when we look of event and even handling, but we can get a fair amount of mileage by looking at delegates her. When we come to use them later on theyll look familiar, which will make some more complicated topics a lot easier to comprehend. Delegates are declared much like functions, but with no function body and using the delegate key word. The delegate declaration sacrifices a function signature consisting of a return type and the parameter list. After defining a delegate we can declare a variable with the type of the delegate. We can than initialize this variable tope a reference to any function that has the same signature as that delegate, once we have done this we can call that function by using the delegate variable as if is were a function. We have a variable that refers to a function we can also perform other operations that would be impossible by other means, for example, we can pass a delegate variable to a function as a parameter, then that function can use the delegate to call whatever function it refer, to without having knowledge, as to what function will be called until runtime. Lets have an example. Lets work it out Using a Delegate to Call a Function

Example 5-6 Using a Delegate to Call a Function Example Try it out Eagles DelegateFunction

Step by Step Example: Using Version 2005


1. Create a new Console Application and name it as Eagles DelegateFunction in the directory C:\EaglesVisualCSharp\Chapter 5 Function\Example Using a Delegate to Call a Function 2. Add the following code to Program.cs as follows:

242

All Rights Reserved To EaglesGroup

namespace Eagles_DelegateFunction { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { delegate double processDelegate(double param1, double param2); static double Muiltiply(double param1, double param2) { return param1 * param2; } static double Divide(double param1, double param2) { return param1 / param2; } static void Main(string[] args) { processDelegate process; Console.WriteLine("Enter 2 number seperated with a comma:"); string input = Console.ReadLine(); int commaPos = input.IndexOf(','); double param1 = Convert.ToDouble(input.Substring(0, commaPos)); double param2 = Convert.ToDouble(input.Substring(commaPos + 1, input.Length - commaPos - 1)); Console.WriteLine("Enter M to mui;ltiply or D to divide:"); input = Console.ReadLine(); if (input == "M") process = new processDelegate(Muiltiply); else process = new processDelegate(Divide); Console.WriteLine("Result:{0}", process(param1, param2)); }

All Rights Reserved To EaglesGroup

243

3. Now Execute the code and you will have the output like this:

Now lets see how the above code works: This code defines a delegate (Process Delegate) whose signature matches that of the two functions (multiply ( ) and Divide ( )). The delegate designation as follows:delegate double processDelegate(double param1, double param2);

The delegate keyword specifies that the definition is for a delegate, rather than a function the definition appears in the same place as a function definition might Next, we have a signature that specifies a double return value and, two double parameter. The actual names used are arbitrary, so we can call the delegate type and parameter name whatever we like, here, weve used a delegate name of process Delegate and double parameters called param1 and param 2. The code in main ( ) stars by declaring a variable using our new delegate type:static void Main(string[] args) { processDelegate process;

244

All Rights Reserved To EaglesGroup

Next, we have some fairly standard C code that requests two numbers separated by a comma and places these numbers in two double variables:Console.WriteLine("Enter 2 number seperated with a comma:"); string input = Console.ReadLine(); int commaPos = input.IndexOf(','); double param1 = Convert.ToDouble(input.Substring(0, commaPos)); double param2 = Convert.ToDouble(input.Substring(commaPos + 1, input.Length - commaPos - 1)); Console.WriteLine("Enter M to mui;ltiply or D to divide:"); input = Console.ReadLine(); if (input == "M") process = new processDelegate(Muiltiply); else process = new processDelegate(Divide); Console.WriteLine("Result:{0}", process(param1, param2)); DENOTE: That far demonstration purposes, Ive included no user input validation here. If this were real code, wed spend much more time ensuring that we get valid in the local param 1 and Param 2 variables. Next we ask the user whether to multiply or divide these numbers:Console.WriteLine("Enter 2 number seperated with a comma:"); string input = Console.ReadLine(); Based on the user choice us initialize the process delegate variable:if (input == "M") process = new processDelegate(Muiltiply); else process = new processDelegate(Divide); Console.WriteLine("Result:{0}", process(param1, param2)); To assign a function reference to a delegate variable, we use slightly add looking syntax. Much like assigning array values, we must use the new keyword to create a new delegate.

All Rights Reserved To EaglesGroup

245

After this keywords we specify the delegate type and supply a parameter referring to function we want to use, namely the multiply ( ) or Divide ( ) function. That this parameter doesnt match the parameters of the delegate type or the target function, it is syntax unique to delegate assignment. The parameter is simply the name of the function to use, without any parentheses. Finally, we call the chosen function using the delegate. The same syntax works here, regardless of which function the delegate refers to. Console.WriteLine("Result:{0}", process(param1, param2));

Here, we treat the delegate variable just as if it were a function name. Unlike function, however, we can also perform additional operations on this variable, Such as passing it to a function via a parameter. A simple example of such a function might be:Static void execute Function (process Delegate Process) { Process (2.2, 3.3); }

This means that we can control the behavior of functions by passing them function delegates, much like choosing a Snap-in to use. Fro example, we might have a function that sorts a string array alphabetically. There are several methods of sorting lists with varying performance depending on the characteristics of the list being sorted. By using delegates, we could specify the method to use by passing a sorting algorithm function delegate to a sorting function. There are many such uses for delegates, but as mentioned earlier, their most prolific use is in event handling. Well come to this subject late we will discuss.

246

All Rights Reserved To EaglesGroup

Summary: In this character, weve seen a fairly complete overview of the use of functions in C code. Much of the additional features that function often (delegates in particular) are more abstract, and well only need to discuss them in the light of object oriented programming, which is a subject that well be discussing very soon. To summarize what has been covered in this chapter. Define and using functions in console applications Exchanging data with functions via return values and parameters Parameter arrays Passing Values by reference or by value Specifying out parameter for additional return values. The concept of variable scope Details of the main ( ) Function, including command line parameter usage Using functions in struct types Function overloading Delegates

All Rights Reserved To EaglesGroup

247

Chapter 06

248

All Rights Reserved To EaglesGroup

Debugging and Error Handling


6.0 Introduction to Debugging and error handling
So far in this book, we have covered all the basics of simple programming in C#. Before we move on to look at object programming in the next section of the book, its time to look at debugging and error handling in C# code. Error in code is something that will always be with us. No matter how a good programmer is, there will be always be problems that slip through, and part of being good programmer is realizing that this is the case and being prepared to deal it. Of course, these may be minor problems that dont affect the execution of an application, perhaps a spelling mistake on a button or such like; they may also be glaring error that causes applications to fail completely fatal errors. Fatal errors include both simple errors in code that will prevent compilation syntax errors, but may be more involved and only occur at runtime. Alternatively, errors may be subtler. Perhaps your application will fail to add a record to a database if a request field is missing, or adds a record with the wrong data in other restricted circumstances. Errors such as these, where application logic is in some way flawed, are know as semantic error also know as logic errors. Often the first that you might hear about the more slight errors will be when a user of your application complains that something isnt working properly. This the leaves you with the task of tracing through your code to try to find out what is happening, and how you can change your code so that it does what it was intended to do. In situations like this, you will find that the debugging capabilities of Visual Studio .NET are fantastic help. In the first part of this chapter. Well look at some of the techniques on offer and apply them to some of the techniques on offer and apply them to some common problems. In addition to this, we will also look at the error handling techniques available in C#. these enables us to take precaution in cases where error are likely, and write code that is resilient enough to cope with errors that might otherwise be fatal. These techniques are part of the C# language rather then a debugging feature of Visual Stuido.NET does provide some tools to help us here to too. Really Thanks to Microsoft Corporation to give the Visual Stuido.NET and also the built in technology Error handling.

All Rights Reserved To EaglesGroup

249

6.1 Debugging in Visual Studio


When programs are run in debug mode, there is more going on that simply the code you have written being executed? Debug builds maintain symbolic information about your application, such that Visual Studio is capable of knowing exactly what is happening as each line of code is executed. Symbolic information means keeping track, of for example, the names of variables used in uncompelled code, such that they can be matched up to the values that exist in the complied machine code application, which you may have seen appearing in debug directories on your computer. This enables us to perform many useful operations, which include the following: Outputting debugging information to Visual Studio .NET Looking at the values of variables in scope during application execution Pausing and restarting program execution Automatically halting execution at certain point in the code Stepping through program execution a line at a timer Monitoring change in variable content during application execution Modifying variables content at runtime Performing test calls of functions

In this section, well take a look at these techniques and how we can use them to identify and fix those areas of code which do not work as expected, a process more commonly know as debugging. Well divide up the techniques into two sections by the way in which they are used. In general, debugging is performed either by interrupting program execution or by making notes for later analysis. In Visual Studio.NET terms, an application is either running or is in break mode, that is normal execution is halted. Well look at the non break mode runtime or normal technique first.

6.2 Debugging in Non- Break normal mode


One of the commands weve being using throughout this book is the Console.WriteLine () and also the System.Console.WriteLine () function that outputs text to the console. When we are developing the console application this function can come in handy for getting extra feedback operations, for example: Console.WriteLine(Eagles() Function about to be called..); Eagles(Welcome to EaglesGroup!); Console.WriteLine(Eagles() Function execution completed.);

250

All Rights Reserved To EaglesGroup

The above code snippet shows how we can give extra information concerning a function called Eagles (). Doing this is all very well, but can make console output a bit cluttered. Ad an alternative, we can output text to a separate location the Output window in Visual Studio.NET Back in the Chapter 1 we took a quick look at the Output window, which is by default located at the bottom of the Visual Studio environment, sharing space with the Task List window, we saw how this window displays information relating to the compilation and execution of code, including errors encountered during compilation and so forth... We can also use this window to display custom diagnostic information by writing to it directly. We can see this window in the screen shot below:

DENOTE: That the above window in the output has three modes that can be selected using the drop down it contains. We can toggle between Build, Debug, and Test Run mode. The Build and Debug mode show us compilation and run time information respectively.

All Rights Reserved To EaglesGroup

251

Alternatively, we might want to create a logging file, which would have information appended to it when our application is executed. The technique for doing this are much the same as for writing text to output window, although it requires an understanding of how to access the file system from C# applications. For now, well leave this function on the back, as there is plenty we can do without getting bogged down by file access techniques.

6.3 Outputting Debugging Information


Writing text to the Output window at run time is a very simple thing to de. We simply need to replace calls to Console.WriteLine () with the required call to write text where we want it. There are two commands we can use it to this they are Debug.WriteLine() Trace.WriteLine() These commands function in almost exactly the same way with one key difference. The first of these two comments only works in the debug builds, the later will work for the release builds as well. In fact, the Debug.WriteLine () command wont even be compiled into a release build; it will just disappear, which certainly has its advantage the compiled code will be smaller in size for a start. We can in effect have two versions of our application created from a single source file. The debug version displays all kinds of extra diagnostic information whereas the release version wont have this overhead, and wont display message to users that might otherwise be annoying. These function dont work exactly like Console.WriteLine (). They only work with a single string parameter for the message to output, rather than letting us insert variables values using {x} syntax. This means that we must use the + operator to insert variables in strings. However, we can optionally supply a second string parameter, which is used to display a category for the output text. This allows us to see at a glance what output messages are displayed in the Output window, useful for when similar message are output from different places in the application. The general output of these functions is as follows: <category>:<message> For example, the following statement, this has Eagles as the optional category parameter: Debug.WriteLine (Added 1 to i:, Eagles);

252

All Rights Reserved To EaglesGroup

The result will be: Eagles: Added 1 to i

Lets work it out Writing Text to the output windows

Example 6-1 Writing Text to the output windows

Example Try it out Eagles TextOutput Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles TextOutput in the directory C:\EaglesVisualCSharp\Chapter 6\Example Writing Text to the OutPut Window\Eagles TextOutput 2. Enter the following code in the using directive: using System; using System.Collections.Generic; using System.Text; using System.Diagnostics;

3. Now enter the following code in the Program.cs : namespace Eagles_TextOutput { # region EaglesGroup Console Application /// <summary> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </summary> # endregion class Program {
All Rights Reserved To EaglesGroup

253

static void Main(string[] args) { int[] EaglesArray = { 0, 4, 2, 7, 2, 3, 1, 7, 3, 4, 3 }; int[] maxValIndices; int maxVal = Maxima(EaglesArray, out maxValIndices); Console.WriteLine("Maximum value {0} found at element indices:", maxVal); foreach (int index in maxValIndices) { Console.WriteLine(index); } }

static int Maxima(int[] integers, out int[] indices) { Debug.WriteLine("Maximum value search started."); indices = new int[1]; int maxVal = integers[0]; indices[0] = 0; int count = 1; Debug.WriteLine("Mximum value intilized to " + maxVal + " at element index 0."); for (int i = 1; i < integers.Length; i ++) { Debug.WriteLine ("Now looking at element at index "+ i + "."); if (integers [i] > maxVal )

254

All Rights Reserved To EaglesGroup

{ maxVal = integers [i]; count = 1; indices = new int [1]; Debug.WriteLine ("New maximum found. new valiues is " + maxVal + ", at elemt index" + i +"."); } else { if (integers [i] == maxVal ) { count ++; int [] oldIndices = indices ; indices = new int [count ]; oldIndices.CopyTo (indices , 0); indices [count - 1] = i; Debug.WriteLine ("Duplicate maximum foud at elemt index" + i + "."); } } } Trace.WriteLine("Maximum value:" + maxVal + "found, with " + count + "occurrences."); Debug.WriteLine("Maximum value search completed."); return maxVal; }

4. Now run the program in the debug mode and you will see the output like this:

All Rights Reserved To EaglesGroup

255

5. Now exit the application, and look at the contents in the output window while in debug mode which will created the following: 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorli b.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Uti lities\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities .dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c5 61934e089\System.Windows.Forms.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\Syste m.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3 a\System.Drawing.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Uti lities.Sync\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Ut ilities.Sync.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\EaglesVisualCSharp\Chapter 6\Example Writing Text to the OutPut All Rights Reserved To EaglesGroup 256 Window\Eagles TextOutput\Eagles TextOutput\bin\Debug\Eagles TextOutput.vshost.exe', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

The thread 0x62c has exited with code 0 (0x0). The thread 0x5f0 has exited with code 0 (0x0). 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\EaglesVisualCSharp\Chapter 6\Example Writing Text to the OutPut Window\Eagles TextOutput\Eagles TextOutput\bin\Debug\Eagles TextOutput.exe', Symbols loaded. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3 a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. Maximum value search started. Mximum value intilized to 0 at element index 0. Now looking at element at index 1. New maximum found. new valiues is 4, at elemt index1. Now looking at element at index 2. Now looking at element at index 3. New maximum found. new valiues is 7, at elemt index3. Now looking at element at index 4. Now looking at element at index 5. Now looking at element at index 6. Now looking at element at index 7. Duplicate maximum foud at elemt index7. Now looking at element at index 8. Now looking at element at index 9. Now looking at element at index 10. Maximum value:7found, with 2occurrences. Maximum value search completed. The thread 0xd74 has exited with code 0 (0x0). The thread 0xd80 has exited with code 0 (0x0). The program '[1900] Eagles TextOutput.vshost.exe: Managed' has exited with code 0 (0x0).

All Rights Reserved To EaglesGroup

257

6. Now Change to Release mode using the drop down menu on the Standard toolbar:

7. Now again run the program but this time you r running it in the Release mode, and take a another look at the output window when the program is executed: Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\msc orlib.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess. Utilities\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess. Utilities.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a 5c561934e089\System.Windows.Forms.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\Sy stem.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d5 0a3a\System.Drawing.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

258

All Rights Reserved To EaglesGroup

'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities.Sy nc\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\EaglesVisualCSharp\Chapter 6\Example Writing Text to the OutPut Window\Eagles TextOutput\Eagles TextOutput\bin\Release\Eagles TextOutput.vshost.exe', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Dat a.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089\System. Xml.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. The thread 0xe04 has exited with code 0 (0x0). 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\EaglesVisualCSharp\Chapter 6\Example Writing Text to the OutPut Window\Eagles TextOutput\Eagles TextOutput\bin\Release\Eagles TextOutput.exe', Symbols loaded. 'Eagles TextOutput.vshost.exe' (Managed): Loaded 'D:\WINDOWS\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\ System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. Maximum value:7found, with 2occurrences. The thread 0x990 has exited with code 0 (0x0). The thread 0x9fc has exited with code 0 (0x0). The program '[1800] Eagles TextOutput.vshost.exe: Managed' has exited with code 0 (0x0).

All Rights Reserved To EaglesGroup

259

Now lets see how the above code works and what happen out there lets see now:

This Program return an array of the indices where maximum values are found in an array, so that the calling code can be manipulated these elements The additional using directive appears at the start of the code it because it simplifies access to the functions discussed above this example, as they are contained in the Sys using System; using System.Collections.Generic; using System.Text; using System.Diagnostics;

Without the above highlighted using directive, we would not be able to code such as: Debug.WriteLine("Maximum value search started.");

Even we can rewrite the following code as follows: System.Diagnostics.Debug.WriteLine("Maximum vale search stated");

The using directive keeps our code simple and reduces verbosity. The code in the Main () simply initializes a test array of integers called EaglesArray; it also declares another integer array called maxValIndices to store the index output of Maxima () the function that performs the calculation, then calls this function. Once the function returns, the code simply outputs the result. Maxima () is slightly more complicates, but doesnt use much code that we havent already seen. The search through the array is performed in similar way to the MaxVal () function in the example.

260

All Rights Reserved To EaglesGroup

Perhaps the key point to note in the code other than those lines that output debugging information is the function used to keep track of the indices. Rather then returning an array that would be large enough to store every index in the source array needing the same dimensions as the source array, Maxima () returns an array just large enough to hold the indices found. It foes this by continually recreating arrays of different sizes as the search progresses. This is necessary as array cant be resized once it has been created. To start with, the search is initialized by assuming that the first element in the source array called integers locally is the maximum value, and that there is only one maximum value in the array. Values can, therefore be set the for maxVal the return value of the function, and the maximum values found and indices, the out parameters array that stores the indices is assigned a single value, simply 0, which is the index of the first element in the array. We also store the number of maximum values found in a variable called count, which allows the program to keep track of the indices array. The main body of the function is a loop that cycle thought the values in the integer array, omitting the first one as this has already been processed. Each value is compared to the current value of maxVal, and ignored if maxVal is greater. If the currently inspected array value is greater then maxVal then maxVal and indices are changed to reflect this. If the value is equal to maxVal then count is incremented and a new array is substituted for indices. This new array is one element bigger than the old indices array, contain the new index found. f (integers [i] > maxVal ) { maxVal = integers [i]; count = 1; indices = new int [1]; Debug.WriteLine ("New maximum found. new valiues is " + maxVal + ", at elemt index" + i +"."); } Through out the code, various pieces of text are output using the Debug.WriteLine () and Trace.WiteLine () functions. The end result of this when running in the debug mode is a completer recode of the steps taken in the loop that give us our result. In release mode, we just see the end result of the calculation as no Debug.WriteLine () functions work. But the old indices array into oldIndices it is because of backing up the ole indices, an integer array local to this if code block, that the value is oldIndices are copied into the new indices array using the oldIndices.CopyTo (indices , 0); . this Function simply takes a target array and index to use for the first element to copy to, and pastes all the values into the target array.

All Rights Reserved To EaglesGroup

261

As well as these WriteLine () functions there are few more we should be aware of it. To start with, these are equlavent to Console.Write (); Debug. Write(); Trace.Write(); Both these functions use the same syntax as the WriteLine () function one or two parameters, with a message and a optional category, but differ in that they dont add end of line characters. These are also the following commands: Debug. WriteLineIF() Trace. WriteLineIF() Debug. WriteIf() Trace. WriteIf()

6.4 Debugging in the Break Mode


The rest of the debugging techniques well look at in this following section in the break mode. This mode can be entered in several ways, all of which result in the program pausing in some way. The first thing we will look at in the section is how we go about this, and then well look at what we can achieve once break mode is entered.

6.5 Entering Break Mode


The simplest way of entering break mode is to hit the pause button in Visual Studio.NET while an application is running. The same thing goes to us also when we have the key we can enter our house gently without break the door or something. The pausing button is found on the Debug toolbar, which we should add to toolbars that appears by default in the Visual Studio. NET to this just right click in the toolbar area and select the Debug toolbar as in the below picture:

262

All Rights Reserved To EaglesGroup

The toolbar after you select it should look like this:

The first four buttons on this toolbar allow manual control of the breaking. In the above screenshot, the three of these grayed out and disabled buttons as they wont work with a program that isnt currently being executed. The one that is enabled, Start is identical to the button that exists on the standard toolbar. In the following sections well look at the rest of the buttons when needed. When an application is running, the toolbar might change and look likes the following screenshot:

Now the three buttons that were grayed in the before picture are enabled in the above picture and let us do the following thing:

All Rights Reserved To EaglesGroup

263

Pause the application and enter break mode Stop the application completely this doesnt enter break mode, it just quit Restart the application Pausing the application is perhaps the simplest way of entering break mode, but it doesnt give us fine granted control over exactly where to stop, we are likely to stop in a natural pause in the application, perhaps where we request user input. We might also be able to enter break mode during a lengthy operation, or a long loop, by the exact point we stop is likely be fairly random. But in general, it is far better to use the break points.

6.6 Breakpoints
A breakpoint is a marker to the source code that triggers automatic entry into break mode. They may be configured to: Enter break mode immediately when the breakpoint is reached Enter break mode when the breakpoint is reached if a Boolean expression evaluates to true Enter break mode once the breakpoint is reached a set number of times. Enter break mode once the breakpoint is reached and a variable value has changed since the last time the breakpoint was reached DENOTE: That the above points available in the debug builds. If you compile a release build then all breakpoints will be ignored. There are three ways to adding breakpoints. To add simple breakpoints that break when a line is reached we simply left click on the gray area to the left of the line code, or right click on the line, and select the Insert BreakPoint menu option:

264

All Rights Reserved To EaglesGroup

The break point will appear as a red circle next to the line of code, and highlight on the line of the code as you can see in the following screenshot:

We can also see information about the breakpoints in a file using the BreakPoints window. We need to enable this window first, by selecting the Debug | Windows | BreakPoints menu option or you press the Ctrl + D, B. The following windows will then appear at the bottom of the screen, in the same place as the TaskList and the Output window.

All Rights Reserved To EaglesGroup

265

Here, we can disable breakpoints by removing the tick to the left of a description a disabled breakpoint shows up as an unfilled red circle, delete breakpoints and edit the properties of breakpoints.

The properties shows in the window, Condition and Hit Count, are only two of the available ones, but they are most useful. We can edit these by right clicking on breakpoints in code or in this window, and selecting the Properties menu option. We can then use the three tabs, Function, File, and Address, to change the location of the breakpoint Address lets us specify an absolute memory address for a breakpoint, an involved subject that we are not seeing it now , and the Condition .. And the Hit Count.. buttons to change the two properties mentioned above. Selecting the Condition button pops up the following dialog as shown in the following screenshot:

266

All Rights Reserved To EaglesGroup

Here, we can type any Boolean Expression, which may involve any variables that are in scope at the breakpoint. The following screenshot show as breakpoint that will trigger when it is reached and the value of maxVal is greater than 4. We can also check to see it this expression has changed, and only trigger the breakpoint then in the below case, we might trigger the maxVal had changed from 2 to 6 between breakpoint encounters

All Rights Reserved To EaglesGroup

267

Selecting the hit Count Button pops up the following dialog as you can see in the following screenshot:

268

All Rights Reserved To EaglesGroup

In the above screenshot by default the Breakpoint Hit Count will be say break always but we change it to the following:

Hence we can specify how times a breakpoint may need to be hit before it is triggered. The drop down list offers the following options:

The option chose, combined with the value entered in the text box to the list, determines the behavior of the breakpoint.

All Rights Reserved To EaglesGroup

269

This hit the count is useful in long loops, when we might want to break after, say, the first 5000 cycles. It would be a pain to break and restart 5000 times it we couldnt do this!.

6.7 Other ways of Entering Break Mode


There are two additional ways to get into break mode. One is to choose to enter it when an unhandled exception is thrown. This subject is covered in the chapter but later, when we look at error handling. The other way is to break when an assertion is generated. Assertions are instructions that can interrupt application execution with a user defined message. They are often used in the development of an application as a means to test that things are going smoothly. For example, we might at some point in our application require a given variable to have a value less then 10. We can use an assertion to check that this is true, and interrupt the program if this isnt the case. When the assertion occurs we have the option to abort, which will terminate the application; retry, causing break mode to be entered; or Ignore and the application will continue as normal. As with the debug output functions we saw earlier, there are two version of the assertion function they are as follows:

Debug.Assert(); Trace.Assert();

Again, the debug version will only be compiled into debug build. These functions take three parameters. The first is a Boolean value, where a value of false will cause the assertion to trigger. The second and third are two string parameters to write information both to pop up dialog and the Output window. The above example would need a function call such as: Debug.Assert(maxVal < 10, "MyVar is 10 or greater,", "Assertion occured in Main ().");

270

All Rights Reserved To EaglesGroup

6.8 Monitoring Variable Content


Monitoring variable content is just one example of an area where Visual Studio.NET helps us a great deal by making thins simple. The easiest way to checking the value of a variable is to hover the mouse over its name in the source code while in break mode. A yellow tooltip showing the information about the variable will appear, including the current value of the variable. We can also highlight whole expressions to get information about their result in the same way. This technique is limited however, and wont for example show us the contents of an array. Now, you many have see that when we run an application thought Visual Studio.NET the layout of the various windows in the environment changes. By the default, the following will occurred at the runtime: The properties window disappears A running Documents tab is added to the Solution Explorer window, showing us what documents in the project are in use, if any The size of the output window changes, as half the bottom of the screen is replaced by a new window. The new window that appears is a particularly useful one for the debugging. It allows us to keep tabs on the values of variables in our application when in break mode. It has three tabs, which have the following uses: Autos Variables in use in the current and previous statement Locals All variables in scope Watch N Customizable variable and expression displays (where N is 1 to 4) The new screen layout can be seen in the screenshot below:

All Rights Reserved To EaglesGroup

271

All these windows works in more or less the same way, with various additional features depending on their specification function. In general, each window will contain a list of variables, with information on variables name, value, and type. More complex variables, such as arrays, may be further intergraded using the and the tree expansion / constriction symbols to the left of their names, allowing a tree view of their content for example, this is display obtained by placing a break point in the code for the earlier example, just after the call to Maxima (); Here, Ive expanded the view for one of the array variables, maxValIndices. We can also edit the content of variables from this view. This effectively bypasses any other variable assignment that might have happened in earlier code. To do this, we simply type a new value into the Value column for the variable we want to edit. We might do this to try out some scenarios that might otherwise require code changes, for example: The Watch windows, of which there may be up to 4, allow us to monitor specific variables or expressions involving specific variables. To use this window, we simply type the name of a variable or expression into the Name column and observe the results. Note that not all variables in an application will be in scope all the time, and will be labeled as such in a Watch window. For example, the following screenshot shows a Watch window with a few sample variables and expressions in it. Again, the code from the last example is used here, paused in the execution of the Maxima () function.

272

All Rights Reserved To EaglesGroup

The EaglesArray array is local to Main (), so we dont see a value here, instead, we get message information us that variable isnt in scope. We can also add variables to watch window by dragging them from the source code into the window. To add more windows, we can use the Debug | Windows | Watch | Watch N menu to toggle the four possible windows on or off. Each window may contain an individual set fo watches on variables and expressions, so we can group related variables together for easy access. As well as these watch windows, there is also a Quick Watch window that can give us detailed information about variables in the source code quickly. To use this, we simply right click on the variable we want to interrogated and select the QuickWatch menu option. In most cases, though, it is just as easy to use the standard windows. An important point to note about watches is that they are maintained between application executions. If we terminate an application then re- run it we dont have to add watches again - Visual Studio.NET will remember what we were looking at this time.

6.9 Stepping Through Code


So, far weve seen how to discover what is going on in our application at the point where break mode is entered. Next we will look at how we can use Visual Studio to step through code while remaining in break mode, allowing us to see exactly the results of the code being executed. This is an extremely valuable technique for those of us who cant think as fast as computer can.

All Rights Reserved To EaglesGroup

273

When break mode is entered, a cursor appears to the left of the code view which may initially appear inside the red circle of a breakpoint if a breakpoint has been used to enter mode, by the line of code that is about to be executed.

This shows us that what point execution has reached when break mode is entered. At this point, we can choose to have execution processed on a line by line basics. To do this, we use some more of the Debug toolbar buttons we saw earlier:

The sixth, seventh, and eight icons control program flow in break mode. In order, they are: Step into execute and move to the next statement to execute Step Over as above, but wont entered nested blocks of code Step Out run to end of code block, and resume break mode at the statement that follows:

274

All Rights Reserved To EaglesGroup

If we want to look at every single operation carried out by the application then we can use Step into to follow the instructions sequentially. This includes moving inside functions, such as Maxima () in the above example. Clicking on this icon when the cursor reaches line 28, the call to Maxima (), will result in the cursor moving to the first line inside the Maxima () function. Alternatively, clicking on Step Over when we reach the line 28, will move the cursor straight to line 29, without having to go through the code in Maxima () although this code is still executed. If we do step into a function that we arent interested in we can hit Step Out to return to the code that called the function.

6.10 Immediate Commands


The command Window has two modes they are Command and Immediate. Command mode allows us to perform Visual Studio operations manually such as menu and toolbar operations and Immediate mode allows to execute additional code in addition to the source lines being executed and to evaluate expressions. In command mode the window contains a right angle bracket (>) symbol at the start of the each line. We can swap to immediate mode by typing immed in this window and hitting return, and back by typing >cmd and hit enter button Now we see on the immediate mode here, as the Command mode is only really useful foe compiles operations The simplest use if this window is simply to evaluate expressions, a bit like a one shot use of the Watch window. To this, we simply type an expression and hit return. The information requested will then be displayed. For example lets see the following screenshot: DENOTE: The introduction of this Immediate commands has been given in the first chapter of this book.

All Rights Reserved To EaglesGroup

275

We can change variables content here, for example:

In most cases, we can get the effects we want more easily using the variable monitoring windows we saw earlier, but this technique can still be handy for tweaking values, and is good for testing expressions where we are unlikely to be interested in the results at a later data:

6.11 The Call Stack Window


The final window well look at here shows us the way in which the current location was reached. In simple terms, this means showing the current function along with the function that called it, function that called that and so on that is a list of nested function calls. The exact points where calls are made are also recorded. In our earlier example, entering break point mode when in Maxima (), or moving into this function using code stepping, reveals the following:

The above window is particular useful when errors are first detected, as they allow us to see what has happened immediately before the error. Where the error occurs in commonly used functions, this will help us to see the source of the error:

276

All Rights Reserved To EaglesGroup

DENOTE: That sometimes this window will show very confusing information, for me a lot time it is, for example, errors occur outside of our application due to using external functions in the wrong way. At times like this, there could be a long list of entries in this window, but only one or two look similar.

6.12 Error Handling


The first past of this chapter has deal with finding and correcting the errors during the application development so that they wont occur in release level code. There are time, however, when we know that error are likely to occur and there is no way of being 100% sure that they wont. In these situation it may be preferable to anticipate problems and write code that is robust enough to deal with these error gracefully, without interrupting execution. Error handling is the name for all techniques of this nature, and here well look at exceptions and how we can deal with them.

6.13 Exceptions
An exception is an error generated either in our code or in a function called by out code that occurs at runtime. The definition of error here is vaguer that to has been up until now, as exception may be generated manually in functions and so on. For example. We might generated an exception in a function if one of its string parameters doesnt start with the letter a this isnt strictly specking an error outside of the context of this function, although it is treated as one by the code that calls the function. Weve come across the exceptions a few times already in this book. Perhaps the simplest example is attempting to address an array element that is out of range, for example: int [] EaglesArray = {1,2,3,4}; int EaglesElem = EaglesArray[4]; This is generated the following exception message, and then terminate the application:

All Rights Reserved To EaglesGroup

277

System.IndexOutOfRangeException was unhandled Message: Index was outside the bounds of the array. Exceptions are defined in namespaces and most have names that make it clear what they are intended for. In this example, the exception generated is called System.IndexOutOfRangeException, which makes sense as we have supplied an index that is not in the range of the indices permissible in EaglesArray[]. This message only appears and the application only terminates when the exception is unhandled. So what exactly we can do to handle this exception lets look in more details this in trycatchfinally

6.13 TRY..CATCHFINALLY
The C# language includes syntax for Structured Exception handling which is known as (SHE). Keywords exist to mark code out as being able to handle exceptions, along with instructions as to what to do if an exception occurs. The three keywords we use for this are try, catch, and finally. Each of these has associated code block, and must be used in the consecutive lines of code. I by myself preferred to use this method in the lot of projects and programs which is easier to reduce the burden .The basic structure is follows:

278

All Rights Reserved To EaglesGroup

try { ... } catch (System.IndexOutOfRangeException siddhu) { } finally { .. }

It is also possible, however, to have a try block and a finally block with no catch block, or try block with multiple catch blocks, if one or more catch blocks exist then the finally block is optional, else, it is mandatory.

The usage of the blocks is as follows: try Contains code that might throw exception catch Contains code to execute when exceptions are thrown. Catch blocks may be set to using System.IndexOutOfRangeException siddhu, hence the ability to provide multiple catch blocks. It is also possible to omit this parameter entirely, to get a general catch block that will respond to all exceptions. Finally contains code that is always executed, either after the try block if no exception occurs, after a catch block if an exception is handled, or just before an unhandled exception terminates the application the fact that this block is proceed at this time is the reason for its own existence, otherwise we might just as well place code after the block. The sequence of event that occurs after an exception occurs in code in a try block is as follows:

All Rights Reserved To EaglesGroup

279

The try block terminates at the point where the exception occurred If a catch block exists then a check is made to see if the block matches the type of exception that has been thrown. If no catch block exists, then the finally block which must be present if there are no catch blocks executes. If a catch block exists, but there is no match, then a check is made for other catch blocks. If a catch block matches the exception type, then the code it contains execution, and then the finally block executes if its present If no catch block match the exception the exception type the finally block of code execution if it is present. Lets work it out Writing Exception Text to the output windows

Example 6-2 Writing Exception Text to the output windows

Example Try it out Eagles ExceptionText Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles ExceptionText in the directory C:\EaglesVisualCSharp\Chapter 6\Example Writing Exception Text to the output windows 2. Enter the following code in the using directive: using System; using System.Collections.Generic; using System.Text; using System.Diagnostics;

280

All Rights Reserved To EaglesGroup

3. Add the following code to the Program.cs as follows: namespace Eagles_ExceptionText { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { static string[] eTypes = { "none", "simple", "index", "nested index" }; static void Main(string[] args) { foreach (string eType in eTypes ) { try { Console.WriteLine ("Main () try block reached."); Console.WriteLine ("ThrowException(\"{0}\") called." ,eType ); ThrowException (eType ); Console.WriteLine ("Main() try block Continues."); }

All Rights Reserved To EaglesGroup

281

catch (System.IndexOutOfRangeException siddhu) { Console.WriteLine ("Main () System.IndexOutOfRangeException catch" + " block reached. Message:\n\"{0}\"", siddhu.Message ); } catch { Console.WriteLine ("Main () general catch block reached."); } finally { Console.WriteLine ("main () finally blcok reached."); } Console.WriteLine (); } } static void ThrowException(string exceptionType) { Console.WriteLine("ThrowException(\"{0}\") reached.", exceptionType); switch (exceptionType) { case "none": Console.WriteLine("Not throwing an exception."); break; case "Simple": Console.WriteLine("Thorew System.Exception."); throw (new System.Exception()); break; case "index": Console.WriteLine("Throwing System.IndexOutOfrangeExceptioon."); eTypes[4] = "error"; break; case "nested index": try { Console.WriteLine("ThrowingException(\"nested index\") " + "try block reached."); Console.WriteLine("ThrowException(\"index\") called.");

282

All Rights Reserved To EaglesGroup

ThrowException("index"); } catch { Console.WriteLine("ThorwException(\"nested index \") general" + "catch block reached."); } finally { Console.WriteLine("ThrowExeption (\"nested index\") finally" + "block reached."); } break; } }

4. Now Run the application and you should see some thing like this:

Now lets see how the above program works: This application has a try block in the Main () that calls a function called Throw Exception (). This function may throw exception, depending on the parameter it is called with:
All Rights Reserved To EaglesGroup

283

Throw Exception (none) doesnt throe an exception Throw Exception (Simple) generates a general exception Throw Exception (index) generates a System.IndexOutOfRangeException exception Throw Exception (Index) to generate a System.IndexOutOfRangeException exception Each of these string parameters is held in the global named eTypes array, which is iterated through in the Main () function to call the Throw Exception () once with each possible parameters. During this loop various messages are written to the console to indictcate what is happening. This code gives us an excellent opportunity to use the code stepping techniques we say earlier in this chapter. By working our way through the code is a line at time you can see exactly how code execution progress; Add a new break point with the default properties to the line 27 of the code, which reads And the line 27 is in my computer. Line 27 // Console.WriteLine ("Main () try block reached.");

Now run the application in the debug mode Almost immediately, the program will enter break mode, with the cursor in line 27. if you select the Locals tab in the variables monitoring window, you should see that eType is currently none. Use the step into button to process lines 27 and 28, and how check that the first line of text has been written to the console.

Next, use the Step into button to the step into the Throw Exception () function on line 29.

Once in the Throw Exception () function on line 50, the Local window changes. eType and Args are no longer in scope they are local to Main(); instead, we see the local exception Type argument, which is of course none. Keep pressing Step into and youll reach the switch statement that checks the value of exception Type and execute the code that writes out the string not throwing an exception to be the screen.

284

All Rights Reserved To EaglesGroup

When we execute the break statement 54 we exit the function and resume processing in Main () at line 29. as no exception was thrown the try block continues. Next, processing continues with the finally block, click step into a few more times to complete the finally block and the first cycle of the foreach loop. The next time we reach the 29, ThrowException () is called using a different parameters, simple. Continue using Step Into through Throw Exception () and youll eventually reach line 57: throw (new System.Exception()); Here we use the C# throw keyword to generate an exception. This keyword simply need to be provided with a new initialized exception as a parameter, and it will throw that exception. Here we are using another exception form the System namespace, which is System.Exception. When we process this statement with the Step into we find ourselves at the general catch block starting on line 36. There was no match with the earlier catch block starting on line 32, so this one is processed instead. Stepping through this code takes us through this block, through the finally block, and back into another loop cycle that calls ThrowException () with a new parameter on line 29. This time the parameter is index. This time, ThrowException () generates an exception on line 61; eTypes[4] = "error";

The eTypes array is global, so we have access to it here, however, here we are attempting to access the 5th element in the array remember counting start at 0, which generates a System.IndexOutOfRangeException exception. This time there is a matched catch block in main (), and stepping into the code us to this block, starting at line 34. As with the earlier exception handling, we now step now through this catch block, and the associated finally block, and reach the end of the function call. However, there is no crucial difference. Although an Exception has been thrown, it has also been handled by the code in ThrowException (). This means that there is no exception left to handle in the Main (), so we go straight to the finally block, and after that the application terminates.
All Rights Reserved To EaglesGroup

285

6.13 Listing and Configuring Exceptions


The .NET Framework contains a whole host of exception types, and we are free to throw and handle any of these in our code, or even throw them form our code so that they may be caught in more complex applications. Visual Studio.NET supplies a dialog for examining and editing the available exceptions, which can be called up with the Debug | Exception menu item or pressing Ctrl + Alt + E.

Exceptions are listed by category and .NET library namespace. We can see the exception in the System.Namespace by expanding the Common Language Runtime (CLR) Exception tab, and then the System tab. This list includes the System.IndexOutOfRangeException exception we used above. Each exception may be configured using the radio button at the button of the dialog. Most are set to Use parent setting by default, which means that they use the category level option which cares all as shown in the above screenshot. We can use the first option, when the exception is thrown, to cause a break into the debugger even for exception that is handled. The second option allows us to ignore unhandled exception and suffer the consequences Inmost cases the default setting here are fine for us.

286

All Rights Reserved To EaglesGroup

Summary
This chapter has concentrated on techniques that you can use to debug you applications. There are a verity of techniques available here, moist of which are available for whatever, type of project you are creating, not just the console application. We just looked at: Using the Debug.WriteLine () Trace .WriteLine () Break mode and how to enter it, including the all-around breakpoints Debugging information windows in Visual Studio.NET Stepping through code Exception handling using the trycatch.finally

We have now concerned everything that we need to produce simple console application, along with the methods of debugging them. In the next section of this book, we will look the most powerful technique of the Object Oriented Programming.

All Rights Reserved To EaglesGroup

287

Chapter 07

288

All Rights Reserved To EaglesGroup

Object Oriented Programming


7.1 Introduction to Object Oriented Programming
At this point in this book weve covered all the basics of C# syntax and programming, and seen how to debug our application. Already we can assemble usable console application. However, to get access to the real power of the C# language and the .NET Framework we need to really make use of the Object Oriented Programming (OOP) techniques. I need to say that that only Java cant support OOP technique since when C++ programming language started to support the OOP technique, Then Java is derived from the C++ at the nature of the C++ Language, so here we are in C# that which is having the common and similar syntax to C++ and Visual C++ it is also a Pure Object Oriented Language. In actual fact, as we will soon see, weve been using these techniques already, although to keep thins simple and clear, we have not focused on this when presenting the code example but for the code example you can refer the CD which is come along with is Book, when you install the software you will automatically have a icon in the desktop name OOPs programming sample code. In this chapter we will guide away from code for a while and focus instead on the main principal behind the OOP. This will soon lead us back into the C# language, as it has a symbolic relationship with OOP. All of these concepts introduced in this chapter will be returned to in later chapter, with illustrative code so dont panic it you dont grasp everything in the first through of this material. To start with, well look at the basics of OOP, which will include answering that most fundamental of questions What is an Object?. We will quickly find that there is a lot of terminology related to OOP that can be quite confusing at first, and there will be plenty of explanation of the language used. We will also se that using OOP requires us to look at programming in a different way. As well as discussing the general principal of OOP, we will also take at one area where a through understanding of OOP is essential: in Windows Forms Application. This type of application which makes use of the Windows Environment with features such as menus, buttons, etc. provides plenty of scope for description, and we will be able to illustrate OOP points effectively in the Windows From environment. DENOTE: That the OOP as presented in this chapter is really a .NET OOP concepts, and that some of the techniques presented here dont apply to other OOP environment. Since when programming in C#, we use .NET specifies OOP, it makes good brains to make a point on these aspects

All Rights Reserved To EaglesGroup

289

7.2 Object Oriented Programming


Object oriented programming is relatively a new approach to creating computer application that seeks to address of many of the problems, with so called traditional but what I am saying is we need to creative to be an ahead for the we need to do something, for that something we need the object to in our hands, the object comes as an object oriented programming language in the computer programming language, lets say there is a word or probe before and it still remains in some places. The hackers Never sleeps and so he should be ahead of others, and they are very will in the math. But here now for me and some people and in some places, what we know is The hackers just be simple enough to bluff you because they are creative and their creative depends on the information gaining and knowledge gaining, and also they will wait for right time and the right place to the happen. And they most depend on the OOP technique is the more because they refer that OOP is more powerful that any other things event though for creating some kind of hacking tool we need to refer the OOP concept the principle.
Welcome to EaglesGroup.

The type of the programming we have seen so far is know as functional or procedural programming, often resulting in so it called monolithic applications, meaning that all functionality is contained in a few modules of code often just one. With OOP techniques we often use many more modules of code, each offering specific functionality, and where each module may be isolated or even completely in depend to other. This modular method of programming gives us much more versatility, and provides more opportunity for code reuse. To illustrate this further, imagine that a high performance application on you computer is a top of the range racing car. If written with traditional programming technique this sports car is basically a single unit. If we want to improve this car we have to replace the whole unit, by sending it back to the manufacture and getting their expert mechanics to upgrade it, to by buying a new one. If OOP technique is used then we could simply buy a new engine from the manufacture and follow their instructions to replace it over selves In more Habitual application the flow of execution is often simple and liner. Application are loaded into memory, start executing at point A, end at point B, and are then unloaded from memory. Along the way various other entities might be used, such as files on storage media, or the capabilities of generally concerned with manipulating data through various mathematical and logical means. The methods of manipulating are usually quite simple, using basic types such as integers and Boolean Values to build up more complex representations of data. With OOP things are really so liner. Although the same result is achieved, the way of getting there is often very different. OOP techniques are firmly rooted in the structure and meaning of data, and the interaction between that data and other data. This is usually means putting more effort into the design stages of a project, but has the benefit of extensibility. Once an agreement is made as to the application, and even entirely new

290

All Rights Reserved To EaglesGroup

applications. The fact that an agreement exists can reduce development time dramatically. This explain how the above racing car example works. The agreement substituted with ease, rather than requiring a trip back to the manufactures. As well as agreeing on data representations, OOP programming often simplifies things by agreeing on the structure and usage more abstract entities. For example, an agreement can be made not just on the format of data that should be used to send output to a device such as printer, but also on the methods of data exchange with that device, this would include what instructions it understands, and so on. As the name of the technology suggests, this is achieved using objects. So what is an object we will look it now.

7.3 What is an Object?


An object is a building block of an OOP application. This building block encapsulates part of the application, which may be a process, a large piece of data or a piece of cake, or some more abstract entity. In the simplest sense of an object may be very similar to as struct type such as we have seen earlier in the book, containing members of variable and function types. The variables contained make up the data stored, in the object, and the functions contained give access to the functionality of the object, slightly more complex objects might not maintain any data, instead they can represent a process by contain only functions. For example, an object representing a printer might be use, which would have function enabling control over a printer allowing you to print a document, print a test page, and so on. Object in C# are created from the types, just like the variables weve seen already. The type of an object is known by a special name in OOP, its class, we can use class definitions to instantiate object, which means to create a real, named instance of a class. The phrases instance of a class and object means the same thing here; be sure to note at this point that the classes and object mean fundamentally different things: In this chapter I have picture the classes and objects using the UML (Universal Modeling Language) syntax. UML is a language designed for modeling applications, form the objects that build them up to the operations they perform, and to the use cases that are expected. Here well only be using the basics of this language, explain these as we go along, and wont worry about the more complex aspects.

All Rights Reserved To EaglesGroup

291

The following diagram in this chapter have been create using the Microsoft Power point which is inbuilt with the Microsoft Office , but even the diagram can be created using the Microsoft Visio which is distribute with the Enterprise Architect edition of Visual Studio. The following is a UML (Universal Modeling Language) representation of out Speaker class, called Speaker:

The class name is shown in the top section of the box. The following is an UML (Universal Modeling Language) representation of an instance of this Speaker class called mySpeaker:

Here the instance name is shown first in the top section, followed by the name of its class. These two names are separated by a colon.

292

All Rights Reserved To EaglesGroup

7.4 Properties and Fields


Properties and fields provide access to the data contained in an object. This object data is what differences6 separate objects, as it is possible for different object of the same class to have different values stored in properties and fields. At this point it is worth introducing another term the various pieces of data contained in an object together make up the state of that object. Imagine an object class that represents a cup of Coffee, called CupOfCofee, when we instantiate this class that is we create an object of this calls we must provide it with state for it to be meaningful. Here we might use properties and fields to enable code using this object to set the type of coffee used, whether the coffee contains milk or sugar, whether the coffee is instant, and so on. Given coffee cups object would then have a given state, such as PanPacific filter coffee with milk and two sugars. Both fields and properties are types, so we can store information in them as string variables, as int variable, and so on. However, properties differ from fields in that they dont provide direct access to the data. Objects are capable of shields users from fields in that they dont provide which need be represented on 1:1 basis in the properties that exist. If we used a filed for the number of sugar in a CupOfCoffee instance then users could place whatever value they liked in the filed, but if we used a property then we could limit this value to, say a number between 0 and 2. In general, it is better to provide properties rather than fields for state access, as we have more control over what goes on. This choice doesnt affect that uses object instance, as the syntax for using properties and fields is the same. Read and Write access to properties may also be clearly defined by an object. Certain properties may be read only, allowing us to see what they are but not change them (like int the network sharing mostly I used to give this permission only to my client computer). This is often a useful technique for reading several pieces of state continues. We might have read only property instance of this class such as the sting given earlier when requested. We might be able to assemble the same data by interrogating several properties, but a property such as this one may save us time and effort. We might also have write only properties operating in the similar way. As well as this read and write access for properties, it also possible to specify a different sort of access permission for both fields and properties, know as accessibility. Accessibility determines what code can access this member that is whether they are available to all code public mostly, only to code within it becomes pertinent. One very common practice is to make fields private and provide access to them via public properties. This mean that code within the class can have direct access to the data stored

All Rights Reserved To EaglesGroup

293

in the field, while the public shields external users form this data and prevents them from placing invalid content here. Public members are said to expose by the class. One way of visualizing this is to equate it with variable scope. Private Fields ad properties, for example, can be thought of as local to the object that posses them, whereas the scope of public filed and properties also encompasses code external to the object. In the UML (Universal Modeling Language) representation of a class we use the second section to display properties and fields, for example lets see

This is a representation of our CupOfCoffee class, with five members: Each of the entries contains the following information: Accessibility: A = Symbol is used for a public member, a symbol is used for a private member. In general, through, I wont show private members in the diagram in this chapter, as this information is internal to the class. No information is provided as to read or to write access. The member name They type of the member A colon is used to separate the member name and type in the diagram shown in the above. .

294

All Rights Reserved To EaglesGroup

7.5 Methods
Methods are the term used to refer to functions exposed by object. These may be called in the same way as any other function, and may use return values and parameters in the same way we already looked at functions in details in the Chapter 5. Methods are use to give access to the functionality of objects. Like fields and properties they can be public or private, restricting access to external code as necessary. They will often make use of objects state to affect their operation, and have access to private members such as fields if required. For example, out CupOfCoffee class might define a method called AddSugar (), which would provide a more readable syntax for incrementing the sugar property than setting the corresponding Sugar property In the UML (Universal Modeling Language), class boxes shown methods in the third section:

The syntax here is similar to that for fields and properties, except that they type shown at the end so the return type and methods parameters are shown. Each parameter is displayed in UML, with one of the following identifiers: in, out, or in out. These are used to signify the direction of data flow, where out and in out roughly correspond to the use of the C# keywords out and ref already defines in the Chapter 5. In roughly corresponds to the C# behavior where neither of these keyword is used.

All Rights Reserved To EaglesGroup

295

7.6 Everythings an Object


At this point its time for me to come clean real clean we have been using objects. Properties and methods thought this book. In fact, everything in C# and the .NET Framework is an object!. The Main () function in a console application is a method of a class. Every variables type weve looked at is a class. Every command we have used has been a property or a method, such as <String> .Length and <String>.ToUpper () and so on. The period character here separates the object instance name from the property or method name. Objects really are everywhere, and the syntax to use them is often very simple. It has certainly been simple enough for us to consternate on some of the more fundamental aspects of C# up until now. Form here on in; well start to look at objects in more details. Bear in mind that the concepts introduced here have far reaching consequences applying event to that simple little int variable youve been happily playing around with it even me too.

7.7. The Life Cycle of an Object


Every object has a clearly defined lifecycle. A part from the normal state of being in use. This lifecycle includes two important stages: Construction When an object is first instatined it need to be initialized. This initialization is known as construction, and is carried out by a constructor function Destruction When an object is destroyed there will often be some clean up tasks to perform such as freeing up memory. This is the job of destructor function.

7.8 Constructors
Basic initialize of an object is automatic. For example, we dont have to worry about finding the memory to fit a new object into. However, there are times where we will want to perform additional tasks during an objects initialization stage. Lets say, we will often need to initialize the data stored by an object. A constructor function is what we use to do this. All objects have a default constructor, which is a parameter less method with the same name as the class itself. In addition, a class definition might include several constructor methods with parameters, know as non default constructors. These enable code that instances an object to do so in many ways, perhaps providing initial values for data stored in the object.
All Rights Reserved To EaglesGroup

296

In C#, constructors are called using the new Keyword. For example, we could instantiate a CupOfCoffee object using its default constructor in the following way: CupOfCofee myCup = new CupOfCofee();

Objects may also be instatined using non default constructors. For example, our CupOfCofee class might have a non default constructors that use a parameter to set the bean type at instantiation: CupOfCofee myCup = new CupOfCofee(Eagles Group);

Constructors, like fields, properties, and methods, may be public or private. Code external to a class cant instantiate an object using a private constructor; it might use a public constructor. In this way we can, for example, force the user of the class to use a non default, constructor. Some classes have no public constructors, meaning that is impossible for external code to instantiate them. However, this doesnt make them completely useless, as we will see soon

7.9 Destructors
Destructors are used by the .NET Framework to clean up after objects. In general, we dont want to have provide code foe a destructor method; instead the default operation works for us. However, we can provide specific instructions if anything important need to be done before the object instance is deleted. DENOTE: That the destructors method of an object doesnt get called as soon as we stop using that object. When a variable goes out of scope, for example, it may not accessible form our code, but it may still exist somewhere in your computers memory. It is only when the .NET

All Rights Reserved To EaglesGroup

297

runtime perform its garbage collection clean up that the instance is completely destroyed. This means that we should rely on the destructors to free up resources that are used by an object instance, as this may be a long time after the object is of no further use to us. If the resources in use are critical this can cause problems. However, there is a solution to this we can see in more details in the Chapter 8 in the section 8.13 The C# Destructor.

7.9 Static and Instance Class Members


As well as having members such as properties, methods, and fields that are specific to object instances, it is also possible to have static also known as shared members, which may be methods, properties, or fields. Static members are shared between instances of a class, so they can be thought to of as global for objects of a given class. Static properties and fields allows us access to data that is independent of any object instances, and static methods allow us to execute commands related to the class type but not specific to object instances. When using static members, in fact, we dont event need to instantiate an object. For example, the Console.WriteLine () and Convert.ToString () methods we have been using are static. At no point do we need to instantiate the Console or Convert class indeed, if we are try it well find that we cant as the constructors of these classes arent publicly accessible, as discussed earlier. There are many situations such as these where static properties and methods can be used to good effect. For example, we might use a static property to keep track of how many instances of a class have been created. In UML (universal modeling language), syntax, static members of classes are shown underlined in the following diagram:

298

All Rights Reserved To EaglesGroup

7.9 OOP Techniques


Now weve covered the basics and know what objects are and how they work, we should spend some time looking at some of the other features of objects. Well look at: Interfaces Inheritance Polymorphism Relationships between objects Operator overloading Events

7.10 Interfaces
An interface is a collection of implicitly public methods and properties that are grouped together to encapsulate specific functionality. Once an interface has been defined, we can implement it in a class. This means that the class will then support all of the properties and members specified by the interface. DENOTE: That interfaces cannot exist on their own. We cant instantiate an interface as we can a class. In addition, interfaces cannot contain any code that implements its members; it just defines the members themselves. The implementation must come form classes that implement the interface.

All Rights Reserved To EaglesGroup

299

In our earlier coffee example, we might group together many of the more general purpose properties and methods into an interface, such as AddSugar (), Milk, Sugar, and Instant. We could call this interface something like IHotDrink (interface names are normally prefixed with a capital I. we could objects in a similar way, and they may still have their own individual properties BeanType for CupOfCoffee and LeafType for CupOfTea, for example. Interface implemented on objects in UML (universal modeling language), are shown using lollopop syntax. In the diagram below, I have split the members of IHotDrink into a separate box using class like syntax unfortunately the current version of Visio doesnt allow interfaces to posses fields or properties.

A class can support multiple interfaces, and multiple classes can support the same interface. The concept of an interface, therefore, makes life easier for user and other developers. For example, you might have some code that uses an object with certain interface. Provided you dont use other properties and methods of this object it is possible to replace one object with another code using the IHotDrink interface shown above in the picture the work with both CupOfCoffee and CupOfTea instances, for example, in addition, the developers of the object itself could supply you with an updated version of an object, and as long as it supports an interface that is already in use becomes to use this new version in you code.

300

All Rights Reserved To EaglesGroup

7.11 Disposable Objects


One interface of particular interest is IDisposable. An object that supports the IDisposable interface must implement the Dispose () method, that is, they must provide code for this method. This method can be called when an object is no longer needed just before it goes out scope, for example and should be used to free up any critical resources which might otherwise linger until the destructor methods is called on garbage collection. This gives you more control over resources used by your objects. C# allows us to use a structure that makes excellent use of this method. The using keywords allows us to initialize an object that uses critical resources in a code block, where Dispose () is automatically called at the end of this code block. The usage is a follows: Using (<ClassName> <VariableName> = new <ClassName> ()) { . }

Here the variable <VariableName> will be usable within this code block, and will be disposed of automatically at the end that is, Dispose () is called when the code block finishes executing.

7.12 Inheritance
Inheritance is one of the most important feature in the Object Oriented Programming. Any class may inherit from another, which means that it will have all the members that the class it inherits form has. In OOP terminology, the class being inherited also know as derived from is the parent class also know as the base class. DENOTE: That objects in C# may only descend from a single base class. Inheritance allows us to extend or create more specific class form a single, more generate base class, for example, consider a class that represents a farm of animals. This class might be called Animal, and process method such as EatFood () or Breed (). We could create a derived class called Dog, which would support all of the methods, but might also supply its own, such as Brake () and SupplyMilk (). We could also create another derived class, chicken, with Clunk () and LayEgg () methods. In UML (universal modeling language), we indicate inheritance using arrows, for example:

All Rights Reserved To EaglesGroup

301

When inheriting from a base class the question of member accessibility becomes an important one. Private members of the base class will not be accessible from a derived class, but public members will, however, public members are accessible to both the derived class and external code. This means that if we could only use these two levels of accessibility we couldnt have a member that was accessible by the base class and the derived class not external code. To get round this, there is a third party type of accessibility, protected, where only derived class has access to a member. As far as external code is aware, this is identical to private member it doesnt have access in either case. As well as the protection level of the member, we can also define an inheritance behavior for it. Members of a base class may be virtual, which means that the member can be overridden by the class that inherits it. What this means is that the derived class may provide an alternative implementation for the member. This alternative doesnt delete the original code, which is still accessible from within the class, but it does shield it from external code. If no alternative is supplied the external code has access to the base class implementation of the member. DENOTE: That virtual members cannot be private, as this would cause a impossibility it is impossible to say that a member can be overridden by a derived class at the same time as saying that it is inaccessible from the derived class:

302

All Rights Reserved To EaglesGroup

In our animal example, we could make EatFood () virtual, and provide a new implementation for it on any derived class, for example just on the Dog class:

Here I have displayed the EatFood () method on the Animal and Dog classes to signify that they have their own implementations. Base classes may also be defined as abstract classes. An abstract class cant be instantiated directly; to use it you need to inherit form it. Abstract classes may have abstract members, which have no implementation in the base class, so an implementation must be supplied in the derived class If Animal was an abstract class then the UML (universal modeling language), would be as follows:

All Rights Reserved To EaglesGroup

303

Abstract class is shown with their name in italics in the above picture: In C# here is a common base class for all objects called object which is an alias for the System.Object class in the .NET Framework Interface, described earlier in this chapter, may also inherit from other interfaces, unlike classes; interface may inherit from multiple base interfaces.

7.13 Polymorphism
One consequence of inheritance is that class deriving from a base class has an overlap in the methods and properties that they expose. Because of this, it is often possible to treat objects instantiated from classes with a base type in common using identical syntax. For example, if a base class called Animal has a method called EatFood () then syntax for calling this method from the derived class Dog and Chicken will be similar: Dog myDog = new Dog (); Chicken myChicken = new Chicken (); myDog.EatFood(); myChicken.EatFood();

304

All Rights Reserved To EaglesGroup

Polymorphism takes this step further. We can assign a variable that is of the base type to variable of the derived types, for example: Animal myAnimal = myDog; No casting is required for this. We can then call method of the base class through this variable: myAnimal.EatFood(); This will result in the implementing of EatFood() in the derived class being called. Note that we cant call methods define on the derived class in the same way. The following code wont work: myAnimal.Bite(); However, we can cast base type variable into a derived class variable and call the method of the derived class that way: Dog myNewDog = (Dog)Animal; myNewDog.Bite(); This casting will cause an exception to be raised if the type of the original variable was anything other than Dog or a class derived from Dog. There are ways of telling what type an object. Polymorphism is an extremely useful technique for performing tasks on different objects descending from a single class with the minimum code. DENOTE: That isnt just classes sharing the same parent class that can make use of polymorphism. It is also possible to treat, say, a child and a grandchild class in the same way, as long as there is common class in their inheritance hierarchy.

All Rights Reserved To EaglesGroup

305

7.14 Interface Polymorphism


Earlier on we introduced the concept of the interface for grouping together related methods and properties. Although we cannot instantiate interfaces in the same way as objects, it is possible to have a variable of an interface type. We can then use this variable to get access to methods and properties exposed by this interface on objects that support it. For example, lets say that instead of an Animal base class being used to supply the Eat Food () method we place this EatFood () method on an interface called IConsume. The Dog and Chicken classes could both support this interface; the only difference being that they are forced to provide an implementation for EatFood() as interfaces contain no implementation. We can then access this method using code such as: Dog myDog = new Dog(); Chicken myChicken = new Chicken (); Iconsume consumeInterface; consumeInterface = myDog; consumeInterface.EatFood(); consumeInterface = myChicken; consumeInterface.EatFood(); This provides a simple way for multiple objects to be called in the same way, and doesnt rely on a common base class. In this code, calling consumeInterface.EafFood() results in the EatFood() method of the Dog or Chicken class being called, depending on which instance has been assigned to the interface type variable.

306

All Rights Reserved To EaglesGroup

7.15 Relationships between Objects


Inheritance is simple relationship between objects that results in a base class being completely exposed by a derived class, where the derived class may also have some access to the inner working of its base class through protected members. There are other situations where relationships between objects become important. In this section well take a brief look at: Containment - Where one class contains another. This similar to inheritance but allows the containing class to control access to the members of the contained class, and event perform additional processing before using members of a contained class. Collections Where one class acts as a container for instances of another class. This is similar to having arrays of objects, but has additional scope, including indexing, sorting, resizing, and more.

7.16 Containment
Containment is simple to achieve by using a member filed to hold an object instance. This member filed might be public, in which can users, of the container object will have access to its exposed methods and properties much like inheritance. However, we wont have the internals of the class via the derived class as we would with inheritance: Alternatively, we can make the contained member object a private member. If we do this, none of its member will be accessible directly by users, even if they are public. Instead, we can provide access to these members using members of containing class. This means we have complete control over what members of the contained class to expose, if any, and can also perform additional processing in the containing class members before accessing the contained class members. For example, a Dog class might an under class with the public method Brake (). The Dog object could call this method as required, perhaps as part of its DogBrake () method, but these details will not be apparent or important to users of the Dog object. Containment classes may be visualized in UML using an association line. For simple containment we label the ends of the lines with 1s, showing a one to one relationship one Dog instance will contains one Udder instance. We can also show the contained Udder class instance as private filed of the Dog class for clarity.

All Rights Reserved To EaglesGroup

307

7.17 Collections
The variables types we have been using are really objects, so this is no real surprise. For example: Animal [] animals = new Animal [5]; A collection is basically an array with bells and whistles. Collections are implemented as classes in much the same way as other objects. They are often named in the plural form of the objects they store, for example a class called Animals might contain a collection of Animal objects. The main difference from arrays is that collections usually implement additional functionality, such as Add () and Remove () methods to ass and remove items from the collection. There is also usually an Item property that returns an object based on its index. More often than not this property is implemented in such a way to allow more sophisticated access. For example, it would be possible to design Animals such that a given Animal object could be accessed by its name. In UML we can visualize this as follows:

308

All Rights Reserved To EaglesGroup

I have left off the members here, as its the relationship that is being illustrated. The numbers on the ends of the connecting lines here show that one Animals object will contain Zero, or more Animal objects.

7.18 Operator Overloading


Earlier on this book we saw how operators can be used to manipulate simples variable types. There are times when it would be logical to use operator with object instatined from our own classes. This is possible because classes can contain intrusions as how to operators should be treated. For example, we might add a new property to our Animal class called Weight; we could then compare animals weight using the following syntax If (dogA.Weight > dogB.Weight) { // do the following }

All Rights Reserved To EaglesGroup

309

Using operator overloading we could provide logic that used the Weight property implicitly in our code, such that we could write code such are: If (dogA > dogB> { // the do the following } Here the greater than operator > has been overloaded. An overloaded operator is one for which we have written the code to perform the operation involved this code is added to the class definition of one of the classes that it operates on. In the above example we are using the Dog objects, so the operator overloaded definition is contained in the Dog classes. We can also overload operator to work with different classes in the same way, where one or both of the classs definitions contains the code to achieve this. DENOTE: That we can only overload existing C# operators in this way; we cant create new ones. However, we can provide implementations for both unary and binary usages of operators such as +. Well see how to do in the C# Next Chapter.

7.19 Events
Object may raise and consume events as part of their processing. Events are important occurrence that we can act on in other pasts of code, similar to but more powerful than exceptions. We might for example, want some specific code to execute when an Animal object is added to an Animals collection, where that code isnt part of either the Animals class or the code that calls the Add() method. To do this we need to add an event handler to our code, which is a special kind of function that is called when the event occurs. We also need to configure this handler to listen for the event we are interested in. Using events, we create event driven applications, which are far more prolific than you might think at this point or stage. As an example, it is wroth bearing in mind that Windows based application are entirely depends on events. Every button click or scrollbar drag you perform is achieved through event handling. Were the event s are triggered by the mouse or by the keyboard. This event we will see later on the chapter 11 more depth and how this works in Windows application, but for the example we are going to use the console application which will be easier to understand but Window application also easier but we prefer to console application because we see more event s working in console application.

310

All Rights Reserved To EaglesGroup

7.20 References versus. Value Types


Data in C# is stored in a variable in one of two ways depending on the type of the variable. This type will fall into one of two categories; it is either a reference type or value type. The difference is as follows: Value types store themselves and their content in one place in memory Reference type hold a reference to somewhere else in memory called the heap where contents are stored. In actual fact we dont have to worry about this too much when using C#. So far weve used string variables which are reference types and other simple variables most of which are value types, such as int in pretty much the same way. The only simple types that are reference types are string and object, although arrays are implicitly reference types as well. Every class we create will be a reference type, which is why I am making this point now really it true!

7.21 Structs
At this point there is an important point to note. The key difference between struct types and classes is that struct types are value types. The fact that struct types and classes are similar may have occurred to you, particularly as we saw in Chapter 5 how we can use functions in struct types. Well see more details about this in Chapter 9.

All Rights Reserved To EaglesGroup

311

7.22 OOP in Windows Applications


Back to the Chapter Fast Introduction to .NET Version 2005 we saw how to create a simple Windows application in C#. Windows applications are heavily dependent on OOP techniques in this section well take at look at this to illustrate some of the points. To do this we will be creating an example: Lets work it out Using Object in Action

Example 7-1 Using Object in Action

Example Try it out Eagles ObjectAction Step by Step Example: Using Version 2005
1. Create a new Windows Application and name it as Eagles ObjectAction in the directory C:\EaglesVisualCSharp\Chapter 7\Example Using Object in Action 2. Add a new Button control using the Toolbox bar, and position it in the center of the Form1.cs[Design] as shown in the following screenshot:

312

All Rights Reserved To EaglesGroup

3. Now double click on the button and the add the code as follows: private void button1_Click(object sender, EventArgs e) { ((Button)sender).Text = "Clicked!"; Button newButton = new Button(); newButton.Text = "Eagles Button"; newButton.Click += new EventHandler(newButton_Click); Controls.Add(newButton); }

4. Now you have error because you need to add the following code in the Form1.cs as follows: private void newButton_Click(object sender, System.EventArgs siddhu) { ((Button)sender).Text = "Clicked!"; }

5. Now run the application and click the button and you should see the following outputs:

All Rights Reserved To EaglesGroup

313

6. Click on the button which say Click Me:

314

All Rights Reserved To EaglesGroup

7. Click on the button named as Eagles:

Now lets see how it workss: By adding just a few lines of code weve created a Windows application that does something, while at the same time illustring some OOP techniques in C#. The phrase we used before in this chapter Everythings an object is even truer when it comes to Windows application. From the form that runs, to the controls on the form, we need to make use of OOP technique all the time. Throughout this example description Ive highlighted some of the concepts that weve looked at earlier in this chapter to show everything fits together. The first thing we did in our application was to add a new button to the Form1.cs [Design]. This button is an object, called Button. Next, by double click the button we have added the event handler to listen out for the Click event that the Button object generates. This event handler is added into the code for the Form1.cs object that encapsulates our application, as a private method:

All Rights Reserved To EaglesGroup

315

private void button1_Click(object sender, EventArgs e) { } This uses the C# keyword private as a qualifier. Dont worry too much about for now; in the next chapter well looking at the C# code required for the OOP techniques weve seen in this chapter. The first line of code we added change the text on the button that is clicked. This makes use of the polymorphism as seen earlier in this chapter. The button object representing the button that we click is sent to the event handler as an object parameter, which we cast into a Button type (this is possible as the Button object inherits from System.Object, which is the .NET class that object is an alias for. We then change the text property to change the text displayed: ((Button)sender).Text = "Clicked!"; Next, we create a new Button object with the new keyword note that namespace are set up in this project to enable this simple syntax, otherwise wed need to use the fully qualified name of this object, System.Windows.Forms.Button: Button newButton = new Button(); newButton.Text = "Eagles Button"; Elsewhere in the code a new event handler is added, which well use to respond to click evetn generated by out new button: private void newButton_Click(object sender, System.EventArgs siddhu) { ((Button)sender).Text = "Clicked!"; }

We then register this event handler as a listener for the Click evetn using some overloaded operator syntax. Along the way we create a new EvetnHandler object using a non default constructor, using the name of the new evetn handler function: newButton.Click += new EventHandler(newButton_Click);

316

All Rights Reserved To EaglesGroup

Finally, we make use of the Controls property. This property is an object that is collection of all the controls on our form, and we use it Add () method to add our new button to the form: Controls.Add(newButton); The Controls property illustrates that properties need not necessarily be simple types such as string or integers, but can be any kind of object. This example has used almost all the techniques introduced in this chapter. As you can see. OOP programming neednt be complicated it just requires a different point of view to get right. As what we need to is Everyday there is a new thing for us, just open your mind for the Different View! The same thing for the OOP techniques also.

All Rights Reserved To EaglesGroup

317

Summary
This chapter has presented us with a full description of object oriented techniques. We have gone through this in the context of C# programming, but this has mainly been illustrative. The vast majority of this chapter is relevant to OOP in any language. We started by covering the basics, such as what it meant by the term object, and how an object is an instance of class. Next we saw how object can have various members, such as fields, properties, and methods. These members can have restricted accessibility, and we looked at what we mean by public and private members. Later on, we saw the members can also be protected, as well as being able to be virtual and abstract where abstract methods are only permissible on abstract classes. We also looked at the difference between static shard and instance members. Next we tool a quick look at the lifecycle of an object, including how constructors are used in object creation, and destructors in object deletion. Later on, after examining groups of members in interfaces, we looked at more advanced object destruction with disposable objects supporting the IDisposable interface. Most of the reminder of this chapter looked at the feature of OOP, many of which well be seeing in more depth in the chapters that follow. We looked at inheritance, where classes inherit from base classes, two versions of polymorphism, through base classes and shared interface, and saw how objects can be used to contain one or more other objects through containment and collections. Finally, we say how operators overloading can be used to simplify the syntax of object usage, and how objects often raise events.

318

All Rights Reserved To EaglesGroup

Chapter 08

All Rights Reserved To EaglesGroup

319

Classes and Objects


8.1. Introduction to Classes and Objects:
C# language, such as int, long, and char. The heart and soul of C#, however, is the ability to create new, complex, programmer-defined types that map cleanly to the objects that make up the problem you are trying to solve It is this ability to create new types that characterizes an object-oriented language. You specify new types in C# by declaring and defining classes. You can also define types with interfaces. Instances of a class are called objects. Objects are created in memory when your program executes The difference between a class and an object is the same as the difference between the concept of a Dog and the particular dog who is sitting at your feet as you read this. You can't play fetch with the definition of a Dog, only with an instance A Dog class describes what dogs are like: they have weight, height, eye color, hair color, disposition, and so forth. They also have actions they can take, such as eat, walk, bark, and sleep. A particular dog (such as my dog Milo) has a specific weight (62 pounds), height (22 inches), eye color (black), hair color (yellow), disposition (angelic), and so forth. He is capable of all the actions of any dog (though if you knew him you might imagine that eating is the only method he implements). The huge advantage of classes in object-oriented programming is that they encapsulate the characteristics and capabilities of an entity in a single, self-contained, and selfsustaining unit of code. When you want to sort the contents of an instance of a Windows list box control, for example, tell the list box to sort itself. How it does so is of no concern; that it does so is all you need to know. Encapsulation, along with polymorphism and inheritance, is one of three cardinal principles of object-oriented programming. An old programming joke asks, how many object-oriented programmers does it take to change a light bulb? Answer: none, you just tell the light bulb to change itself. (Alternate answer: none, Microsoft has changed the standard to darkness.)

320

All Rights Reserved To EaglesGroup

This chapter explains the C# language features that are used to specify new classes. The elements of a classits behaviors and propertiesare known collectively as its class members. This chapter will show how methods are used to define the behaviors of the class, and how the state of the class is maintained in member variables (often called fields). In addition, this chapter introduces properties, which act like methods to the creator of the class but look like fields to clients of the class

Now lets see How to Defining Classes:


To define a new type or class, first declare it, and then define its methods and fields. Declare a class using the class keyword. The complete syntax is as follows: [attributes] [access-modifiers] class identifier [:base-class] {class-body} The member definitions that make up the class-body are enclosed by open and closed curly braces ({}) C and C++ programmers take note: A C# class definition does not end with a semicolon, though if you add one, the program will still compile In C#, everything happens within a class; make use of a class named Program.cs: public class Program { public static int Main( ) { /... } }

So far, we've not instantiated any instances of that class; that is, we haven't created any Tester objects. What is the difference between a class and an instance of that class? To answer that question, start with the distinction between the type int and a variable of type int. Thus, while you would write:

All Rights Reserved To EaglesGroup

321

int myInteger = 5; you would not write: int = 5;

You can't assign a value to a type; instead, you assign the value to an object of that type (in this case, a variable of type int). When you declare a new class, you define the properties of all objects of that class, as well as their behaviors. For example, if you are creating a windowing environment, you might want to create screen widgets more commonly known as controls in Windows programming to simplify user interaction with your application. One control of interest might be a list box, which is very useful for presenting a list of choices to the user and enabling the user to select from the list. List boxes have a variety of characteristicsfor example, height, width, location, and text color. Programmers have also come to expect certain behaviors of list boxes: they can be opened, closed, sorted, and so on. Object-oriented programming allows you to create a new type, ListBox, which encapsulates these characteristics and capabilities. Such a class might have member variables named height, width, location, and text color, and member methods named sort ( ), add ( ), remove ( ), etc. You can't assign data to the ListBox type. Instead you must first create an object of that type, as in the following code snippet: ListBox myListBox;

322

All Rights Reserved To EaglesGroup

Once you create an instance of ListBox, you can assign data to its fields. Now consider a class to keep track of and display the time of day. The internal state of the class must be able to represent the current year, month, date, hour, minute, and second. You probably would also like the class to display the time in a variety of formats. You might implement such a class by defining a single method and six variables, as shown Lets work it out Using Simple Time Class

Example 8-1.Using Simple Time Class

Example Try it out Eagles SimpleTime Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles SimpleTime in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using Simple Time Class 2. Add the following code in the Program.cs as follows: namespace Eagles_SimpleTime { # region EaglesGroup /// <EaglesGroup> ///Somu ///Siddhu ///Sri ///(C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class Time { // private variables

All Rights Reserved To EaglesGroup

323

int Month; int Year; int Date; int Hour; int Minute; int Second; // public methods public void DisplayCurrentTime() { Console.WriteLine(DateTime.Now.ToString ()); } }

3. Now enter the following code into the static main () in the program.cs as follows: static void Main(string[] args) { Time t = new Time(); t.DisplayCurrentTime(); } 4. Now run the program and you will see the output like this:

324

All Rights Reserved To EaglesGroup

Now lets see how the above program works:

The only method declared within the Time class definition is DisplayCurrentTime ( ). The body of the method is defined within the class definition itself. Unlike other languages (such as C++), C# does not require that methods be declared before they are defined, nor does the language support placing its declarations into one file and code into another. (C# has no header files.) All C# methods are defined inline as shown in Example with DisplayCurrentTime ( ). The DisplayCurrentTime ( ) method is defined to return void; that is, it will not return a value to a method that invokes it. For now, the body of this method has been "stubbed out." The Time class definition ends with the declaration of a number of member variables: Year, Month, Date, Hour, Minute, and Second. After the closing brace, a second class, Tester, is defined. Tester contains our now familiar Main ( ) method. In Main ( ), an instance of Time is created and its address is assigned to object t. Because t is an instance of Time, Main ( ) can make use of the DisplayCurrentTime ( ) method available with objects of that type and call it to display the time: t.DisplayCurrentTime ( );

All Rights Reserved To EaglesGroup

325

8.1.2 Access Modifiers


An access modifier determines which class methodsincluding methods of other classescan see and use a member variable or method within a class. The Following Table summarizes the C# access modifiers

Table Access modifiers

Access Modifier public Private Protected

Restrictions No restrictions. Members marked public


are visible to any method of any class.

The members in class A that are marked private are accessible only to methods of class A. The members in class A that are marked protected are accessible to methods of
class A and also to methods of classes derived from class A

Internal protected internal

The members in class A that are marked internal are accessible to methods of any class in A's assembly The members in class A that are marked protected internal are accessible to methods of class A, to methods of classes
derived from class A, and also to any class in A's assembly. This is effectively protected OR internal. There is no

concept of protected AND internal.

326

All Rights Reserved To EaglesGroup

It is generally desirable to designate the member variables of a class as private. This means that only member methods of that class can access their value. Because private is the default accessibility level, you do not need to make it explicit, but I recommend that you do so. Thus, in Example in the above example, the declarations of member variables should have been written as follows: // private variables private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second;

Class Program and method DisplayCurrentTime ( ) are both declared public so that any other class can make use of them.

DENOTE: It is good programming practice to explicitly set the accessibility of all methods and members of your class. Although you can rely on the fact that class members are declared private by default, making their access explicit indicates a conscious decision and is self-documenting

8.1. 3 Method Arguments


Methods can take any number of parameters. The parameter list follows the method name and is encased in parentheses, with each parameter preceded by its type. For example, the following declaration defines a method named MyMethod ( ), which returns void that is, which returns no value at all and which takes two parameters: an integer and a button. The terms "argument" and "parameter" are often used interchangeably, though some programmers insist on differentiating between the argument declaration and the parameters passed in when the method is invoked.

void MyMethod (int firstParam, button secondParam) { // ... }

All Rights Reserved To EaglesGroup

327

Within the body of the method, the parameters act as local variables, as if you had declared them in the body of the method and initialized them with the values passed in. The Following Example will show you how to pass the values into a methodin this case, values of type int and float. Lets work it out Using passing values into SomeMethod ()

Example 8-2.Using passing values into SomeMethod

Example Try it out Eagles passingvalues Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles passingvalues in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using passing values into SomeMethod () 2. Add the Following code into the Program.cs as follows namespace Eagles_passingvalues { # region EaglesGroup /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion public class SiddhuClass { public void SomeMethod(int firstParam, float secondParam) { Console.WriteLine("Here are the parameters received: {0}, {1}", firstParam, secondParam); }

328

All Rights Reserved To EaglesGroup

class Program { static void Main(string[] args) { int howManyPeople = 5; float pi = 3.14f; SiddhuClass mc = new SiddhuClass (); mc.SomeMethod(howManyPeople, pi); }

3. Now run the program and you should see the out put like this:

Now lets see how the above program works?

The method SomeMethod ( ) takes an int and a float and displays them using Console.WriteLine ( ). The parameters, which are named firstParam and secondParam, are treated as local variables within SomeMethod ( ).

All Rights Reserved To EaglesGroup

329

DENOTE: VB6 programmers take note: C# methods don't allow you to declare optional arguments. Instead, you have to use method overloading to create methods that declare different combinations of arguments. In the calling method (Main), two local variables (howManyPeople and pi) are created and initialized. These variables are passed as the parameters to SomeMethod ( ). The compiler maps howManyPeople to firstParam and pi to secondParam, based on their relative positions in the parameter list

8.2 Creating Objects


The primitive C# types (int, char, etc.) are value types, and are created on the stack. Objects, however, are reference types, and are created on the heap, using the keyword new, as in the following: Time t = new Time ( );

It

does not actually contain the value for the Time object; it contains the address of that (unnamed) object that is created on the heap. t itself is just a reference to that object. DENOTE: VB6 programmers take note: While there is a performance penalty in using the VB6 keywords Dim and New on the same line, in C# this penalty has been removed. Thus in C# there is no drawback to using the new keyword when declaring an object variable

8.2.1 Constructors
In Example 8.2, notice that the statement that creates the Time object looks as though it is invoking a method:

Time t = new Time( );

330

All Rights Reserved To EaglesGroup

In fact, a method is invoked whenever you instantiate an object. This method is called a constructor, and you must either define one as part of your class definition or let the Common Language Runtime (CLR) provide one on your behalf. The job of a constructor is to create the object specified by a class and to put it into a valid state. Before the constructor runs, the object is undifferentiated memory; after the constructor completes, the memory holds a valid instance of the class type. The Time class of Example 8.2 does not define a constructor. If a constructor is not declared, the compiler provides one for you. The default constructor creates the object but takes no other action. Member variables are initialized to innocuous values (integers to 0, strings to the empty string, etc.).

The Table 8.2.2.1 lists the default values assigned to primitive types. Table 8.2.2.1 Primitive types and their default values Type numeric (int, long, etc.) bool char enum Default Value

false

'\0' (null)

reference

null

Typically, you'll want to define your own constructor and provide it with arguments so that the constructor can set the initial state for your object. In Example 8.2, assume that you want to pass in the current year, month, date, and so forth, so that the object is created with meaningful data.

All Rights Reserved To EaglesGroup

331

To define a constructor, declare a method whose name is the same as the class in which it is declared. Constructors have no return type and are typically declared public. If there are arguments to pass, define an argument list just as you would for any other method. The below Example will declares a constructor for the Time class that accepts a single argument, an object of type Date Time. Lets work it out Using Declaring a Constructor

Example 8-3.Using Declaring a Constructor

Example Try it out Eagles DeclaringConstructor Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles declaringconstructor in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using Declaring a Constructor 2. Add the following code in the body of the Program.cs as follows:

namespace Eagles_declaringconstructor { # region EaglesGroup /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { public class Siddhu {

332

All Rights Reserved To EaglesGroup

// private member variables int Year; int Month; int Date; int Hour; int Minute; int Second; // public accessor methods public void DisplayCurrentTime() { System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", Month, Date, Year, Hour, Minute, Second); } // constructor public Siddhu (System.DateTime dt) { Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; } }

3. Now add the following code in the static void main() as follows:

static void Main(string[] args) { System.DateTime currentTime = System.DateTime.Now; Siddhu t = new Siddhu (currentTime); t.DisplayCurrentTime(); }

All Rights Reserved To EaglesGroup

333

4. Now Run the program and you will have the result similar to like this:

Now lets see how the above program works: In this example, the constructor takes a DateTime object and initializes all the member variables based on values in that object. When the constructor finishes, the Time object exists and the values have been initialized. When DisplayCurrentTime ( ) is called in Main ( ), the values are displayed. Try commenting out one of the assignments and running the program again. You'll find that the member variable is initialized by the compiler to 0. Integer member variables are set to 0 if you don't otherwise assign them. Remember, value types (e.g., integers) cannot be uninitialized; if you don't tell the constructor what to do, it will try for something innocuous In Example 8.3, the DateTime object is created in the Main ( ) method of Tester. This object, supplied by the System library, offers a number of public valuesYear, Month, Day, Hour, Minute, and Secondthat correspond directly to the private member variables of our Time object. In addition, the DateTime object offers a static member property, now, which is a reference to an instance of a DateTime object initialized with the current time. Examine the highlighted line in Main ( ), where the DateTime object is created by calling the static method now ( ). Now ( ) creates a DateTime object on the heap and returns a reference to it.

334

All Rights Reserved To EaglesGroup

That reference is assigned to currentTime, which is declared to be a reference to a DateTime object. Then currentTime is passed as a parameter to the Time constructor. The Time constructor parameter, dt, is also a reference to a DateTime object; in fact dt now refers to the same DateTime object as currentTime does. Thus, the Time constructor has access to the public member variables of the DateTime object that was created in Tester.Main ( ). The reason that the DateTime object referred to in the Time constructor is the same object referred to in Main( ) is that objects are reference types. Thus, when you pass one as a parameter it is passed by referencethat is, the pointer is passed and no copy of the object is made.

8.3 Initializers
It is possible to initialize the values of member variables in an initializer, instead of having to do so in every constructor. Create an initializer by assigning an initial value to a class member: private int Second = 30; // initializer Assume that the semantics of our Time object are such that no matter what time is set, the seconds are always initialized to 30. We might rewrite our Time class to use an initializer so that no matter which constructor is called, the value of Second is always initialized, either explicitly by the constructor or implicitly by the initializer. See Example 8.4 The Following Example will uses an overloaded constructor, which means there are two versions of the constructor that differ by the number and type of variables. Lets work it out Using an Initializer

Example 8-4.Using an Initializer

Example Try it out Eagles Initializer Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles Initializer in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using an Initializer

All Rights Reserved To EaglesGroup

335

2. Add the following code in the Program.cs as follows: namespace Eagles_Initializer { #region EaglesGroup /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class EaglesTime { // private member variables private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second = 30; // initializer // public accessor methods public void DisplayCurrentTime() { System.DateTime now = System.DateTime.Now; System.Console.WriteLine("\nDebug\t: {0}/{1}/{2} {3}:{4}:{5}", now.Month, now.Day, now.Year, now.Hour, now.Minute, now.Second); System.Console.WriteLine("Time\t: {0}/{1}/{2} {3}:{4}:{5}", Month, Date, Year, Hour, Minute, Second); } // constructors public EaglesTime(System.DateTime dt) { Year = Month = Date = Hour = Minute = Second = } 336
All Rights Reserved To EaglesGroup

dt.Year; dt.Month; dt.Day; dt.Hour; dt.Minute; dt.Second; //explicit assignment

public EaglesTime(int Year, int Month, int Date, int Hour, int Minute) { this.Year = Year; this.Month = Month; this.Date = Date; this.Hour = Hour; this.Minute = Minute; } }

3. Add the Following Code in the Static Main () as follows: static void Main(string[] args) { System.DateTime currentTime = System.DateTime.Now; EaglesTime t = new EaglesTime(currentTime); t.DisplayCurrentTime(); EaglesTime t2 = new EaglesTime(2005, 11, 18, 11, 45); t2.DisplayCurrentTime(); }

All Rights Reserved To EaglesGroup

337

4. Run the Program and you will have the output like this:

Now lets see how the above program works: If you do not provide a specific initializer, the constructor will initialize each integer member variable to zero (0). In the case shown, however, the Second member is initialized to 30: private int Second = 30; // initializer

If a value is not passed in for Second, its value will be set to 30 when t2 is created: EaglesTime t2 = new EaglesTime (2007, 11, 18, 11, 45); t2.DisplayCurrentTime ( );

However, if a value is assigned to Second, as is done in the constructor (which takes a DateTime object, shown in bold), that value overrides the initialized value.

338

All Rights Reserved To EaglesGroup

The first time through the program, we call the constructor that takes a DateTime object, and the seconds are initialized to 54. The second time through, we explicitly set the time to 11:45 (not setting the seconds), and the initializer takes over. If the program did not have an initializer and did not otherwise assign a value to Second, the value would be initialized by the compiler to zero.

8.4 Copy Constructors


A copy constructor creates a new object by copying variables from an existing object of the same type. For example, you might want to pass a Time object to a Time constructor so that the new Time object has the same values as the old one. C# does not provide a copy constructor, so if you want one you must provide it yourself. Such a constructor copies the elements from the original object into the new one: public Time(Time existingTimeObject) { Year = existingTimeObject.Year; Month = existingTimeObject.Month; Date = existingTimeObject.Date; Hour = existingTimeObject.Hour; Minute = existingTimeObject.Minute; Second = existingTimeObject.Second; }

A copy constructor is invoked by instantiating an object of type Time and passing it the name of the Time object to be copied: EaglesTime t3 = new EaglesTime(t2);

Here an existingTimeObject (t2) is passed as a parameter to the copy constructor that will create a new Time object (t3).

All Rights Reserved To EaglesGroup

339

DENOTE: C and C++ programmers take note: The C# compiler does not generate a copy constructor for you if you do not create your own; however, it doesn't need to. A copy constructor is simply another function in C#it is never called automatically

8.4 The ICloneable Interface


The .NET Framework defines an ICloneable interface to support the concept of a copy constructor. This interface defines a single method: Clone ( ). Classes that support the idea of a copy constructor should implement ICloneable and then should implement either a shallow copy (calling MemberwiseClone) or a deep copy (by calling the copy constructor and hand-copying all the members). class SomeType: ICloneable { public Object Clone( ) { return MemberwiseClone( ); // shallow copy } }

8.6The this Keyword


The keyword this refers to the current instance of an object. The this reference sometimes referred to as this pointer is a hidden pointer to every nonstatic method of a class. Each method can refer to the other methods and variables of that object by way of the this reference. A pointer is a variable that holds the address of an object in memory. C# does not use pointers with managed objects.

There are three ways in which the this reference is typically used. The first way is to qualify instance members otherwise hidden by parameters, as in the following: public void SomeMethod (int hour) { this.hour = hour; }

340

All Rights Reserved To EaglesGroup

In this example, SomeMethod ( ) takes a parameter (hour) with the same name as a member variable of the class. The this reference is used to resolve the name ambiguity. While this.hour refers to the member variable, hour refers to the parameter. The argument in favor of this style is that you pick the right variable name and then use it both for the parameter and for the member variable. The counter argument is that using the same name for both the parameter and the member variable can be confusing. The second use of the this reference is to pass the current object as a parameter to another method. For instance, the following code: public void FirstMethod(OtherClass otherObject) { otherObject.SecondMethod(this); }

Establishes two classes, one with the method FirstMethod ( ) and the second (OtherClass) with the method SecondMethod ( ). Inside FirstMethod, we'd like to invoke SecondMethod, passing in the current object for further processing.

8.7 Using Static Members


The properties and methods of a class can be either instance members or static members. Instance members are associated with instances of a type, while static members are considered to be part of the class. You access a static member through the name of the class in which it is declared. For example, suppose you have a class named Button and have instantiated objects of that class named btnUpdate and btnDelete. Suppose as well that the Button class has a static method SomeMethod ( ). To access the static method, you write: Button.SomeMethod( ); Rather than writing:

btnUpdate.SomeMethod( );

All Rights Reserved To EaglesGroup

341

In C#, it is not legal to access a static method or member variable through an instance, and trying to do so will generate a compiler error (C++ programmers, take note). Some languages distinguish between class methods and other (global) methods that are available outside the context of any class. In C# there are no global methods, only class methods, but you can achieve an analogous result by defining static methods within your class. DENOTE: VB6 programmers take note: Don't confuse the static keyword in C# with the Static keyword in VB6 and VB.NET. In Visual Basic, the Static keyword declares a variable that is only available to the method it was declared in. In other words, the Static variable is not shared among different objects of its class (i.e., each Static variable instance has its own value). However, this variable exists for the life of the program, which allows its value to persist from one method call to another.

In C#, the static keyword indicates a class variable. In VB, the equivalent keyword is shared. Static methods act more or less like global methods, in that you can invoke them without actually having an instance of the object at hand. The advantage of static methods over global, however, is that the name is scoped to the class in which it occurs, and thus you do not clutter up the global namespace with myriad function names. This can help manage highly complex programs, and the name of the class acts very much like a namespace for the static methods within it.

DENOTE: Resist the temptation to create a single class in your program in which you stash all your miscellaneous methods. It is possible but not desirable and undermines the encapsulation of an object-oriented design.

342

All Rights Reserved To EaglesGroup

8.8 Invoking Static Methods


The Main ( ) method is static. Static methods are said to operate on the class, rather than on an instance of the class. They do not have a this reference, as there is no instance to point to. DENOTE: Java programmers take note: In C#, calling static methods through instance variables is not permitted. Static methods cannot directly access nonstatic members. For Main( ) to call a nonstatic method, it must instantiate an object. Consider Example 8.3, reproduced here for your convenience: using System; public class MyClass { public void SomeMethod(int firstParam, float secondParam) { Console.WriteLine( "Here are the parameters received: {0}, {1}", firstParam, secondParam); } } public class Tester { static void Main( ) { int howManyPeople = 5; float pi = 3.14f; MyClass mc = new MyClass( ); mc.SomeMethod(howManyPeople, pi); } }

SomeMethod( )

is a nonstatic method of SiddhuClass. For Main( ) to access this method, it must first instantiate an object of type SiddhuClass and then invoke the method through that object.

All Rights Reserved To EaglesGroup

343

8.9 Using Static Constructors


If your class declares a static constructor, you will be guaranteed that the static constructor will run before any instance of your class is created. DENOTE: You are not able to control exactly when a static constructor will run, but you do know that it will be after the start of your program and before the first instance is created. Because of this, you cannot assume (or determine) whether an instance is being created. For example, you might add the following static constructor to the Time class from Example 8.4: static Time( ) { Name = "Time"; } Notice that there is no access modifier (e.g., public) before the static constructor. Access modifiers are not allowed on static constructors. In addition, because this is a static member method, you cannot access nonstatic member variables, and so Name must be declared a static member variable: private static string Name; The final change is to add a line to DisplayCurrentTime( ), as in the following: public void DisplayCurrentTime( ) { System.Console.WriteLine("Name: {0}", Name); System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", Month, Date, Year, Hour, Minute, Second); }

344

All Rights Reserved To EaglesGroup

When all these changes are made, the output is: Name: Time 11/27/2005 7:52:54 Name: Time 11/18/2005 11:45:30

Although this code works, it is not necessary to create a static constructor to accomplish this goal. You could, instead, use an initializer: private static string Name = "Time";

Which accomplishes the same thing? Static constructors are useful, however, for set-up work that cannot be accomplished with an initializer and that needs to be done only once. DENOTE: Java programmers take note: In C#, a static constructor will serve where a static initializer would be used in Java. For example, assume you have an unmanaged bit of code in a legacy DLL. You want to provide a class wrapper for this code. You can call load library in your static constructor and initialize the jump table in the static constructor.

All Rights Reserved To EaglesGroup

345

8.10 Using Private Constructors


In C#, there are no global methods or constants. You might find yourself creating small utility classes that exist only to hold static members. Setting aside whether this is a good design or not, if you create such a class you will not want any instances created. You can prevent any instances from being created by creating a default constructor one with no parameters, which does nothing, and which is marked private. With no public constructors, it will not be possible to create an instance of your class

8.11 Using Static Fields


Common use of static member variables is to keep track of the number of instances that currently exist for your class. Example 8-5 illustrates Lets work it out Using Static fields for instance counting

Example 8-5.Using Static fields for instance counting

Example Try it out Eagles StaticFields Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles StaticFields in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using Static fields for instance counting 2. Add the following code in the Program.cs as follows: namespace Eagles_StaticFields { #region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGrroup /// </EaglesGroup> # endregion class Program

346

All Rights Reserved To EaglesGroup

{ public class Eagles { private static int instances = 0; public Eagles( ) { instances++; } public static void HowManyEagles( ) { Console.WriteLine("{0} Eagles adopted",instances); } } static void Main(string[] args) { Eagles.HowManyEagles(); Eagles siddhu = new Eagles(); Eagles.HowManyEagles(); Eagles Shamu = new Eagles(); Eagles.HowManyEagles(); } }

3.

Now Run the program and the result will be like this:

All Rights Reserved To EaglesGroup

347

Now lets see how the above program will work: The Eagles class has been stripped to its absolute essentials. A static member variable called instances is created and initialized to zero. Note that the static member is considered part of the class, not a member of an instance, and so it cannot be initialized by the compiler on creation of an instance. Thus, an explicit initializer is required for static member variables. When additional instances of Eagles are created in a constructor, the count is incremented. Static Methods to Access Static Fields It is undesirable to make member data public. This applies to static member variables as well. One solution is to make the static member private, as we've done here with instances. We have created a public accessor method, HowManyEagles ( ), to provide access to this private member.

8.12 Destroying Objects


Since C# provides garbage collection, you never need to explicitly destroy your objects. However, if your object controls unmanaged resources, you will need to explicitly free those resources when you are done with them. Implicit control over unmanaged resources is provided by a destructor, which will be called by the garbage collector when your object is destroyed.

DENOTE: C and C++ programmers take note: A destructor is not necessarily called when an object goes out of scope but when it is garbage-collected (which may happen much later). This is known as non-deterministic finalization

The destructor should only release resources that your object holds on to, and should not reference other objects. Note that if you have only managed references, you do not need to and should not implement a destructor; you want this only for handling unmanaged resources. Because there is some cost to having a destructor, you ought to implement this only on methods that require it (that is, methods that consume valuable unmanaged resources).

348

All Rights Reserved To EaglesGroup

Never call an object's destructor directly. The garbage collector (GC) will call it for you. How Destructors Work? The garbage collector maintains a list of objects that have a destructor. This list is updated every time such an object is created or destroyed. When an object on this list is first collected, it is placed on a queue with other objects waiting to be destroyed. After the destructor executes, the garbage collector then collects the object and updates the queue, as well as its list of destructible objects.

8.13 The C# Destructor

C#'s destructor looks, syntactically, much like a C++ destructor, but it behaves quite differently. Declare a C# destructor with a tilde as follows: In C#, this syntax is simply a shortcut for declaring a Finalize ( ) method that chains up to its base class. Thus, when you write: The C# compiler translates it to: protected override void Finalize( ) { try { // do work here. } finally { base.Finalize( ); } }

All Rights Reserved To EaglesGroup

349

8.14 Destructors versus Dispose


It is not legal to call a destructor explicitly. Your destructor will be called by the garbage collector. If you do handle precious unmanaged resources such as file handles that you want to close and dispose of as quickly as possible, you ought to implement the IDisposable interface.

The IDisposable interface requires its implementers to define one method, named Dispose ( ), to perform whatever cleanup you consider to be crucial. The availability of Dispose ( ) is a way for your clients to say, "Don't wait for the destructor to be called, do it right now." If you provide a Dispose ( ) method, you should stop the garbage collector from calling your object's destructor. To do so, call the static method GC.SuppressFinalize ( ), passing in the this pointer for your object. Your destructor can then call your Dispose ( ) method.

8.15 Implementing the Close ( ) Method

For some objects, you'd rather have your clients call the Close ( ) method. (For example, Close ( ) makes more sense than Dispose ( ) for file objects.) You can implement this by creating a private Dispose ( ) method and a public Close ( ) method and having your Close ( ) method invoke Dispose ( ).

8.16 The using Statement


Because you cannot be certain that your user will call Dispose ( ) reliably, and because finalization is nondeterministic i.e., you can't control when the GC will run, C# provides a using statement that ensures that Dispose ( ) will be called at the earliest possible time. The idiom is to declare the objects you are using and then to create a scope for these objects with curly braces. When the close brace is reached, the Dispose ( ) method will be called on the object automatically.

350

All Rights Reserved To EaglesGroup

Lets work it out Using the Using Statement

Example 8-6.Using the Using Statement

Example Try it out Eagles UsingStatment Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles UsingStatment in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using the Using Statement 2. Add the following code in the Program.cs as follows: namespace Eagles_UsingStatment { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> #endregion class Program { static void Main(string[] args) { using (Font theFont = new Font("Arial", 10.0f)) { // use theFont } // compiler will call Dispose on theFont Font anotherFont = new Font("Courier", 12.0f); using (anotherFont) { // use anotherFont } // compiler calls Dispose on anotherFont }

All Rights Reserved To EaglesGroup

351

Now lets see what exactly the above code does: In the first part of this example, the Font object is created within the using statement. When the using statement ends, Dispose ( ) is called on the Font object. In the second part of the example, a Font object is created outside of the using statement. When we decide to use that font, we put it inside the using statement; when that statement ends, Dispose ( ) is called once again. The using statement also protects you against unanticipated exceptions. No matter how control leaves the using statement, Dispose ( ) is called. It is as if there was an implicit try-catch-finally block

8.17 Passing Parameters

By default, value types are passed into methods by value, this means that when a value object is passed to a method, a temporary copy of the object is created within that method. Once the method completes, the copy is discarded. Although passing by value is the normal case, there are times when you will want to pass value objects by reference. C# provides the ref parameter modifier for passing value objects into a method by reference, and the out modifier for those cases in which you want to pass in a ref variable without first initializing it. C# also supports the params modifier, which allows a method to accept a variable number of parameters.

8.17.1 Passing by Reference


Methods can return only a single value (though that value can be a collection of values). Let's return to the Time class and add a GetTime ( ) method, which returns the hour, minutes, and seconds.

DENOTE: Java programmers take note: In C#, there is no need for wrapper classes for basic types like int (integer). Instead, use reference parameters Because we cannot return three values, perhaps we can pass in three parameters, let the method modify the parameters, and examine the result in the calling method

352

All Rights Reserved To EaglesGroup

Lets work it out Using Returning values in parameters

Example 8-7.Using Returning values in parameters

Example Try it out Eagles ReturningParameters Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles ReturningParameters in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using Returning values in parameters 2. Add the following code in the Program.cs as follows: namespace Eagles_ReturningParameters { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class EaglesTime { // private member variables private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second;

All Rights Reserved To EaglesGroup

353

// public accessor methods public void DisplayCurrentTime( ) { System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}",Month, Date, Year, Hour, Minute, Second); } public int GetHour( ) { return Hour; } public void GetTime(int h, int m, int s) { h = Hour; m = Minute; s = Second; } // constructor public EaglesTime(System.DateTime dt) { Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; } }

354

All Rights Reserved To EaglesGroup

3. Add the following code in the Static Void Main() as follows: ystem.DateTime currentTime = System.DateTime.Now; EaglesTime t = new EaglesTime(currentTime); t.DisplayCurrentTime(); int theHour = 0; int theMinute = 0; int theSecond = 0; t.GetTime(theHour, theMinute, theSecond); System.Console.WriteLine("Current time: {0}:{1}:{2}", theHour, theMinute, theSecond);

4. Now run the program and you will have the output like this:

Now lets see how the above code works:

Notice that the "Current time" in the output is 0:0:0. Clearly, this first attempt did not work. The problem is with the parameters. We pass in three integer parameters to GetTime( ), and we modify the parameters in GetTime( ), but when the values are accessed back in Main( ), they are unchanged. This is because integers are value types, and so are passed by value; a copy is made in GetTime( ). What we need is to pass these values by reference. Two small changes are required. First, change the parameters of the GetTime( ) method to indicate that the parameters are ref (reference) parameters:

All Rights Reserved To EaglesGroup

355

public void GetTime(ref int h, ref int m, ref int s) { h = Hour; m = Minute; s = Second; }

Second, modify the call to GetTime ( ) to pass the arguments as references as well: t.GetTime (ref theHour, ref theMinute, ref theSecond);

If you leave out the second step of marking the arguments with the keyword ref, the compiler will complain that the argument cannot be converted from an int to a ref int. The results now show the correct time. By declaring these parameters to be ref parameters, you instruct the compiler to pass them by reference. Instead of a copy being made, the parameter in GetTime ( ) is a reference to the same variable (theHour) that is created in Main( ). When you change these values in GetTime ( ), the change is reflected in Main( ). Keep in mind that ref parameters are references to the actual original valueit is as if you said, "Here, work on this one." Conversely, value parameters are copiesit is as if you said, "Here, work on one just like this."

8.17.2 Passing out Parameters with Definite Assignment

C# imposes definite assignment, which requires that all variables be assigned a value before they are used, Example 8.7, if you don't initialize theHour, theMinute, and theSecond before you pass them as parameters to GetTime ( ), the compiler will complain. Yet the initialization that is done merely sets their values to 0 before they are passed to the method:

356

All Rights Reserved To EaglesGroup

int theHour = 0; int theMinute = 0; int theSecond = 0; t.GetTime( ref theHour, ref theMinute, ref theSecond);

It seems silly to initialize these values because you immediately pass them by reference into GetTime where they'll be changed, but if you don't, the following compiler errors are reported: Use of unassigned local variable 'theHour' Use of unassigned local variable 'theMinute' Use of unassigned local variable 'theSecond'

C# provides the out parameter modifier for this situation. The out modifier removes the requirement that a reference parameter be initialized. The parameters to GetTime( ), for example, provide no information to the method; they are simply a mechanism for getting information out of it. Thus, by marking all three as out parameters, you eliminate the need to initialize them outside the method. Within the called method, the out parameters must be assigned a value before the method returns. Here are the altered parameter declarations for GetTime ( ): public void GetTime(out int h, out int m, out int s) { h = Hour; m = Minute; s = Second; } And here is the new invocation of the method in Main( ): t.GetTime( out theHour, out theMinute, out theSecond);

All Rights Reserved To EaglesGroup

357

To summarize, value types are passed into methods by value. ref parameters are used to pass value types into a method by reference. This allows you to retrieve their modified value in the calling method. Out parameters are used only to return information from a method Lets work it out Using in, out, and ref parameters

Example 8-8.Using in, out, and ref parameters

Example Try it out Eagles Using3Parameters Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles Using3Parameters in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using in, out, and ref parameters 2. Add the following code in the program.cs as follows:

namespace Eagles_Using3Parameters { # region EaglesGroup Console Application /// <EaglesGruop> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program public class EaglesTime { // private member variables private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second;

358

All Rights Reserved To EaglesGroup

// public accessor methods public void DisplayCurrentTime( ) { System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", Month, Date, Year, Hour, Minute, Second); } public int GetHour( ) { return Hour; } public void SetTime(int hr, out int min, ref int sec) { // if the passed in time is >= 30 // increment the minute and set second to 0 // otherwise leave both alone if (sec >= 30) { Minute++; Second = 0; } Hour = hr; // set to value passed in // pass the minute and second back out min = Minute; sec = Second; } // constructor

All Rights Reserved To EaglesGroup

359

public EaglesTime(System.DateTime dt) { Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; } }

static void Main(string[] args) { System.DateTime currentTime = System.DateTime.Now; EaglesTime t = new EaglesTime(currentTime); t.DisplayCurrentTime( ); int theHour = 3; int theMinute; int theSecond = 20; t.SetTime(theHour, out theMinute, ref theSecond); System.Console.WriteLine( "the Minute is now: {0} and {1} seconds", theMinute, theSecond); theSecond = 40; t.SetTime(theHour, out theMinute, ref theSecond); System.Console.WriteLine("the Minute is now: " + "{0} and {1} seconds", theMinute, theSecond); }

360

All Rights Reserved To EaglesGroup

Now lets see how the above program works:


SetTime

is a bit contrived, but it illustrates the three types of parameters. theHour is passed in as a value parameter; its entire job is to set the member variable Hour, and no value is returned using this parameter. The ref parameter theSecond is used to set a value in the method. If theSecond is greater than or equal to 30, the member variable Second is reset to 0 and the member variable Minute is incremented. DENOTE: C and C++ programmers take note: In C#, you must specify ref on both the call and the destination when using reference parameters

Finally, theMinute is passed into the method only to return the value of the member variable Minute, and thus is marked as an out parameter. It makes perfect sense that theHour and theSecond must be initialized; their values are needed and used. It is not necessary to initialize theMinute, as it is an out parameter that exists only to return a value. What at first appeared to be arbitrary and capricious rules now make sense; values are only required to be initialized when their initial value is meaningful.

8.18 Overloading Methods and Constructors


Often you'll want to have more than one function with the same name. The most common example of this is to have more than one constructor. In the examples shown so far, the constructor has taken a single parameter: a DateTime object. It would be convenient to be able to set new Time objects to an arbitrary time by passing in year, month, date, hour, minute, and second values. It would be even more convenient if some clients could use one constructor, and other clients could use the other constructor. Function overloading provides for exactly these contingencies. The signature of a method is defined by its name and its parameter list. Two methods differ in their signatures if they have different names or different parameter lists. Parameter lists can differ by having different numbers or types of parameters. For example, in the following code the first method differs from the second in the number of parameters, and the second differs from the third in the types of parameters:

All Rights Reserved To EaglesGroup

361

void myMethod(int p1); void myMethod(int p1, int p2); void myMethod(int p1, string s1);

A class can have any number of methods, as long as each one's signature differs from that of all the others Example 8.9 illustrates our Time class with two constructors: one that takes a DateTime object, and the other that takes six integers Lets work it out Using overloading the constructor

Example 8-9.Using overloading the constructor

Example Try it out Eagles overloadingconstructor Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles overloadingconstructor in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using overloading the constructor 2. Add the following code in the Program.cs as follows: namespace Eagles_overloadingconstructor { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class EaglesTime { // private member variables

362

All Rights Reserved To EaglesGroup

private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second; // public accessor methods public void DisplayCurrentTime( ) { System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", Month, Date, Year, Hour, Minute, Second); } // constructors public EaglesTime(System.DateTime dt) { Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; } public EaglesTime(int Year, int Month, int Date, int Hour, int Minute, int Second) { this.Year = Year; this.Month = Month; this.Date = Date; this.Hour = Hour; this.Minute = Minute; this.Second = Second; } } static void Main(string[] args) { System.DateTime currentTime = System.DateTime.Now; EaglesTime t = new EaglesTime(currentTime); t.DisplayCurrentTime(); EaglesTime t2 = new EaglesTime(2005, 11, 18, 11, 03, 30); t2.DisplayCurrentTime(); }

All Rights Reserved To EaglesGroup

363

3. Now run the program and the you should have the output like this:

Now lets see how the above code works: As you can see, the Time class in Example 8-9 has two constructors. If a function's signature consisted only of the function name, the compiler would not know which constructors to call when constructing t1 and t2. However, because the signature includes the function argument types, the compiler is able to match the constructor call for t1 with the constructor whose signature requires a DateTime object. Likewise, the compiler is able to associate the t2 constructor call with the constructor method whose signature specifies six integer arguments. When you overload a method, you must change the signature i.e., the name, number, or type of the parameters. You are free, as well, to change the return type, but this is optional. Changing only the return type does not overload the method, and creating two methods with the same signature but differing return types will generate a compile error. This is illustrated in Example 8-10.

364

All Rights Reserved To EaglesGroup

Lets work it out Using varying the return type on overload methods.

Example 8-10 Using the varying return type on overload methods.

Example Try it out Eagles overloadmethods Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles overloadmethods in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using varying the return type on overload methods 2. Add the Following code into the Program.cs as follows:

amespace Eagles_overloadmethods { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class Eagles { private int Triple(int val) { return 3 * val; } private long Triple(long val) { return 3 * val; }

All Rights Reserved To EaglesGroup

365

public void Test() { int x = 5; int y = Triple(x); System.Console.WriteLine("x: {0} y: {1}", x, y); long lx = 10; long ly = Triple(lx); System.Console.WriteLine("lx: {0} ly: {1}", lx, ly); } static void Main(string[] args) { Eagles E = new Eagles(); E.Test(); } } 3. Run the Application and you should have the output like this:

366

All Rights Reserved To EaglesGroup

In this example, the Tester class overloads the Triple ( ) method, one to take an integer, the other to take a long. The return type for the two Triple ( ) methods varies. Although this is not required, it is very convenient in this case.

8.19 Encapsulating Data with Properties


Properties allow clients to access class state as if they were accessing member fields directly, while actually implementing that access through a class method. This is ideal. The client wants direct access to the state of the object and does not want to work with methods. The class designer, however, wants to hide the internal state of his class in class members, and provide indirect access through a method. By decoupling the class state from the method that accesses that state, the designer is free to change the internal state of the object as needed. When the Time class is first created, the Hour value might be stored as a member variable. When the class is redesigned, the Hour value might be computed or retrieved from a database. If the client had direct access to the original Hour member variable, the change to computing the value would break the client. By decoupling and forcing the client to go through a method (or property), the Time class can change how it manages its internal state without breaking client code. Properties meet both goals: they provide a simple interface to the client, appearing to be a member variable. They are implemented as methods, however, providing the data-hiding required by good object-oriented design, as illustrated in Example 8-11 Lets work it out Using a Property

Example 8-11. Using a property

Example Try it out Eagles property Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles property in the directory C:\EaglesVisualCSharp\Chapter 8\Example Using a Property

All Rights Reserved To EaglesGroup

367

2. Add the following code in the program.cs as follows: namespace Eagles_property { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class EaglesTime { // private member variables private int year; private int month; private int date; private int hour; private int minute; private int second; // public accessor methods public void DisplayCurrentTime() { System.Console.WriteLine( "Time\t: {0}/{1}/{2} {3}:{4}:{5}", month, date, year, hour, minute, second); } // constructors public EaglesTime(System.DateTime dt) { year = dt.Year; month = dt.Month; date = dt.Day; hour = dt.Hour; minute = dt.Minute; second = dt.Second; } // create a property 368
All Rights Reserved To EaglesGroup

public int Hour { get { return hour; } set { hour = value; } } } static void Main(string[] args) { System.DateTime currentTime = System.DateTime.Now; EaglesTime E = new EaglesTime(currentTime); E.DisplayCurrentTime(); int theHour = E.Hour; System.Console.WriteLine("\nRetrieved the hour: {0}\n", theHour); theHour++; E.Hour = theHour; System.Console.WriteLine("Updated the hour: {0}\n", theHour); }

All Rights Reserved To EaglesGroup

369

3. Run the program and you will have the output like this:

Now lets see how the above program works: To declare a property, write the property type and name followed by a pair of braces. Within the braces you may declare get and set accessor. Neither of these has explicit parameters, though the set ( ) method has an implicit parameter value as shown next. In Example 8-11, Hour is a property. Its declaration creates two accessor: get and set. public int Hour { get { return hour; } set { hour = value; } }

370

All Rights Reserved To EaglesGroup

Each accessor has an accessor-body that does the work of retrieving and setting the property value. The property value might be stored in a database (in which case the accessor-body would do whatever work is needed to interact with the database), or it might just be stored in a private member variable: private int hour;

8.19.1 The get Accessor


The body of the get accessor is similar to a class method that returns an object of the type of the property. In the example, the accessor for Hour is similar to a method that returns an int. It returns the value of the private member variable in which the value of the property has been stored: get { return hour; } In this example, a local int member variable is returned, but you could just as easily retrieve an integer value from a database, or compute it on the fly. Whenever you reference the property (other than to assign to it), the get accessor is invoked to read the value of the property: Time t = new Time(currentTime); int theHour = t.Hour;

In this example, the value of the Time object's Hour property is retrieved, invoking the get accessor to extract the property, which is then assigned to a local variable.

All Rights Reserved To EaglesGroup

371

8.19.2 The set Accessor:

The set accessor sets the value of a property and is similar to a method that returns void. When you define a set accessor, you must use the value keyword to represent the argument whose value is passed to and stored by the property. set { hour = value; }

Here, again, a private member variable is used to store the value of the property, but the set accessor could write to a database or update other member variables as needed. When you assign a value to the property, the set accessor is automatically invoked, and the implicit parameter value is set to the value you assign: theHour++; t.Hour = theHour; The advantage of this approach is that the client can interact with the properties directly, without sacrificing the data-hiding and encapsulation sacrosanct in good object-oriented design

8. 20 Read-only Fields
You might want to create a version of the Time class that is responsible for providing public static values representing the current time and date. Example 8-12 illustrates a simple approach to this problem. Lets work it out Using Static public Constants

Example 8-12. Using Static public Constants

Example Try it out Eagles publicconstants Step by Step Example: Using Version 2005

372

All Rights Reserved To EaglesGroup

1. Create a new Console Application name it as Eagles publicconstants in the directory 2:\EaglesVisualCSharp\Chapter 8\Example Using Static public Constants 2. Add the following Code in the Program.cs as follows: namespace Eagles_publicconstants { # region EaglesGroup Console Application /// <EaglesGroup> /// Somu /// Siddhu /// Sri /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { public class RightNow { // public member variables public static int Year; public static int Month; public static int Date; public static int Hour; public static int Minute; public static int Second; static RightNow() { System.DateTime dt = System.DateTime.Now; Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; } } static void Main(string[] args) { System.Console.WriteLine("This year: {0}", RightNow.Year.ToString()); RightNow.Year = 2006; System.Console.WriteLine("This year: {0}", RightNow.Year.ToString()); }

All Rights Reserved To EaglesGroup

373

3. Now Run the program and you should have something like this:

Now lets see hoe the above program works: This works well enough, until someone comes along and changes one of these values. As the example shows, the RightNow.Year value can be changed, for example, to 2006. This is clearly not what we'd like. We'd like to mark the static values as constant, but that is not possible, because we don't initialize them until the static constructor is executed. C# provides the keyword readonly for exactly this purpose. If you change the class member variable declarations as follows: public static readonly int Year; public static readonly int Month; public static readonly int Date; public static readonly int Hour; public static readonly int Minute; public static readonly int Second;

Then comment out the reassignment in Main ( ): // RightNow.Year = 2008; // error! The program will compile and run as intended.

374

All Rights Reserved To EaglesGroup

Summary:
In this Chapter we had been looked the Classes and Objects and their uses in the C# as well and the sub topics and the topics so far covered are:

Introduction to Classes and Objects: 8.1.2 Access Modifiers: 8.1. 3 Method Arguments 8.2 Creating Objects 8.2.1 Constructors 8.2.2 Constructors 8.3 Initializers 8.3 Copy Constructors 8.4 The ICloneable Interface 8.6 The this Keyword 8.7 Using Static Members 8.8 Invoking Static Methods 8.9 Using Static Constructors 8.10 Using Private Constructors 8.11 Using Static Fields 8.12 Destroying Objects 8.13 The C# Destructor 8.14 Destructors Versus Dispose 8.15 Implementing the Close( ) Method 8.16 The using Statement 8.17 Passing Parameters 8.17.1 Passing by Reference 8.17.2 Passing Out Parameters with Definite Assignment 8.18 Overloading Methods and Constructors 8.19 Encapsulating Data with Properties 8.19.1 The get Accessor 8.19.2 The set Accessor 8. 20 Read-only Fields

All Rights Reserved To EaglesGroup

375

Chapter 09

376

All Rights Reserved To EaglesGroup

Structs
9.1 Introduction to Struts
A struct is a simple user-defined type, a lightweight alternative to classes. Structs are similar to classes in that they may contain constructors, properties, methods, fields, operators, nested types, and indexers There are also significant differences between classes and structs. For instance, structs don't support inheritance or destructors. More important, although a class is a reference type, a struct is a value type. Thus, structs are useful for representing objects that do not require reference semantics. The consensus view is that you ought to use structs only for types that are small, simple, and similar in their behavior and characteristics to built-in types DENOTE: C and C++ programmers take note: The meaning of C#'s struct construct is very different from C++'s. It permits C# to step outside the single-inheritance Object hierarchy and is particularly useful when interfacing with libraries written in C++. Structs are somewhat more efficient in their use of memory in arrays. However, they can be less efficient when used in collections. Collections expect references, and structs must be boxed. There is overhead in boxing and unboxing, and classes might be more efficient in large collections. In this chapter, you will learn how to define and work with structs, and how to use constructors to initialize their values.

All Rights Reserved To EaglesGroup

377

9.2 Defining Structs


The syntax for declaring a struct is almost identical to that for a class: [attributes ] [access-modifiers ] struct identifier [:interface-list ] { struct-members }

Example 9.1 illustrates the definition of a struct. Location represents a point on a twodimensional surface. Notice that the struct Location is declared exactly as a class would be, except for the use of the keyword struct. Also notice that the Location constructor takes two integers and assigns their value to the instance members, x and y. The x and y coordinates of Location are declared as properties.

378

All Rights Reserved To EaglesGroup

Example 9-1.Creating a struct

Example Try it out Eagles CreatingStruct Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles CreatingStruct in the directory C:\EaglesVisualCSharp\Chapter 9\Example CreatingStruct 2. Declare a variable as follows in the constructor of the program.cs public struct Location { private int xVal; private int yVal;

3. Enter the following code into the program.cs body as follows:

public Location(int xCoordinate, int yCoordinate) { xVal = xCoordinate; yVal = yCoordinate; } public int x { get { return xVal; } set { xVal = value; } }

All Rights Reserved To EaglesGroup

379

public int y { get { return yVal; } set { yVal = value; } } public override string ToString( ) { return (String.Format("{0}, {1}", xVal,yVal)); } public void myFunc(Location loc) { loc.x = 50; loc.y = 100; Console.WriteLine("In MyFunc loc: {0}", loc); } static void Main(string[] args) { Location loc1 = new Location(200, 300); Console.WriteLine("Loc1 location: {0}", loc1); Tester t = new Tester(); t.myFunc(loc1); Console.WriteLine("Loc1 location: {0}", loc1); } }

380

All Rights Reserved To EaglesGroup

4. Now run the program and you should have the output like this:

Unlike classes, structs do not support inheritance. They implicitly derive from object (as do all types in C#, including the built-in types) but cannot inherit from any other class or struct. Structs are also implicitly sealed (that is, no class or struct can derive from a struct). Like classes, however, structs can implement multiple interfaces. Additional differences include the following:

No destructor or custom default constructor


Structs cannot have destructors, nor can they have a custom parameter less (default) constructor. If you do not supply a constructor, your struct will in effect be provided with a default constructor that will zero all the data members or set them to default values appropriate to their type. If you supply any constructor, you must initialize all the fields in the struct. No initialization You cannot initialize an instance field in a struct. Thus it is illegal to write: private int xVal = 50; private int yVal = 100;

Though that would have been fine had this been a class.

All Rights Reserved To EaglesGroup

381

Structs are designed to be simple and lightweight. While private member data promotes data hiding and encapsulation, some programmers feel it is overkill for structs. They make the member data public, thus simplifying the implementation of the struct. Other programmers feel that properties provide a clean and simple interface, and that good programming practice demands data-hiding even with simple lightweight objects. Whichever you choose is a matter of design philosophy; the language supports either approach.

9.3 Creating Structs


Create an instance of a struct by using the new keyword in an assignment statement, just as you would for a class. In Example 9-1, the Tester class creates an instance of Location as follows: Location loc1 = new Location(200,300);

Here the new instance is named loc1 and is passed two values, 200 and 300.

9.3.1 Structs as Value Types


The definition of the Tester class in Example 9-1 includes a Location object (loc1) created with the values 200 and 300. This line of code calls the Location constructor: Location loc1 = new Location(200,300); Then WriteLine( ) is called: Console.WriteLine("Loc1 location: {0}", loc1);

WriteLine ( )

is expecting an object, but, of course, Location is a struct (a value type). The compiler automatically boxes the struct (as it would any value type), and it is the boxed object that is passed to WriteLine ( ). ToString ( ) is called on the boxed object, and because the struct (implicitly) inherits from object, it is able to respond polymorphically, overriding the method just as any other object might: Loc1 location: 200, 300

382

All Rights Reserved To EaglesGroup

Structs are value objects, however, and when passed to a function, they are passed by valueas seen in the next line of code, in which the loc1 object is passed to the myFunc( ) method: t.myFunc (loc1);

In myFunc ( ), new values are assigned to x and y, and these new values are printed out: Loc1 location: 50, 100

When you return to the calling function (Main ( )) and call WriteLine ( ) again, the values are unchanged: Loc1 location: 200, 300 The struct was passed as a value object, and a copy was made in myFunc( ). Try changing the declaration to class: public class Location

And run the test again. Here is the output:

Loc1 location: 200, 300 In MyFunc loc: 50, 100 Loc1 location: 50, 100

This time the Location object has reference semantics. Thus, when the values are changed in myFunc ( ), they are changed on the actual object back in Main ( ).

All Rights Reserved To EaglesGroup

383

9.3.2 Calling the Default Constructor


As mentioned earlier, if you do not create a constructor, an implicit default constructor is called by the compiler. We can see this if we comment out the constructor: /* public Location(int xCoordinate, int yCoordinate) { xVal = xCoordinate; yVal = yCoordinate; } */ And replace the first line in Main ( ) with one that creates an instance of Location without passing values: // Location loc1 = new Location(200,300); Location loc1 = new Location( );

Because there is now no constructor at all, the implicit default constructor is called. The output looks like this: Loc1 location: 0, 0 In MyFunc loc: 50, 100 Loc1 location: 0, 0

The default constructor has initialized the member variables to zero. DENOTE: C++ programmers take note: In C#, the new keyword does not always create objects on the heap. Classes are created on the heap, and structs are created on the stack. Also, when new is omitted (as you will see in the next section), a constructor is never called. Because C# requires definite assignment, you must explicitly initialize all the member variables before using the struct.

384

All Rights Reserved To EaglesGroup

9.3.4 Creating Structs Without new


Because loc1 is a struct (not a class), it is created on the stack. Thus, in Example 9-1, when the new operator is called: Location loc1 = new Location(200,300);

The resulting Location object is created on the stack. The new operator calls the Location constructor. However, unlike with a class, it is possible to create a struct without using new at all. This is consistent with how built-in type variables (such as int) are defined, and is illustrated in Example 9-2.

DENOTE: A caveat: I am demonstrating how to create a struct without using new because it differentiates C# from C++, and also differentiates how C# treats classes versus structs. That said, however, creating structs without the keyword new brings little advantage and can create programs that are harder to understand, more error prone, and more difficult to maintain. Proceed at your own risk.

All Rights Reserved To EaglesGroup

385

Example 9-2.Creating a struct without using new

Example Try it out Eagles CreatingStruct Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles Struct in the directory C:\EaglesVisualCSharp\Chapter 9\Example Creating a struct without using new 2. Enter the following code in the body of the program.cs as follows:

public struct Location { public int xVal; public int yVal; public Location(int xCoordinate, int yCoordinate) { xVal = xCoordinate; yVal = yCoordinate; } public int x { get { return xVal; } set { xVal = value; } }

386

All Rights Reserved To EaglesGroup

public int y { get { return yVal; } set { yVal = value; } } public override string ToString() { return (String.Format("{0}, {1}", xVal, yVal)); } } public class Tester { static void Main(string[] args) { Location loc1; // no call to the constructor loc1.xVal = 75; // initialize the members loc1.yVal = 225; Console.WriteLine(loc1); } }

All Rights Reserved To EaglesGroup

387

3. Now run the application and you should have the output like this:

In Example 9-2, you initialize the local variables directly, before calling a method of loc1 and before passing the object to WriteLine( ): loc1.xVal = 75; loc1.yVal = 225;

If you were to comment out one of the assignments and recompile: static void Main( ) { Location loc1; loc1.xVal = 75; // loc1.yVal = 225; Console.WriteLine(loc1); } You would get a compiler error: Use of unassigned local variable 'loc1' Once you assign all the values, you can access the values through the properties x and y:

388

All Rights Reserved To EaglesGroup

static void Main( ) { Location loc1; loc1.xVal = 75; // assign member variable loc1.yVal = 225; // assign member variable loc1.x = 300; // use property loc1.y = 400; // use property Console.WriteLine(loc1); }

Be careful about using properties. Although these allow you to support encapsulation by making the actual values private, the properties themselves are actually member methods, and you cannot call a member method until you initialize all the member variables.

Summary:
In this chapter we see about struts and creating structs and many more things as the topics are covered are as follows: Introduction Defining Structs Creating Structs Structs as Value Types Calling the Default Constructor Creating Structs Without new

All Rights Reserved To EaglesGroup

389

Chapter 10

390

All Rights Reserved To EaglesGroup

Interfaces
10.1Introduction to Interfaces
An interface is a contract that guarantees to a client how a class or struct will behave. When a class implements an interface, it tells any potential client "I guarantee I'll support the methods, properties, events, and indexers of the named interface." An interface offers an alternative to an abstract class for creating contracts among classes and their clients. These contracts are made manifest using the interface keyword, which declares a reference type that encapsulates the contract. Syntactically, an interface is like a class that has only abstract methods. An abstract class serves as the base class for a family of derived classes, while interfaces are meant to be mixed in with other inheritance trees. When a class implements an interface, it must implement all the methods of that interface; in effect the class says "I agree to fulfill the contract defined by this interface." DENOTE: Java programmers take note: C# does not support the use of constant fields (member constants) in interfaces. Inheriting from an abstract class implements this-a relationship. Implementing an interface defines a different relationship that we've not seen until now: the implements relationship. These two relationships are subtly different. A car is-a vehicle, but it might implement the CanBeBoughtWithABigLoan capability (as can a house, for example). In this chapter, you will learn how to create, implement, and use interfaces. You'll learn how to implement multiple interfaces, and how to combine and extend interfaces, as well as how to test whether a class has implemented an interface.

All Rights Reserved To EaglesGroup

391

10.2 Implementing an Interface


The syntax for defining an interface is as follows: [attributes] [access-modifier] interface interface-name [:base-list] {interfacebody}

The interface keyword is followed by the name of the interface. It is common but not required to begin the name of your interface with a capital I thus, IStorable, ICloneable, IClaudius, etc. The interface-body is the implementation of the interface, as described next. Suppose you wish to create an interface that describes the methods and properties a class needs to be stored to and retrieved from a database or other storage such as a file. You decide to call this interface IStorable. In this interface you might specify two methods: Read ( ) and Write ( ), which appear in the interface-body: interface IStorable { void Read( ); void Write(object); }

The purpose of an interface is to define the capabilities that you want to have available in a class. For example, you might create a class, Document. It turns out that Document types can be stored in a database, so you decide to have Document implement the IStorable interface. To do so, use the same syntax as if the new Document class were inheriting from IStorablea colon (:), followed by the interface name:

392

All Rights Reserved To EaglesGroup

public class Document : IStorable { public void Read( ) {...} public void Write(object obj) {...} // ... } It is now your responsibility, as the author of the Document class, to provide a meaningful implementation of the IStorable methods. Having designated Document as implementing IStorable, you must implement all the IStorable methods, or you will generate an error when you compile. This is illustrated in Example 101, in which the Document class implements the IStorable interface.

Lets work it out Using a simple interface

Example 10-1.Using a simple interface

Example Try it out Eagles SimpleInterface Step by Step Example: Using Version 2005
1. Create a new Console application name it as Eagles SimpleInterface in the directory C:\EaglesVisualCSharp\Chapter 10\Example Using SimpleInterface 2. Add the following code into the body of the Program.cs as follows: namespace Eagles_SimpleInterface { class Program { interface IStorable { // no access modifiers, methods are public // no implementation void Read(); void Write(object obj); int Status { get; set; } }
All Rights Reserved To EaglesGroup

393

// create a class which implements the IStorable interface public class Document : IStorable { // store the value for the property private int status = 0; public Document(string s) { Console.WriteLine("Creating document with: {0}", s); } // implement the Read method public void Read( ) { Console.WriteLine("Implementing the Read Method for IStorable"); } // implement the Write method public void Write(object o) { Console.WriteLine("Implementing the Write Method for IStorable"); }

// implement the property public int Status { get { return status; } set { status = value; } } } // Take our interface out for a spin

394

All Rights Reserved To EaglesGroup

3. Now add the following code in the Static Main () as follows:

static void Main(string[] args) { // access the methods in the Document object Document doc = new Document("Test Document"); doc.Status = -1; doc.Read(); Console.WriteLine("Document Status: {0}", doc.Status); } Now lets see how the above code works: Example 10.1 defines a simple interface, IStorable, with two methods (Read ( ) and Write ( )) and a property (Status)

Of type integer. Notice that the property declaration does not provide an implementation for get ( ) and set ( ), but simply designates that there is a get ( ) and a set ( ): int Status { get; set; }

Notice also that the IStorable method declarations do not include access modifiers (e.g., public, protected, internal, private). In fact, providing an access modifier generates a compile error. Interface methods are implicitly public because an interface is a contract meant to be used by other classes. You cannot create an instance of an interface; instead you instantiate a class that implements the interface. The class implementing the interface must fulfill the contract exactly and completely. Document must provide both a Read ( ) and a Write ( ) method and the Status property. How it fulfills these requirements, however, is entirely up to the Document class. Although IStorable dictates that Document must have a Status property, it does not know or care whether Document stores the actual status as a member variable or looks it up in a database. The details are up to the implementing class.

All Rights Reserved To EaglesGroup

395

10.2.1 Implementing More Than One Interface


Classes can implement more than one interface. For example, if your Document class can be stored and it also can be compressed, you might choose to implement both the IStorable and ICompressible interfaces. To do so, change the declaration (in the base-list) to indicate that both interfaces are implemented, separating the two interfaces with commas:

public class Document : IStorable, ICompressible Having done this, the Document class must also implement the methods specified by the ICompressible interface (which is declared in Example 10-2): public void Compress( ) { Console.WriteLine ("Implementing the Compress Method"); } public void Decompress( ) { Console.WriteLine ("Implementing the Decompress Method"); }

10.2.2 Extending Interfaces


It is possible to extend an existing interface to add new methods or members, or to modify how existing members work. For example, you might extend ICompressible with a new interface, ILoggedCompressible, which extends the original interface with methods to keep track of the bytes saved: interface ILoggedCompressible : ICompressible { void LogSavedBytes( ); } Classes are now free to implement either ICompressible or ILoggedCompressible, depending on whether they need the additional functionality. If a class does implement ILoggedCompressible, it must implement all the methods of both ILoggedCompressible and

396

All Rights Reserved To EaglesGroup

ICompressible. ICompressible.

Objects of that type can be cast either to ILoggedCompressible or to

10.2.3 Combining Interfaces


Similarly, you can create new interfaces by combining existing interfaces and, optionally, adding new methods or properties. For example, you might decide to create IStorableCompressible. This interface would combine the methods of each of the other two interfaces, but would also add a new method to store the original size of the precompressed item: interface IStorableCompressible : IStoreable, ILoggedCompressible { void LogOriginalSize( ); } Lets work it out Extending and combining interfaces

Example 10-2.Extending and Combining Interfaces

Example Try it out Eagles CombiningInterfaces Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles CombiningInterfaces in the Directory C:\EaglesVisualCSharp\Chapter 10\Example Extending and combining interfaces 2. Now add the following code in the body of the program.cs as follows: namespace Eagles_CombiningInterfaces { class Program { interface IStorable { void Read( ); void Write(object obj); int Status { get; set; } } // here's the new interface

All Rights Reserved To EaglesGroup

397

interface ICompressible { void Compress( ); void Decompress( ); } // Extend the interface interface ILoggedCompressible : ICompressible { void LogSavedBytes( ); } // Combine Interfaces interface IStorableCompressible : IStorable, ILoggedCompressible { void LogOriginalSize( ); } // yet another interface interface IEncryptable { void Encrypt( ); void Decrypt( ); }

public class Document : IStorableCompressible, IEncryptable { // hold the data for IStorable's Status property private int status = 0; // the document constructor public Document(string s) { Console.WriteLine("Creating document with: {0}", s); } // implement IStorable

398

All Rights Reserved To EaglesGroup

public void Read( ) { Console.WriteLine( "Implementing the Read Method for IStorable"); } public void Write(object o) { Console.WriteLine( "Implementing the Write Method for IStorable"); } public int Status { get { return status; } set { status = value; } } // implement ICompressible public void Compress( ) { Console.WriteLine("Implementing Compress"); } public void Decompress( ) { Console.WriteLine("Implementing Decompress"); } // implement ILoggedCompressible public void LogSavedBytes( ) { Console.WriteLine("Implementing LogSavedBytes"); }

All Rights Reserved To EaglesGroup

399

// implement IStorableCompressible public void LogOriginalSize( ) { Console.WriteLine("Implementing LogOriginalSize"); } // implement IEncryptable public void Encrypt( ) { Console.WriteLine("Implementing Encrypt"); } public void Decrypt( ) { Console.WriteLine("Implementing Decrypt"); } }

3. Now add the following code in the Main () method as follows:

static void Main(string[] args) { // create a document object Document doc = new Document("Test Document"); // cast the document to the various interfaces IStorable isDoc = doc as IStorable; if (isDoc != null) { isDoc.Read( ); } else Console.WriteLine("IStorable not supported"); ICompressible icDoc = doc as ICompressible;

400

All Rights Reserved To EaglesGroup

if (icDoc != null) { icDoc.Compress( ); } else Console.WriteLine("Compressible not supported"); ILoggedCompressible ilcDoc = doc as ILoggedCompressible; if (ilcDoc != null) { ilcDoc.LogSavedBytes( ); ilcDoc.Compress( ); // ilcDoc.Read( ); } else Console.WriteLine("LoggedCompressible not supported"); IStorableCompressible isc = doc as IStorableCompressible; if (isc != null) { isc.LogOriginalSize( ); // IStorableCompressible isc.LogSavedBytes( ); // ILoggedCompressible isc.Compress( ); // ICompressible isc.Read( ); // IStorable } else { Console.WriteLine("StorableCompressible not supported"); } IEncryptable ie = doc as IEncryptable; if (ie != null) { ie.Encrypt( ); } else Console.WriteLine("Encryptable not supported"); } } }

All Rights Reserved To EaglesGroup

401

4. Now run the application and you should have the output like this:

Lets see how the above code works: The Program starts by implementing the IStorable interface and the ICompressible interface. The latter is extended to ILoggedCompressible and then the two are combined into IStorableCompressible. Finally, the example adds a new interface, IEncryptable. The Eagles_CombiningInterfaces program creates a new Document object and then casts it to the various interfaces. When the object is cast to ILoggedCompressible, you can use the interface to call methods on Icompressible because ILoggedCompressible extends (and thus subsumes) the methods from the base interface: ILoggedCompressible ilcDoc = doc as ILoggedCompressible; if (ilcDoc != null) { ilcDoc.LogSavedBytes( ); ilcDoc.Compress( ); // ilcDoc.Read( ); }

402

All Rights Reserved To EaglesGroup

You cannot call Read ( ), however, because that is a method of IStorable, an unrelated interface. And if you uncomment out the call to Read ( ), you will receive a compiler error. If you cast to IStorableCompressible which combines the extended interface with the Storable interface, you can then call methods of IStorableCompressible, Icompressible, and IStorable:

IStorableCompressible isc = doc as IStorableCompressible if (isc != null) { isc.LogOriginalSize( ); // IStorableCompressible isc.LogSavedBytes( ); // ILoggedCompressible isc.Compress( ); // ICompressible isc.Read( ); // IStorable }

10.2.1 Accessing Interface Methods


You can access the members of the IStorable interface as if they were members of the Document class: Document doc = new Document("Test Document"); doc.status = -1; doc.Read( );

You can also create an instance of the interface by casting the document to the interface type, and then use that interface to access the methods: IStorable isDoc = (IStorable) doc; isDoc.status = 0; isDoc.Read( );

All Rights Reserved To EaglesGroup

403

In this case, in Main ( ) you know that Document is in fact an IStorable, so you can take advantage of that knowledge.

As stated earlier, you cannot instantiate an interface directly. That is, you cannot say: IStorable isDoc = new IStorable( );You can, however, create an instance of the implementing class, as in the following: Document doc = new Document("Test Document");You can then create an instance of the interface by casting the implementing object to the interface type, which in this case is IStorable: IStorable isDoc = (IStorable) doc; You can combine these steps by writing: IStorable isDoc = (IStorable) new Document ("Test Document");

In general, it is a better design decision to access the interface methods through an interface reference. Thus, it is better to use isDoc.Read ( ) than doc.Read ( ) in the previous example. Access through an interface allows you to treat the interface polymorphically. In other words, you can have two or more classes implement the interface, and then by accessing these classes only through the interface, you can ignore their real runtime type and treat them interchangeably.

10.1.2.2 Casting to an Interface


In many cases, you don't know in advance that an object supports a particular interface. Given a collection of objects, you might not know whether a particular object supports IStorable or ICompressible or both. You can just cast to the interfaces: Document doc = new Document("Test Document"); IStorable isDoc = (IStorable) doc; isDoc.Read( ); ICompressible icDoc = (ICompressible) doc; icDoc.Compress( );

404

All Rights Reserved To EaglesGroup

If it turns out that Document implements only the IStorable interface: public class Document : IStorable

The cast to ICompressible would still compile because ICompressible is a valid interface. However, because of the illegal cast, when the program is run, an exception will be thrown: An exception of type System.InvalidCastException was thrown.

10.2.3The is Operator
You would like to be able to ask the object if it supports the interface, in order to then invoke the appropriate methods. In C# there are two ways to accomplish this. The first method is to use in the operator. The form of the is operator is: expression is type

The is operator evaluates true if the expression which must be a reference type can be safely cast to type without throwing an exception. The Following Example will illustrates the use of the is operator to test whether a Document implements the IStorable and ICompressible interfaces.

DENOTE: Java programmers take note: The C# is operator is the equivalent of Java's instance of.

All Rights Reserved To EaglesGroup

405

Lets work it out Using the is Operator

Example 10-3 Using the Is Operator

Example Try it out Eagles ISOperator Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles ISOperator in the directory C:\EaglesVisualCSharp\Chapter 10\Example Using the Is Operator. 2. Add the following code in the body of the Program.cs as follows:

namespace Eagles_ISOperator { class Program { interface IStorable { void Read(); void Write(object obj); int Status { get; set; } } // here's the new interface interface ICompressible { void Compress(); void Decompress(); }

406

All Rights Reserved To EaglesGroup

// Document implements IStorable public class Document : IStorable { private int status = 0; public Document(string s) { Console.WriteLine( "Creating document with: {0}", s); } // IStorable.Read public void Read() { Console.WriteLine("Implementing the Read Method for IStorable"); } // IStorable.Write public void Write(object o) { Console.WriteLine("Implementing the Write Method for IStorable"); } // IStorable.Status public int Status { get { return status; } set { status = value; } } }

All Rights Reserved To EaglesGroup

407

3. Now add the following code in the Static Main method as follows:

Document doc = new Document("Eagles Test Document"); // only cast if it is safe if (doc is IStorable) { IStorable isDoc = (IStorable)doc; isDoc.Read(); } // this test will fail if (doc is ICompressible) { ICompressible icDoc = (ICompressible)doc; icDoc.Compress(); }

4. Now run the program and you should have the output like this:

408

All Rights Reserved To EaglesGroup

Now lets see how the above code works: The above program differs from Example 10-2 in that Document no longer implements the ICompressible interface. Main ( ) now determines whether the cast is legal (sometimes referred to as safe) by evaluating the following if clause: if (doc is IStorable)

This is clean and nearly self-documenting. The if statement tells you that the cast will happen only if the object is of the right interface type. Unfortunately, this use of the is operator turns out to be inefficient. To understand why, you need to dip into the MSIL code that this generates. Here is a small excerpt note that the line numbers are in hexadecimal notation: IL_0023: IL_0028: IL_002a: IL_002b: IL_0030: IL_0031: IL_0032: isinst ICompressible brfalse.s IL_0039 ldloc.0 castclass ICompressible stloc.2 ldloc.2 callvirt instance void ICompressible::Compress( )

What is most important here is the test for ICompressible on line 17 in my computer. The keyword isinst is the MSIL code for the is operator. It tests to see if the object (doc) is in fact of the right type. Having passed this test we continue on to line 2b, in which cast class is called. Unfortunately, castclass also tests the type of the object. In effect, the test is done twice. A more efficient solution is to use the as operator.

10.2.4 The as Operator


The as operator combines the is and cast operations by testing first to see whether a cast is valid i.e., whether an is test would return true and then completing the cast when it is. If the cast is not valid i.e., if an is test would return false, the as operator returns null. DENOTE: The keyword null represents a null referenceone that does not refer to any object.

All Rights Reserved To EaglesGroup

409

Using the as operator eliminates the need to handle cast exceptions. At the same time you avoid the overhead of checking the cast twice. For these reasons, it is optimal to cast interfaces using as. The form of the as operator is: expression as type

The following code adapts the Eagles_ISOperator code from Example 10-3, using the as operator and testing for null: static void Main( ) { Document doc = new Document("Test Document"); IStorable isDoc = doc as IStorable; if (isDoc != null) isDoc.Read( ); else Console.WriteLine("IStorable not supported"); ICompressible icDoc = doc as ICompressible; if (icDoc != null) icDoc.Compress( );

else Console.WriteLine("Compressible not supported"); } A quick look at the comparable MSIL code shows that the following version is in fact more efficient: IL_0023: isinst ICompressible IL_0028: stloc.2 IL_0029: ldloc.2 IL_002a: brfalse.s IL_0034 IL_002c: ldloc.2 IL_002d: callvirt instance void ICompressible::Compress( )

410

All Rights Reserved To EaglesGroup

10.2.5 The is Operator Versus the as Operator


If your design pattern is to test the object to see if it is of the type you need, and if so you will immediately cast it, the as operator is more efficient. At times, however, you might want to test the type of an operator but not cast it immediately. Perhaps you want to test it but not cast it at all; you simply want to add it to a list if it fulfills the right interface. In that case, the is operator will be a better choice.

10.2.6 Interface versus Abstract Class


Interfaces are very similar to abstract classes. In fact, you could change the declaration of IStorable to be an abstract class: abstract class Storable { abstract public void Read( ); abstract public void Write( ); }

Document

could now inherit from Storable, and there would not be much difference from using the interface. Suppose, however, that you purchase a List class from a third-party vendor whose capabilities you wish to combine with those specified by Storable? In C++, you could create a StorableList class and inherit from both List and Storable. But in C#, you're stuck; you can't inherit from both the Storable abstract class and also the List class because C# does not allow multiple inheritances with classes. However, C# does allow you to implement any number of interfaces and derive from one base class. Thus, by making Storable an interface, you can inherit from the List class and also from IStorable, as StorableList does in the following example: public class StorableList : List, IStorable { // List methods here ... public void Read( ) {...} public void Write(object obj) {...} // ... }

All Rights Reserved To EaglesGroup

411

10.3.1 Overriding Interface Implementations


An implementing class is free to mark any or all of the methods that implement the interface as virtual. Derived classes can override or provide new implementations. For example, a Document class might implement the IStorable interface and mark the Read ( ) and Write( ) methods as virtual. The Document might Read ( ) and Write ( ) its contents to a File type. The developer might later derive new types from Document, such as a Note or Email Message type, and he might decide that Note will read and write to a database rather than to a file.

The Following Example Program will strips down the complexity of Example 10-3 and illustrates overriding an interface implementation. The Read ( ) method is marked as virtual and implemented by Document. Read ( ) is then overridden in a Note type that derives from Document.

Lets work it out Using Overriding an interface Implementation

Example 10-4 Using overriding an interface Implementation

Example Try it out Eagles overridinginterface Step by Step Example: Using Version 2005

1. Create a new Console Application and name it as Eagles overridinginterface in the directory C:\EaglesVisualCSharp\Chapter 10\Example Using overriding an interface Implementation

412

All Rights Reserved To EaglesGroup

2. Add the following code in the body of the Program.cs as follows:

amespace Eagles_overridinginterface { #region EaglesGroup /// <summary> /// EaglesSiddhu /// Siddhu /// Sri /// All Rights Reserved to EaglesGroup ///(C) EaglesGroup 1978 - 2010 /// </summary> #endregion class Program { // Declare the Interface here interface IStorable { void Read(); void Write(); } // Simplify Document to implement only IStorable public class Document : IStorable { // the document constructor public Document(string s)

All Rights Reserved To EaglesGroup

413

{ Console.WriteLine( "Creating document with: {0}", s); } // Make read virtual public virtual void Read() { Console.WriteLine( "Document Read Method for IStorable"); } // NB: Not virtual! public void Write() { Console.WriteLine( "Document Write Method for IStorable"); } } // Derive from Document public class Note : Document { public Note(string s) : base(s) { Console.WriteLine( "Creating note with: {0}", s); } // override the Read method

414

All Rights Reserved To EaglesGroup

public override void Read() { Console.WriteLine( "Overriding the Read method for Note!"); } // implement my own Write method public new void Write() { Console.WriteLine( "Implementing the Write method for Note!"); } }

3. Now add the following code in the Main () in the Program.cs as follows: static void Main(string[] args) { // create a document object Document theNote = new Note("Test Note"); IStorable isNote = theNote as IStorable; if (isNote != null) { isNote.Read( ); isNote.Write( ); } Console.WriteLine("\n"); // direct call to the methods theNote.Read( ); theNote.Write( ); Console.WriteLine("\n"); // create a note object Note note2 = new Note("Second Test"); IStorable isNote2 = note2 as IStorable; if (isNote2 != null) { isNote2.Read( ); isNote2.Write( ); } Console.WriteLine("\n"); // directly call the methods note2.Read( ); note2.Write( ); }
All Rights Reserved To EaglesGroup

415

4. Now run the application and you will have the output like this:

Now lets see hoe the above program works: In the above example, Document implements a simplified IStorable interface (simplified to make the example clearer): interface IStorable { void Read( ); void Write( ); } The designer of Document has opted to make the Read ( ) method virtual, but not to make the Write ( ) method virtual: public virtual void Read( )

416

All Rights Reserved To EaglesGroup

In a real-world application, you would almost certainly mark both as virtual, but I've differentiated them to demonstrate that the developer is free to pick and choose which methods are made virtual. The new class Note derives from Document: public class Note : Document

It is not necessary for Note to override Read ( ), but it is free to do so and has in fact done so here: public override void Read( )

In Static, the Read and Write methods are called in four ways: Through the base class reference to a derived object Through an interface created from the base class reference to the derived object Through a derived object Through an interface created from the derived object To accomplish the first two calls, a Document (base class) reference is created, and the address of a new Note (derived) object created on the heap is assigned to the Document reference: Document theNote = new Note("Test Note"); An interface reference is created and the as operator is used to cast the Document to the IStorable reference: IStorable isNote = theNote as IStorable; You then invoke the Read ( ) and Write ( ) methods through that interface. The output reveals that the Read ( ) method is responded to polymorphically and the Write ( ) method is not, just as we would expect: Overriding the Read method for Note! Document Write Method for IStorable

All Rights Reserved To EaglesGroup

417

The Read ( ) and Write ( ) methods are then called directly on the object itself: theNote.Read( ); theNote.Write( ); And once again you see the polymorphic implementation has worked: Overriding the Read method for Note! Document Write Method for IStorable In both cases, the Read ( ) method of Note is called and the Write ( ) method of Document is called. To prove to yourself that this is a result of the overriding method, next create a second Note object, this time assigning its address to a reference to a Note. This will be used to illustrate the final cases i.e., a call through a derived object and a call through an interface created from the derived object: Note note2 = new Note("Second Test");

Once again, when you cast to a reference, the overridden Read ( ) method is called. When, however, methods are called directly on the Note object: note2.Read( ); note2.Write( );

The output reflects that you've called a Note and not an overridden Document: Overriding the Read method for Note! Implementing the Write method for Note!

418

All Rights Reserved To EaglesGroup

10.4.1 Explicit Interface Implementation


In the implementation shown so far, the implementing class (in this case, Document) creates a member method with the same signature and return type as the method detailed in the interface. It is not necessary to explicitly state that this is an implementation of an interface; this is understood by the compiler implicitly. What happens, however, if the class implements two interfaces, each of which has a method with the same signature? Example 10-5 creates two interfaces: IStorable and ITalk. The latter implements a Read ( )method that reads a book aloud. Unfortunately, this conflicts with the Read( ) method in IStorable. Because both IStorable and ITalk have a Read( ) method, the implementing Document class must use explicit implementation for at least one of the methods. With explicit implementation, the implementing class (Document) explicitly identifies the interface for the method: void ITalk.Read( ) This resolves the conflict, but it creates a series of interesting side effects. First, there is no need to use explicit implementation with the other method of Talk( ): public void Talk( ) Because there is no conflict, this can be declared as usual. More importantly, the explicit implementation method cannot have an access modifier: void ITalk.Read( ) This method is implicitly public. In fact, a method declared through explicit implementation cannot be declared with the abstract, virtual, override, or new modifiers. Most important, you cannot access the explicitly implemented method through the object itself. When you write: theDoc.Read( ); The compiler assumes you mean the implicitly implemented interface for IStorable. The only way to access an explicitly implemented interface is through a cast to an interface:

All Rights Reserved To EaglesGroup

419

ITalk itDoc = theDoc as ITalk; if (itDoc != null) { itDoc.Read( ); }

Explicit implementation is demonstrated in the following Example Lets work it out Using Explicit Implementation

Example 10-5 Using Explicit Implementation

Example Try it out Eagles ExplicitImplemention Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles ExplicitImplemention in the directory C:\EaglesVisualCSharp\Chapter 10\Example Using Explicit Implementation 2. Add the following code in the body of the Program.cs as follows:
namespace Eagles_ExplicitImplemention { # region EaglesGroup /// <summary> /// EaglesSiddhu /// Siddhu /// Sri /// All Rights Reserved To EaglesGroup /// (C) EaglesGroup 1978 - 2010 /// </summary> # endregion class Program { interface IStorable { void Read(); void Write(); }

420

All Rights Reserved To EaglesGroup

interface ITalk { void Talk(); void Read(); } // Modify Document to implement IStorable and ITalk public class Document : IStorable, ITalk { // the document constructor public Document(string s) { Console.WriteLine("Creating document with: {0}", s); } // Make read virtual public virtual void Read() { Console.WriteLine("Implementing IStorable.Read"); } public void Write() { Console.WriteLine("Implementing IStorable.Write"); } void ITalk.Read() { Console.WriteLine("Implementing ITalk.Read"); } public void Talk() { Console.WriteLine("Implementing ITalk.Talk"); } }

All Rights Reserved To EaglesGroup

421

3. Now add the following code in the Static void main() as follows:

static void Main(string[] args) { // create a document object Document theDoc = new Document("Test Document"); IStorable isDoc = theDoc as IStorable; if (isDoc != null) { isDoc.Read(); } ITalk itDoc = theDoc as ITalk; if (itDoc != null) { itDoc.Read(); } theDoc.Read(); theDoc.Talk(); } 4. Now Run the Program and you will have the output something like this:

422

All Rights Reserved To EaglesGroup

10.4.2 Selectively Exposing Interface Methods


A class designer can take advantage of the fact that when an interface is implemented through explicit implementation, the interface is not visible to clients of the implementing class except through casting. Suppose the semantics of your Document object dictate that it implement the IStorable interface, but you do not want the Read ( ) and Write ( ) methods to be part of the public interface of your Document. You can use explicit implementation to ensure that they are not available except through casting. This allows you to preserve the semantics of your Document class while still having it implement IStorable. If your client wants an object that implements the IStorable interface, it can make an explicit cast, but when using your document as a Document, the semantics will not include Read( ) and Write( ). In fact, you can select which methods to make visible through explicit implementation, so that you can expose some implementing methods as part of Document but not others. In Example 10-5, the Document object exposes the Talk ( ) method as a method of Document, but the ITalk.Read ( ) method can be obtained only through a cast. Even if IStorable did not have a Read ( ) method, you might choose to make Read ( ) explicitly implemented so that you do not expose Read ( ) as a method of Document. Note that because explicit interface implementation prevents the use of the virtual keyword, a derived class would be forced to reimplement the method. Thus, if Note derived from Document, it would be forced to reimplement ITalk.Read ( ) because the Document implementation of ITalk.Read ( ) could not be virtual.

10.4.3 Member Hiding


It is possible for an interface member to become hidden. For example, suppose you have an interface IBase that has a property P: interface IBase { int P { get; set; } }

Suppose you derive from that interface a new interface, IDerived, which hides the property P with a new method P ( ):

All Rights Reserved To EaglesGroup

423

interface IDerived : IBase { new int P( ); }

Setting aside whether this is a good idea, you have now hidden the property P in the base interface. An implementation of this derived interface will require at least one explicit interface member. You can use explicit implementation for either the base property or the derived method, or you can use explicit implementation for both.

10.4.4 Accessing Sealed Classes and Value Types

Generally, it is preferable to access the methods of an interface through an interface cast. The exception is with value types (e.g., structs) or with sealed classes. In that case, it is preferable to invoke the interface method through the object. When you implement an interface in a struct, you are implementing it in a value type. When you cast to an interface reference, there is an implicit boxing of the object. Unfortunately, when you use that interface to modify the object, it is the boxed object, not the original value object, that is modified. Further, if you change the value type, the boxed type will remain unchanged. In the Below Example Program we will creates a struct that implements IStorable and illustrates the impact of implicit boxing when you cast the struct to an interface reference. Lets work it out Using References on value Types

Example 10-5 Using References on Value Types

Example Try it out Eagles valuetype Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles value type in the directory C:\EaglesVisualCSharp\Chapter 10\Example Using References on Value Types 2. Add the following code in the body of the Program.cs as follows:

424

All Rights Reserved To EaglesGroup

amespace Eagles_valuetype { # region EaglesGroup /// <EaglesGroup> /// EaglesSiddhu /// Siddhu /// Sri /// Somu /// (C) EaglesGroup 1978 - 2010 /// All Rights Reserved to EaglesGroup /// </EaglesGroup> # endregion class Program { // declare a simple interface interface IStorable { void Read(); int Status { get;set;} } // Implement through a struct public struct myStruct : IStorable { public void Read() { Console.WriteLine( "Implementing IStorable.Read"); } public int Status { get { return status; } set { status = value; } }

All Rights Reserved To EaglesGroup

425

private int status; } 3. Now add the following code in the Static Void Main() as follows in the Program.cs static void Main(string[] args) { // create a myStruct object myStruct theStruct = new myStruct( ); theStruct.Status = -1; // initialize Console.WriteLine( "theStruct.Status: {0}", theStruct.Status); // Change the value theStruct.Status = 2; Console.WriteLine("Changed object."); Console.WriteLine( "theStruct.Status: {0}", theStruct.Status); // cast to an IStorable // implicit box to a reference type IStorable isTemp = (IStorable) theStruct; // set the value through the interface reference isTemp.Status = 4; Console.WriteLine("Changed interface."); Console.WriteLine("theStruct.Status: {0}, isTemp: {1}", theStruct.Status, isTemp.Status); // Change the value again theStruct.Status = 6; Console.WriteLine("Changed object."); Console.WriteLine("theStruct.Status: {0}, isTemp: {1}", theStruct.Status, isTemp.Status); }

426

All Rights Reserved To EaglesGroup

4. Now Run the Program.cs and you will have the output like this:

Now lets see how the above program works: In the above program, the IStorable interface has a method (Read) and a property (Status). This interface is implemented by the struct named myStruct: public struct myStruct : IStorable

The interesting code is in Eagles_valuetype. Start by creating an instance of the structure and initializing its property to -1. The status value is then printed: myStruct theStruct = new myStruct( ); theStruct.status = -1; // initialize Console.WriteLine( "theStruct.Status: {0}", theStruct.status);

All Rights Reserved To EaglesGroup

427

The output from this shows that the status was set properly: theStruct.Status: -1

Next access the property to change the status, again through the value object itself: // Change the value theStruct.status = 2; Console.WriteLine("Changed object."); Console.WriteLine( "theStruct.Status: {0}", theStruct.status);

The output shows the change: Changed object. theStruct.Status: 2

No surprises so far. At this point, create a reference to the IStorable interface. This causes an implicit boxing of the value object theStruct. Then use that interface to change the status value to 4: // cast to an IStorable // implicit box to a reference type IStorable isTemp = (IStorable) theStruct; // set the value through the interface reference isTemp.status = 4; Console.WriteLine("Changed interface."); Console.WriteLine("theStruct.Status: {0}, isTemp: {1}", theStruct.status, isTemp.status);

428

All Rights Reserved To EaglesGroup

Here the output can be a bit surprising:

Changed interface. theStruct.Status: 2, isTemp: 4

Aha! The object to which the interface reference points has been changed to a status value of 4, but the struct value object is unchanged. Even more interesting, when you access the method through the object itself: // Change the value again theStruct.status = 6; Console.WriteLine("Changed object."); Console.WriteLine("theStruct.Status: {0}, isTemp: {1}", theStruct.status, isTemp.status);

The output reveals that the value object has been changed, but the boxed reference value for the interface reference has not: Changed object. theStruct.Status: 6, isTemp: 4

All Rights Reserved To EaglesGroup

429

Summary
In this chapter, we have looked at the important topic of interfaces. Although, initially difficult to get your head around, the code involved is quiet simple and youll certainly be using event handlers a lot in the rest of the book. The topics so far we covered are as follows: Introduction to Interfaces Implementing an Interface Implementing More Than One Interface Extending Interfaces Combining Interfaces Accessing Interface Methods Casting to an Interface The is Operator The as Operator The is Operator Versus the as Operator Interface Versus Abstract Class Overriding Interface Implementations Explicit Interface Implementation Selectively Exposing Interface Methods Member Hiding Accessing Sealed Classes and Value Types

430

All Rights Reserved To EaglesGroup

Chapter 11

All Rights Reserved To EaglesGroup

431

Delegates and Events


11.0 Introduction to Delegates
In programming, you are often faced with situations where you need to execute a particular action, but you don't know in advance which method, or even which object, you'll want to call upon to execute it. For example, a button might know that it must notify some object when it is pushed, but it might not know which object or objects need to be notified. Rather than wiring the button to a particular object, you will connect the button to a delegate and then resolve that delegate to a particular method when the program executes. In the early, dark, and primitive days of computing, a program would begin execution and then proceed through its steps until it completed. If the user was involved, the interaction was strictly controlled and limited to filling in fields. Today's Graphical User Interface (GUI) programming model requires a different approach, known as event-driven programming. A modern program presents the user interface and waits for the user to take an action. The user might take many different actions, such as choosing among menu selections, pushing buttons, updating text fields, clicking icons, and so forth. Each action causes an event to be raised. Other events can be raised without direct user action, such as events that correspond to timer ticks of the internal clock, email being received, file-copy operations completing, etc. An event is the encapsulation of the idea that "something happened" to which the program must respond. Events and delegates are tightly coupled concepts because flexible event handling requires that the response to the event be dispatched to the appropriate event handler. An event handler is typically implemented in C# as a delegate. In C#, delegates are first-class objects, fully supported by the language. Technically, a delegate is a reference type used to encapsulate a method with a specific signature and return type. You can encapsulate any matching method in that delegate. DENOTE: In C++ and many other languages, you can accomplish this requirement with function pointers and pointers to member functions. Unlike function pointers, delegates are object-oriented and type safe

432

All Rights Reserved To EaglesGroup

A delegate is created with the delegate keyword, followed by a return type and the signature of the methods that can be delegated to it, as in the following: public delegate int WhichIsFirst(object obj1, object obj2);

This declaration defines a delegate named WhichIsFirst, which will encapsulate any method that takes two objects as parameters and that returns an int. Once the delegate is defined, you can encapsulate a member method with that delegate by instantiating the delegate, passing in a method that matches the return type and signature. The delegate can then be used to invoke that encapsulated method.

11.1 Using Delegates to Specify Methods at Runtime


Delegates uncouple the class that declares the delegate from the class that uses the delegate. For example, suppose that you want to create a simple container class called a Pair that can hold and sort any two objects passed to it. You can't know in advance what kind of objects a Pair will hold, but by creating methods within those objects to which the sorting task can be delegated, you can delegate responsibility for determining their order to the objects themselves. Different objects will sort differently for example, a Pair of Counter objects might sort in numeric order, while a Pair of Buttons might sort alphabetically by their name. As the author of the Pair class, you want the objects in the pair to have the responsibility of knowing which should be first and which should be second. To accomplish this, you will insist that the objects to be stored in the Pair must provide a method that tells you how to sort the objects. You can define this requirement with interfaces, as well. Delegates are smaller and of finer granularity than interfaces. The Pair class does not need to implement an entire interface, it just needs to define the signature and return type of the method it wants to invoke. That is what delegates are for: they define the return type and signature of methods that can be invoked through the interface. In this case, the Pair class will declare a delegate named WhichIsFirst. When the Pair needs to know how to order its objects, it will invoke the delegate passing in its two member objects as parameters. The responsibility for deciding which of the two objects comes first is delegated to the method encapsulated by the delegate.

All Rights Reserved To EaglesGroup

433

public delegate Comparison WhichIsFirst (object obj1, object obj2);

In this definition, WhichIsFirst is defined to encapsulate a method that takes two objects as parameters, and that returns an object of type Comparison. Comparison turns out to be an enumeration you will define: public enum Comparison { theFirstComesFirst = 1, theSecondComesFirst = 2 }

To test the delegate, you will create two classes, a Dog class and a Student class. Dogs and Students have little in common, except that they both implement methods that can be encapsulated by WhichComesFirst, and thus both Dog objects and Student objects are eligible to be held within Pair objects. In the test program, you will create a couple of Students and a couple of Dogs, and store them each in a Pair. You will then create instances of WhichIsFirst to encapsulate their respective methods that will determine which Student or which Dog object should be first, and which second. Let's take this step by step. You begin by creating a Pair constructor that takes two objects and stashes them away in a private array: public class Pair { // hold both objects private object[]thePair = new object[2]; // two objects, added in order received public Pair(object firstObject, object secondObject) { thePair[0] = firstObject; thePair[1] = secondObject; }

434

All Rights Reserved To EaglesGroup

Next, you override ToString ( ) to obtain the string value of the two objects: public override string ToString( ) { return thePair [0].ToString( ) + ", " + thePair[1].ToString( ); }

You now have two objects in your Pair and you can print out their values. You're ready to sort them and print the results of the sort. You can't know in advance what kind of objects you will have, so you delegate the responsibility of deciding which object comes first in the sorted Pair to the objects themselves. Both the Dog class and the Student class implement methods that can be encapsulated by WhichIsFirst. Any method that takes two objects and returns a comparison can be encapsulated by this delegate at runtime. You can now define the Sort ( ) method for the Pair class: public void Sort(WhichIsFirst theDelegatedFunc) { if (theDelegatedFunc(thePair[0],thePair[1]) == comparison.theSecondComesFirst) { object temp = thePair[0]; thePair[0] = thePair[1]; thePair[1] = temp; } }

This method takes a parameter: a delegate of type WhichIsFirst named theDelegatedFunc. The Sort ( ) method delegates responsibility for deciding which of the two objects in the Pair comes first to the method encapsulated by that delegate. In the body of the Sort ( ) method, it invokes the delegated method and examines the return value, which will be one of the two enumerated values of comparison. If the value returned is theSecondComesFirst, the objects within the pair are swapped; otherwise no action is taken.

All Rights Reserved To EaglesGroup

435

This is analogous to how the other parameters work. If you had a method that took an int as a parameter: int SomeMethod (int myParam){//...}

The parameter name is myParam, but you can pass in any int value or variable. Similarly, the parameter name in the delegate example is theDelegatedFunc, but you can pass in any method that meets the return value and signature defined by the delegate WhichIsFirst. Imagine you are sorting Students by name. You write a method that returns theFirstComesFirst if the first student's name comes first and theSecondComesFirst if the second student's name does. If you pass in "siddhu, sambu" the method will return theFirstComesFirst, and if you pass in "sambu, siddhu" it will return theSecondComesFirst. If you get back theSecondComesFirst, the Sort ( ) method reverses the items in its array, setting Amy to the first position and Beth to the second. Now add one more method, ReverseSort ( ), which will force the items in the array into the reverse of their normal order: public void ReverseSort(WhichIsFirst theDelegatedFunc) { if (theDelegatedFunc(thePair[0], thePair[1]) == comparison.theFirstComesFirst) { object temp = thePair[0]; thePair[0] = thePair[1]; thePair[1] = temp; } } The logic here is identical to Sort ( ), except that this method performs the swap if the delegated method says that the first item comes first. Because the delegated function thinks the first item comes first, and this is a reverse sort, the result you want is for the second item to come first. This time if you pass in "siddhu, sambu," the delegated function returns theFirstComesFirst (i.e., Amy should come first), but because this is a reverse sort, it swaps the values, setting Beth first. This allows you to use the same delegated function as you used with Sort ( ), without forcing the object to support a function that returns the reverse sorted value.

436

All Rights Reserved To EaglesGroup

Now all you need are some objects to sort. You'll create two absurdly simple classes: Student and Dog. Assign Student objects a name at creation: public class Student { public Student(string name) { this.name = name; }

The Student class requires two methods: one to override ToString ( ) and the other to be encapsulated as the delegated method. Student must override ToString ( ) so that the ToString ( ) method in Pair, which invokes ToString ( ) on the contained objects, will work properly; the implementation does nothing more than return the student's name (which is already a string object): public override string ToString( ) { return name ; }

It must also implement a method to which Pair.Sort ( ) can delegate the responsibility of determining which of two objects comes first: return (String.Compare (s1.name, s2.name) < 0? comparison.theFirstComesFirst: comparison.theSecondComesFirst); String.Compare( ) is a .NET Framework method on the String class that compares two strings and returns less than zero if the first is smaller, greater than zero if the second is smaller, and zero if they are the same. DENOTE: That the logic here returns theFirstComesFirst only if the first string is smaller; if they are the same or the second is larger, this method returns theSecondComesFirst. The WhichStudentComesFirst ( ) method takes two objects as parameters and returns a comparison. This qualifies it to be a Pair.WhichIsFirst delegated method, whose signature and return value it matches.

All Rights Reserved To EaglesGroup

437

The second class is Dog. For our purposes, Dog objects will be sorted by weight, lighter dogs before heavier. Here's the complete declaration of Dog: public class Dog { public Dog(int weight) { this.weight=weight; } // dogs are ordered by weight public static comparison WhichDogComesFirst( Object o1, Object o2) { Dog d1 = (Dog) o1; Dog d2 = (Dog) o2; return d1.weight > d2.weight ? comparison.theSecondComesFirst : comparison.theFirstComesFirst; } public override string ToString( ) { return weight.ToString( ); } private int weight; }

The Dog class also overrides ToString and implements a static method with the correct signature for the delegate. Notice also that the Dog and Student delegate methods do not have the same name. They do not need to have the same name, as they will be assigned to the delegate dynamically at runtime.

438

All Rights Reserved To EaglesGroup

Lets work it out - Working with delegates

Example 11-1 Working with delegates

Example Try it out Eagles Delegates Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles Delegates in the directory C:\EaglesVisualCSharp\Chapter 11 - Events\Example Using Delegates 2. Add the following code into the body of the Program.cs as follows: amespace Eagles_Delegates { class Program { public enum Comparison { theFirstComesFirst = 1, theSecondComesFirst = 2 } // a simple collection to hold 2 items public class Pair { // private array to hold the two objects private object[] thePair = new object[2]; // the delegate declaration public delegate Comparison WhichIsFirst(object obj1, object obj2); // passed in constructor take two objects, // added in order received public Pair( object firstObject, object secondObject) { thePair[0] = firstObject; thePair[1] = secondObject; } // public method which orders the two objects // by whatever criteria the object likes!

All Rights Reserved To EaglesGroup

439

public void Sort( WhichIsFirst theDelegatedFunc) { if (theDelegatedFunc(thePair[0],thePair[1]) == Comparison.theSecondComesFirst) { object temp = thePair[0]; thePair[0] = thePair[1]; thePair[1] = temp; } } // public method which orders the two objects // by the reverse of whatever criteria the object likes! public void ReverseSort( WhichIsFirst theDelegatedFunc) { if (theDelegatedFunc(thePair[0],thePair[1]) == Comparison.theFirstComesFirst) { object temp = thePair[0]; thePair[0] = thePair[1]; thePair[1] = temp; } } // ask the two objects to give their string value

public override string ToString() { return thePair[0].ToString() + ", " + thePair[1].ToString(); } } // end class Pair public class Dog { private int weight; public Dog(int weight) { this.weight = weight; }

440

All Rights Reserved To EaglesGroup

// dogs are ordered by weight public static Comparison WhichDogComesFirst( Object object1, Object object2) { Dog dog1 = (Dog)object1; Dog dog2 = (Dog)object2; return dog1.weight > dog2.weight ? Comparison.theSecondComesFirst : Comparison.theFirstComesFirst; } public override string ToString() { return weight.ToString(); } } // end class Dog public class Student { private string name; public Student(string name) { this.name = name; } // students are ordered alphabetically public static Comparison WhichStudentComesFirst(Object o1, Object o2) { Student student1 = (Student)o1; Student student2 = (Student)o2; return (String.Compare(student1.name, student2.name) < 0 ? Comparison.theFirstComesFirst : Comparison.theSecondComesFirst); } public override string ToString() { return name; } } // end class Student

All Rights Reserved To EaglesGroup

441

3. Now add the following code into the Main () of the Program.cs as follows:

static void Main(string[] args) { // create two students and two dogs // and add them to Pair objects Student Siddhu = new Student("Siddhu"); Student Sambu = new Student("Sambu"); Dog Blacky = new Dog(65); Dog Jimmy = new Dog(12); Dog Puppy = new Dog(20); Pair studentPair = new Pair(Siddhu, Sambu); Pair dogPair = new Pair(Blacky, Jimmy); Console.WriteLine("studentPair\t\t\t: {0}", studentPair.ToString()); Console.WriteLine("dogPair\t\t\t\t: {0}", dogPair.ToString());

// Instantiate the delegates Pair.WhichIsFirst theStudentDelegate = new Pair.WhichIsFirst( Student.WhichStudentComesFirst); Pair.WhichIsFirst theDogDelegate = new Pair.WhichIsFirst( Dog.WhichDogComesFirst); // sort using the delegates studentPair.Sort(theStudentDelegate); Console.WriteLine("After Sort studentPair\t\t: {0}", studentPair.ToString()); studentPair.ReverseSort(theStudentDelegate); Console.WriteLine("After ReverseSort studentPair\t: {0}", studentPair.ToString());

442

All Rights Reserved To EaglesGroup

dogPair.Sort(theDogDelegate); Console.WriteLine("After Sort dogPair\t\t: {0}", dogPair.ToString()); dogPair.ReverseSort(theDogDelegate); Console.WriteLine("After ReverseSort dogPair\t: {0}", dogPair.ToString()); } 4. Now Run the program and the you will get the output something like this:

Lets see how the above code works: The Eagles Delegates program creates two Student objects and two Dog objects and then adds them to Pair containers. The student constructor takes a string for the student's name and the dog constructor takes an int for the dog's weight.

All Rights Reserved To EaglesGroup

443

Student Siddhu = new Student("Siddhu"); Student Sambu = new Student ("Sambu"); Dog Blacky = new Dog(65); Dog Jimmy = new Dog(12); Dog Puppy = new Dog (20); Pair studentPair = new Pair(Siddhu,Sambu); Pair dogPair = new Pair(Blacky, Jimmy); Console.WriteLine("studentPair\t\t\t: {0}", studentPair.ToString( )); Console.WriteLine("dogPair\t\t\t\t: {0}", dogPair.ToString( ));

It then prints the contents of the two Pair containers to see the order of the objects. The output looks like this: studentPair dogPair : Siddhu, Sambu : 65, 12

As expected, the objects are in the order in which they were added to the Pair containers. We next instantiate two delegate objects: Pair.WhichIsFirst theStudentDelegate = new Pair.WhichIsFirst( Student.WhichStudentComesFirst); Pair.WhichIsFirst theDogDelegate = new Pair.WhichIsFirst( Dog.WhichDogComesFirst);

The first delegate, theStudentDelegate, is created by passing in the appropriate static method from the Student class. The second delegate, theDogDelegate, is passed a static method from the Dog class.

444

All Rights Reserved To EaglesGroup

The delegates are now objects that can be passed to methods. You pass the delegates first to the Sort ( ) method of the Pair object, and then to the ReverseSort ( ) method. The results are printed to the console

11.2 Delegates and Instance Methods


In Example 11-1, the delegates encapsulate static methods, as in the following: public static Comparison WhichDogComesFirst( Object object1, Object object2)

The delegate is then instantiated using the class rather than an instance: Pair.WhichIsFirst theStudentDelegate = new Pair.WhichIsFirst( Student.WhichStudentComesFirst);

You can just as easily encapsulate instance methods public Comparison WhichStudentComesFirst(Object o1, Object o2)

All Rights Reserved To EaglesGroup

445

In which case you will instantiate the delegate by passing in the instance method as invoked through an instance of the class, rather than through the class itself: Pair.WhichIsFirst theStudentDelegate = new Pair.WhichIsFirst( Jesse.WhichStudentComesFirst);

11.3 Static Delegates


One disadvantage of Example 11-1 is that it forces the calling class (in this case Test) to instantiate the delegates it needs in order to sort the objects in a Pair. It would be nice to get the delegate from the Student or Dog class itself. You can do this by giving each class its own static delegate. Thus, you can modify Student to add this: public static readonly Pair.WhichIsFirst OrderStudents = new Pair.WhichIsFirst(Student.WhichStudentComesFirst);

This creates a static, read-only delegate named OrderStudents DENOTE: Marking OrderStudents read-only denotes that once this static field is created, it will not be modified. You can create a similar delegate within the Dog class

public static readonly Pair.WhichIsFirst OrderDogs = new Pair.WhichIsFirst(Dog.WhichDogComesFirst);

446

All Rights Reserved To EaglesGroup

These are now static fields of their respective classes. Each is prewired to the appropriate method within the class. You can invoke delegates without declaring a local delegate instance. You just pass in the static delegate of the class: studentPair.Sort(Student.OrderStudents); Console.WriteLine("After Sort studentPair\t\t: {0}", studentPair.ToString( )); studentPair.ReverseSort(Student.OrderStudents); Console.WriteLine("After ReverseSort studentPair\t: {0}", studentPair.ToString( )); dogPair.Sort(Dog.OrderDogs); Console.WriteLine("After Sort dogPair\t\t: {0}", dogPair.ToString( )); dogPair.ReverseSort(Dog.OrderDogs); Console.WriteLine("After ReverseSort dogPair\t: {0}", dogPair.ToString( ));

The output after these changes is identical to Example 11-1

11.4 Delegates as Properties


The problem with static delegates is that they must be instantiated, whether or not they are ever used, as with Student and Dog in Example 11-1. You can improve these classes by changing the static delegate fields to properties. For Student, you take out the declaration: public static readonly Pair.WhichIsFirst OrderStudents = new Pair.WhichIsFirst(Student.WhichStudentComesFirst); And replace it with

public static Pair.WhichIsFirst OrderStudents { get { return new Pair.WhichIsFirst(WhichStudentComesFirst); } }

All Rights Reserved To EaglesGroup

447

Similarly, you replace the static Dog field with

public static Pair.WhichIsFirst OrderDogs { get { return new Pair.WhichIsFirst(WhichDogComesFirst); } }

The assignment of the delegates is unchanged studentPair.Sort(Student.OrderStudents); dogPair.Sort(Dog.OrderDogs);

When the OrderStudent property is accessed, the delegate is created: return new Pair.WhichIsFirst(WhichStudentComesFirst);

The key advantage is that the delegate is not created until it is requested. This allows the test class to determine when it needs a delegate, but still allows the details of the creation of the delegate to be the responsibility of the Student or Dog class.

11.5 Setting Order of Execution with Delegate Arrays


Delegates can help you create a system in which the user can dynamically decide the order in which operations are performed. For instance, suppose you have an image processing system in which an image can be manipulated in a number of well-defined ways, such as blurring, sharpening, rotating, filtering, and so forth. Assume, as well, that the order in which these effects are applied to the image is important. The user wishes to choose from a menu of effects, applying all that he likes, and then telling the image processor to run the effects, one after the other in the order that he has specified.

448

All Rights Reserved To EaglesGroup

You can create delegates for each operation and add them to an ordered collection, such as an array, in the order you'd like them to execute. Once all the delegates are created and added to the collection, you simply iterate over the array, invoking each delegated method in turn. You begin by creating a class, Image, to represent the image that will be processed by the Eagles_ImageProcessor: public class EaglsImage { public Image( ) { Console.WriteLine("An image created"); } }

DENOTE: You can imagine that this stands in for a .gif or .jpeg file or other image The Eagles_ImageProcessor then declares a delegate. You can of course define your delegate to return any type and take any parameters you like. For this example, you'll define the delegate to encapsulate any method that returns void and takes no arguments: public delegate void DoEffect( ); The Eagles_ImageProcessor then declares a number of methods, each of which processes an image and each of which matches the return type and signature of the delegate:

All Rights Reserved To EaglesGroup

449

public static void Blur( ) { Console.WriteLine("Blurring image"); } public static void Filter( ) { Console.WriteLine("Filtering image"); } public static void Sharpen( ) { Console.WriteLine("Sharpening image"); } public static void Rotate( ) { Console.WriteLine("Rotating image"); }

DENOTE: In a production environment, these methods would be very complicated, and they'd actually do the work of blurring, filtering, sharpening, and rotating the image

The Eagles_ImageProcessor class needs an array to hold the delegates that the user picks, a variable to hold the running total of how many effects are in the array, and of course a variable for the image itself

DoEffect[] arrayOfEffects; Image image; int numEffectsRegistered = 0;

450

All Rights Reserved To EaglesGroup

The Eagles_ImageProcessor also needs a method to add delegates to the array public void AddToEffects(DoEffect theEffect) { if (numEffectsRegistered >= 10) { throw new Exception("Too many members in array"); } arrayOfEffects[numEffectsRegistered++] = theEffect; }

It needs another method to actually call each method in turn public void Eagles_ProcessImages( ) { for (int i = 0;i < numEffectsRegistered;i++) { arrayOfEffects[i]( ); } }

Finally, you need to declare the static delegates that the client can call, hooking them to the processing methods public DoEffect BlurEffect = new DoEffect(Blur); public DoEffect SharpenEffect = new DoEffect(Sharpen); public DoEffect FilterEffect = new DoEffect(Filter); public DoEffect RotateEffect = new DoEffect(Rotate);

DENOTE: In a production environment, in which you might have dozens of effects, you might choose to make these properties rather than static methods. That would save creating the effects unless they are needed, at the cost of making the program slightly more complicated.

All Rights Reserved To EaglesGroup

451

The client code would normally have an interactive user-interface component, but we'll
simulate that by choosing the effects, adding them to the array, and then calling Eagles_ProcessImage, as shown in Example 11-2.

Lets work it out - Working array of delegates

Example 11-2 Working with array of delegates

Example Try it out Eagles ProcessImage Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles ProcessImage in the directory C:\EaglesVisualCSharp\Chapter 11 - Events\Example Using array of delegates

452

All Rights Reserved To EaglesGroup

2. Add the following code in the body of the Program.cs as follows: namespace Eagles_ProcessImage { // the image which we'll manipulate class Program { public class Image { public Image() { Console.WriteLine("An image created"); } } public class ImageProcessor { // declare the delegate public delegate void DoEffect( ); // create various static delegates tied to member methods public DoEffect BlurEffect = new DoEffect(Blur); public DoEffect SharpenEffect = new DoEffect(Sharpen); public DoEffect FilterEffect = new DoEffect(Filter); public DoEffect RotateEffect = new DoEffect(Rotate); // the constructor initializes the image and the array public ImageProcessor(Image image) { this.image = image; arrayOfEffects = new DoEffect[10]; } // in a production environment we'd use a more // flexible collection.

All Rights Reserved To EaglesGroup

453

public void AddToEffects(DoEffect theEffect) { if (numEffectsRegistered >= 10) { throw new Exception( "Too many members in array"); } arrayOfEffects[numEffectsRegistered++] = theEffect; } // the image processing methods... public static void Blur() { Console.WriteLine("Blurring image"); } public static void Filter() { Console.WriteLine("Filtering image"); } public static void Sharpen() { Console.WriteLine("Sharpening image"); } public static void Rotate() { Console.WriteLine("Rotating image"); } public void ProcessImages() { for (int i = 0; i < numEffectsRegistered; i++) { arrayOfEffects[i](); } }

454

All Rights Reserved To EaglesGroup

// private member variables... private DoEffect[] arrayOfEffects; private Image image; private int numEffectsRegistered = 0; } // test the Process

3. Now add the following code into the Static Main () as follows:

static void Main(string[] args) { Image theImage = new Image(); // no ui to keep things simple, just pick the // methods to invoke, add them in the required // order, and then call on the image processor to // run them in the order added. ImageProcessor theProc = new ImageProcessor(theImage); theProc.AddToEffects(theProc.BlurEffect); theProc.AddToEffects(theProc.FilterEffect); theProc.AddToEffects(theProc.RotateEffect); theProc.AddToEffects(theProc.SharpenEffect); theProc.ProcessImages(); }

All Rights Reserved To EaglesGroup

455

4. Now run the program and you will have the output like this:

Now lets see how the above the code works: In the Test class of Example 11-2, the ImageProcessor is instantiated, and effects are added. If the user chooses to blur the image before filtering the image, it is a simple matter to add the delegates to the array in the appropriate order. Similarly, any given operation can be repeated as often as the user desires, just by adding more delegates to the collection. You can imagine displaying the order of operations in a listbox that might allow the user to reorder the methods, moving them up and down the list at will. As the operations are reordered, you need only change their sort order in the collection. You might even decide to capture the order of operations to a database and then load them dynamically, instantiating delegates as dictated by the records you've stored in the database. Delegates provide the flexibility to determine dynamically which methods will be called, in what order, and how often.

456

All Rights Reserved To EaglesGroup

11.1.0 Introduction to Events


Well start, as usual with the basics looking at what events actually are. After this well move on to see some simple events in action and look at what we can do with them. Once this is described, well move on to look at how we can create and use events of our own. An event is the outcome of something happening. Events are ways of letting the world know that something going on is worth mentioning to other people. The development world doesnt really involve many other people; of course you generally have only a single user. Events consist of two parts an object that performs an action and wants to let any object interested know that the action is being performed; and or more object that want to know when that particular action is performed. In a given application, any objects perform many tasks. How can any individual object know which of these many objects might be interested in knowing of a change in that particular objects state? For C#, the answer lies in the twin constructs events sources and event handlers. GUIs, such as Microsoft Windows and web browsers, require that programs respond to events. An event might be a button push, a menu selection, the completion of a file transfer, and so forth. In short, something happens and you must respond to it. You cannot predict the order in which events will arise. The system is quiescent until the event, and then springs into action to handle it. In a GUI environment, any number of widgets can raise an event. For example, when you click a button, it might raise the Click event. When you add to a drop-down list, it might raise a List Changed event. Other classes will be interested in responding to these events. How they respond is not of interest to the class raising the event. The button says, "I was clicked," and the responding classes react appropriately. To start with, then, lets look at what events are:

11.1.1 What is an event?


Events are similar to exceptions in that they are raised (thrown) by objects and we can supply code that acts on them. However, there are several important differences. The most important of these is that there is no equivalent to the try Catch structure for handling events. Instead we must subscribe to them.

All Rights Reserved To EaglesGroup

457

Subscribing to an event means supplying code that will be executed when an event is raised in the form of an event handler. An event can have many handles subscribed to it, which will all be called when the event is raised. This may include event handlers that are part of the class of the object that raises the event but event handles are just as like to be found in other classes. Event handlers themselves are simply functions. The only restriction on an event handler function is that must match the signature (return type and parameters) required by the event. This signature is part of the definition of an event, and is specified by a delegate. DENOTE: The fact that delegates are used in events in events is what makes delegates such useful thing. This is the reason we devoted sometime to the back in chapter 5, and you may wish to re-read that section to refresh your memory as to what delegates are and how we use them. The sequence of processing goes something like this: First, an application creates an object that can raise an event. As an example, lets say that the application is an instant messaging application, and that the object it creates represents a connection to a remote user. This connection object might raise an event, say, when a message arrives through the connection from the remote user.

Picture 11.1

Application

Creates

Connection

Next, the application subscribes to the event. Our instant messaging application would do this by defining a function that could be used with the delegate type specified by the event, and passing a reference to this function to the event. This event handler function might be a method on another object. Lets say an object representing a display device to display instant message on when they arrive.

458

All Rights Reserved To EaglesGroup

Picture 11.2

Application

Connection

Creates Subscribes to Display

When the event is raised, the subscriber is notified. When an instant message arrives through the connection object, the event handler method on the display device object is called. As we are using a standard method, the object that raises the event may pass any relevant information via parameters, making events very versatile. In our example case, one parameter might be the text of the instant message, which the event handler could display on the display device object.

Picture 11.3

Application

Connection Raises Events

Display Calls Mi Siddhu

All Rights Reserved To EaglesGroup

459

11.1.2 Event Handlers


As a simple example, consider an evetn handler that deals with account underflows. This event occurs when the owner of an account posts a debit withdrawal from the account that would make the account negative. When this situation happens, you might want to send the user an email message to notify her that unless the account is brought to balance that day, she will be charged a fee. To do this, of course, the event handler would need to notify of the fact that a debit had driven the balance negative. Imagine, however, that the writer of the accounting component had not considered the need to track an event such as the account going negative. Instead, the writer simply dealt with the more general case of firing an event for the Object whenever the balance of the account changed, either a credit or a debit. If you had created an additional object to monitor accounts and keep a track of the balance yourself, you could maintain an internal state of the balance is an each credit ort debit is posted to the account. This way, you could quickly and easily watch for changes that will drive the account to have a negative balance. In the way, event handling is a powerful way to extended classes without using any form of inheritance.

11.1.3 Event Sources


An evetn source is an object that notifies other objects or tasks that something has changed. The event source determines when the notification takes place, or in fact, whether the notification even takes place. Event notification in C# takes the form of callbacks. In other system, event handling is more in the form of published and subscribe. The event source sends out a general message when it wants to notify other objects of change, and then anyone interested in the message reads it and interrupts it. Although this mechanism is powerful and quite useful, it is not the most efficient way of doing tings. Publish and subscribe require that you have a generalized broadcast mechanism and that all objects receive all messages. In C#, each event source maintains one or more events that it publishes. These events are noted in the source code and documentation for the object, although the specifies of when the event s are fired are not necessarily know. Events in C# are considered to be asynchronous form the perspective of the caller. A callback does not occur when the caller wants it to, but rather when the event firing objects decides that something of note has happened.

460

All Rights Reserved To EaglesGroup

11.1.4 Using Events


In this section, well look at the code required for handling events, and then move on to look at how we can define and use our own.

11.1.5 Handling Events


Event handlers receive event notifications. When an event source decides that something has happened that merits notification, all the event handlers that have registered for notification of that event are told about the occurrence. An event handler may be either a static or non static method of class. In the case of static method, event handlers simply responded to a given evetn source and take a course of action based on the information passed to the handler. For non static event handler, the entire state of the object can be considered when working with the event, allowing an object to make intelligent decisions for a given event. As we have discussed, to handle an event we need to subscribe to the event by providing an event handler functions those signature matches that of the delegate specified for use with the event. Lets look at an example that uses a simple timer object to raise events, which will result in a handler function being called.

11.1.6 Publishing and Subscribing


In C#, any object can publish a set of events to which other classes can subscribe. When the publishing class raises an event, all the subscribed classes are notified. With this mechanism, your object can say "Here are things I can notify you about," and other classes might sign up, saying "Yes, let me know when that happens." For example, a button might notify any number of interested observers when it is clicked. The button is called the publisher because the button publishes the Click event and the other classes are the subscribers because they subscribe to the Click event. As a second example, a Clock might notify interested classes whenever the time changes by one second. The Clock class could simply print the time rather than raising an event, so why bother with the indirection of using delegates? The advantage of the publish/subscribe idiom is that any number of classes can be notified when an event is raised. The subscribing classes do not need to know how the Clock works, and the Clock does not need to know what they are going to do in response to the event. The publisher and the subscribers are uncoupled by the delegate. This is highly desirable; it makes for more flexible and robust code. The Clock can change how it detects time

All Rights Reserved To EaglesGroup

461

without breaking any of the subscribing classes. The subscribing classes can change how they respond to time changes without breaking the Clock. The two classes spin independently of one another, and that makes for code that is easier to maintain.

11.1.7 Events and Delegates


Events in C# are implemented with delegates. The publishing class defines a delegate that the subscribing classes must implement. When the event is raised, the subscribing class's methods are invoked through the delegate.

A method that handles an event is called an event handler. You can declare your event handlers as you would any other delegate.

By convention, event handlers in the .NET Framework return void and take two parameters. The first parameter is the "source" of the event that is, the publishing object. The second parameter is an object derived from EventArgs. It is recommended that your event handlers follow this design pattern. DENOTE: VB6 programmers take note: C# doesn't put restrictions on the names of the methods that handle events. Also, the .NET implementation of the publish/subscribe model lets you have a single method that subscribes to multiple events.

EventArgs is the base class for all event data. Other than its constructor, the EventArgs class inherits all its methods from Object, though it does add a public static field named empty, which represents an event with no state (to allow for the efficient use of events with no state). The EventArgs derived class contains information about the event. Suppose you want to create a Clock class that uses delegates to notify potential subscribers whenever the local time changes value by one second. Call this delegate SecondChangeHandler The declaration for the SecondChangeHandler delegate is: public delegate void SecondChangeHandler( object clock, TimeInfoEventArgs timeInformation );

462

All Rights Reserved To EaglesGroup

This delegate will encapsulate any method that returns void and that takes two parameters. The first parameter is an object that represents the clock the object raising the event, and the second parameter is an object of type TimeInfoEventArgs that will contain useful information for anyone interested in this event. TimeInfoEventArgs is defined as follows: public class TimeInfoEventArgs : EventArgs { public TimeInfoEventArgs(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } public readonly int hour; public readonly int minute; public readonly int second; }

The TimeInfoEventArgs object will have information about the current hour, minute, and second. It defines a constructor and three public, read-only integer variables.

In addition to its delegate, a Clock has three member variableshour, minute, and secondas well as a single method, Run( ): public void Run( ) { for(;;) { // sleep 10 milliseconds Thread.Sleep(10); // get the current time System.DateTime dt = System.DateTime.Now; // if the second has changed // notify the subscribers if (dt.Second != second) { // create the TimeInfoEventArgs object // to pass to the subscriber
All Rights Reserved To EaglesGroup

463

TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour,dt.Minute,dt.Second); // if anyone has subscribed, notify them if (OnSecondChange != null) { OnSecondChange(this,timeInformation); } } // update the state this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; } }

Run ( ) creates an infinite for loop that periodically checks the system time. If the time has changed from the Clock object's current time, it notifies all its subscribers and then updates its own state.

The first step is to sleep for 10 milliseconds: Thread.Sleep(10);

This makes use of a static method of the Thread class from the System.Threading namespace, the call to Sleep ( ) prevents the loop from running so tightly that little else on the computer gets done.

After sleeping for 10 milliseconds, the method checks the current time: System.DateTime dt = System.DateTime.Now;

464

All Rights Reserved To EaglesGroup

About every 100 times it checks, the second will have incremented. The method notices that change and notifies its subscribers. To do so, it first creates a new TimeInfoEventArgs object: if (dt.Second != second) { // create the TimeInfoEventArgs object // to pass to the subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(dt.Hour,dt.Minute,dt.Second);

It then notifies the subscribers by firing the OnSecondChange event: // if anyone has subscribed, notify them if (OnSecondChange != null) { OnSecondChange(this,timeInformation); } If an event has no subscribers registered, it will evaluate to null. The test above checks } that the value is not null, ensuring that there are subscribers before calling OnSecondChange. You will remember that OnSecondChange takes two arguments: the source of the event and the object derived from EventArgs. In the snippet, you see that the clocks this reference is passed because the clock is the source of the event. The second parameter is the TimeInfoEventArgs object, timeInformation, created on the line above. Raising the event will invoke whatever methods have been registered with the Clock class through the delegate. We'll examine this in a moment. Once the event is raised, you update the state of the Clock class:

this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour;

All Rights Reserved To EaglesGroup

465

All that is left is to create classes that can subscribe to this event. You'll create two. First will be the DisplayClock class. The job of DisplayClock is not to keep track of time, but rather to display the current time to the console. The example simplifies this class down to two methods. The first is a helper method named Subscribe ( ) that is used to subscribe to the clock's OnSecondChange delegate. The second method is the event handler TimeHasChanged ( ):

public class DisplayClock { public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(TimeHasChanged); } public void TimeHasChanged( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Current Time: {0}:{1}:{2}", ti.hour.ToString( ), ti.minute.ToString( ), ti.second.ToString( )); } }

When the first method, Subscribe ( ), is invoked, it creates a new SecondChangeHandler delegate, passing in its event handler method, TimeHasChanged ( ). It then registers that delegate with the OnSecondChange event of Clock.

You will create a second class that will also respond to this event, LogCurrentTime. This class would normally log the event to a file, but for our demonstration purposes, it will log to the standard console:

466

All Rights Reserved To EaglesGroup

public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(WriteLogEntry); } // this method should write to a file // we write to the console to see the effect // this object keeps no state public void WriteLogEntry( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Logging to file: {0}:{1}:{2}", ti.hour.ToString( ), ti.minute.ToString( ), ti.second.ToString( )); } } Although in this example these two classes are very similar, in a production program any number of disparate classes might subscribe to an event. All that remains is to create a Clock class, create the DisplayClock class, and tell it to subscribe to the event. You then will create a LogCurrentTime class and tell it to subscribe as well.

All Rights Reserved To EaglesGroup

467

Lets work it out - Implementing events with delegates

Example 11-3 Working events with delegates

Example Try it out Eagles Events&delegates Step by Step Example: Using Version 2005
1. Create a new Console Application called it EaglesEventsDelegents in the directory C:\EaglesVisualCSharp\Chapter 11 - Events\ Example Using Eventsdelegates 2. Now add the following code in the System. Namespace as follows: using System; using System.Collections.Generic; using System.Text; using System.Threading;

468

All Rights Reserved To EaglesGroup

3. Now add the following code into the body of the Program.cs as follows: namespace EaglesEventsDelegents { class Program { // a class to hold the information about the event // in this case it will hold only information // available in the clock class, but could hold // additional state information public class TimeInfoEventArgs : EventArgs { public TimeInfoEventArgs(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } public readonly int hour; public readonly int minute; public readonly int second; } // our subject -- it is this class that other classes // will observe. This class publishes one delegate: // OnSecondChange. public class Clock { // the delegate the subscribers must implement public delegate void SecondChangeHandler ( object clock, TimeInfoEventArgs timeInformation );

All Rights Reserved To EaglesGroup

469

// an instance of the delegate public SecondChangeHandler OnSecondChange; // set the clock running // it will raise an event for each new second public void Run() { for (; ; ) { // sleep 10 milliseconds Thread.Sleep(10); // get the current time System.DateTime dt = System.DateTime.Now; // if the second has changed // notify the subscribers if (dt.Second != second) { // create the TimeInfoEventArgs object // to pass to the subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour, dt.Minute, dt.Second); // if anyone has subscribed, notify them if (OnSecondChange != null) { OnSecondChange( this, timeInformation); } }

470

All Rights Reserved To EaglesGroup

// update the state this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; } } private int hour; private int minute; private int second; } // an observer. DisplayClock subscribes to the // clock's events. The job of DisplayClock is // to display the current time

public class DisplayClock { // given a clock, subscribe to // its SecondChangeHandler event public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(TimeHasChanged); } // the method that implements the // delegated functionality public void TimeHasChanged( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Current Time: {0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); } } // a second subscriber whose job is to write to a file

All Rights Reserved To EaglesGroup

471

public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(WriteLogEntry); } // this method should write to a file // we write to the console to see the effect // this object keeps no state public void WriteLogEntry( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Logging to file: {0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); } }

4. Now Add the following code into the Static Main () as follows: static void Main(string[] args) { // create a new clock Clock theClock = new Clock(); // create the display and tell it to // subscribe to the clock just created DisplayClock dc = new DisplayClock(); dc.Subscribe(theClock); // create a Log object and tell it // to subscribe to the clock LogCurrentTime lct = new LogCurrentTime(); lct.Subscribe(theClock); // Get the clock started theClock.Run(); }

472

All Rights Reserved To EaglesGroup

5. Now run the application and you will have the output like this:

Now lets see how the above the code works: The net effect of this code is to create two classes, DisplayClock and LogCurrentTime, both of which subscribe to a third class' event (Clock.OnSecondChange). OnSecondChange is a multicast delegate. It starts out set to null. When the observer classes wish to be notified, they create an instance of the delegate and then add these delegates to OnSecondChange. For example, in DisplayClock's Subscribe ( ) method, you see this line of code: theClock.OnSecondChange += new Clock.SecondChangeHandler(TimeHasChanged);

It turns out that the LogCurrentTime class also wants to be notified. In its Subscribe ( ) method is very similar code:

All Rights Reserved To EaglesGroup

473

public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(WriteLogEntry); }

11.1.8 Problems with Delegates and Events


There is a problem with Example 11-3, however. What if the LogCurrentTime class was not so considerate and it used the assignment operator (=) rather than the subscribe operator (+=), as in the following: public void Subscribe(Clock theClock) { theClock.OnSecondChange = new Clock.SecondChangeHandler(WriteLogEntry); }

If you make that one tiny change to the example, you'll find that the Logger ( ) method is called, but the DisplayClock method is not called. The assignment operator replaced the delegate held in the OnSecondChange multicast delegate. This is not good.

A second problem is that other methods can call SecondChangeHandler directly. For example, you might add the following code to the Main ( ) method of your Test class:

474

All Rights Reserved To EaglesGroup

Console.WriteLine("Calling the method directly!"); System.DateTime dt = System.DateTime.Now.AddHours(2); TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour,dt.Minute,dt.Second); theClock.OnSecondChange(theClock, timeInformation);

Here Main ( ) has created its own TimeInfoEventArgs object and invoked OnSecondChange directly. This runs fine, even though it is not what the designer of the Clock class intended. Here is the output

The problem is that the designer of the Clock class intended the methods encapsulated by the delegate to be invoked only when the event is fired. Here Main ( ) has gone around through the back door and invoked those methods itself. What is more, it has passed in bogus data passing in a time construct set to two hours into the future!

All Rights Reserved To EaglesGroup

475

Example 11-4 Handling Events

Example Try it out Eagles HandlingEvents Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles HandlingEvents in the directory C:\EaglesVisualCSharp\Chapter 11 Events\Example Using HandlingEvents 2. Now enter the following code in the System. Namespace as follows using System; using System.Collections.Generic; using System.Text; using System.Timers;

3. Now enter the following code in the body of the program.cs as follows: class Program { static int counter = 0; static string displayString = "Welcome to EaglesGroup ! "; static void Main(string[] args) { Timer siddhu = new Timer(100); siddhu.Elapsed += new ElapsedEventHandler(WriteChar); siddhu.Start(); Console.ReadLine(); } static void WriteChar(object source, ElapsedEventArgs sri) { Console.Write(displayString[counter++ % displayString.Length]); } }

476

All Rights Reserved To EaglesGroup

4. Run the application and the program will continuously will run and if you want to exit the program hit enter the program will terminate the application.

Lets see how the above code works: The object we are using to raise events is an instance of the system.Timers.Timerclass. This object is initialized with a time period (in milliseconds). When the timer object is started using its start () method a stream of events will be raised, spaced out in time according to the specified time period. Main (). Initializes a timer object with a timer period of 100 milliseconds, so it will raise events 10 tines a second when started. static void main (string [] Args) { Timer siddhu = new Timer (100);

The timer object possesses an event called Elapsed, and the event handler signature required by this event is that of the system.Timers.Elapsed Event handler delegate type, which is one of the standard delegates defined in the .Net framework. This delegate is used for functions that match the following signature: void function name(object source, ElapsedEvent Args e);

All Rights Reserved To EaglesGroup

477

The timer object sends a reference to itself in the first parameter and an instance of an ElapsedEvent Args object in its second parameter. It is safe to ignore these parameters for now, but will take a look at them a little later. In our code, we have a method that matches this signature ; static void writechar(objectsource.ElapsedEventArg s e) { console.write(displaystring[counter ++ %display string.length]); }

This method uses the two static fields of siddhu1, counter and displaystring, to display a single character. different. Every time the method is called the character displayed will be

myTimer.start ();

Since, we dont want the application terminating before we have handled any events, we then put the main () function on hold. The simplest way of doing this is to request user input, since this command wont finish processing until the user has entered a line of text and or / pressed the enter key. console.Readline ();

Although processing in main () effectively ceases here, processing in the timer object continues when it raises events it calls our write char () method, which runs concurrently with the console.Readline () statement.

478

All Rights Reserved To EaglesGroup

11.1.8 Defining Events


Next lets look at defining and using our own events. Well implement an example version the instant messaging case set out in the introduction to events in this chapter, and create a connection object that raises events that are handled by a display object.

Lets work it out Defining Events:

Example 11-5 Defining Events

Example Try it out Eagles DefiningEvents Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles DefiningEvents in the directory C:\EaglesVisualCSharp\Chapter 11 - Events\Example Using DefiningEvents 2. Now enter the following code in the System. Namespace as follows using System; using System.Collections.Generic; using System.Text; using System.Timers;

3. Now declare a variable which is shown below in the constructor of the program.cs public delegate void MessageHandler(string messageText);

All Rights Reserved To EaglesGroup

479

4. Now enter the following code in into the body of the program.cs as follows:

public class Connection { public event MessageHandler MessageArrived; private Timer siddhuTimer; public Connection() { siddhuTimer = new Timer(100); siddhuTimer.Elapsed += new ElapsedEventHandler(CheckForMessage); }

public void Connect() { siddhuTimer.Start(); } public void Disconnect() { siddhuTimer.Stop(); } private void CheckForMessage(object source, ElapsedEventArgs sri) { Console.WriteLine ("Checking for new messages."); Random random = new Random (); if ((random.Next (10) ==0) && (MessageArrived != null )) { MessageArrived("Welcome to EaglesGroup!"); } }

480

All Rights Reserved To EaglesGroup

5. Now add a new class name it as Display.cs in the same console application for that just right click the Solution Explorer and then add new item and then add the class and then rename it to Display.cs and enter the following code in the Display.cs body as follows: public void DisplayMessage(string message) { Console.WriteLine("Message arrived:{0}", message); }

6. Now again go to the Program.cs and then modify the code a little bit as follows add the following code in the program.cs static void Main(string[] args) { Connection myConnection = new Connection(); Display myDisplay = new Display(); myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage); myConnection.Connect(); Console.ReadLine();

} 7. Now run the application and you should see the following output

All Rights Reserved To EaglesGroup

481

Lets see how the above code works: The class that does most for the work in this application is the Connection class. Instances of the this class make use of a Timer object much like the one we saw in the first example of this chapter, initializing it in the class constructor and giving access to its state either enable or disabled via Connect () and Disconnect ():

public class Connection { public event MessageHandler MessageArrived; private Timer siddhuTimer; public Connection() { siddhuTimer = new Timer(100); siddhuTimer.Elapsed += new ElapsedEventHandler(CheckForMessage); } public void Connect() { siddhuTimer.Start(); } public void Disconnect() { siddhuTimer.Stop(); }

Also in the constructor, we register an event handler for the Elapsed event in the same way as we did in the first chapter. This handler method, CheckForMessage (), will rise on average once every ten times it is called. Before we look at the code for this, thought, lets look at the event definition itself

Before we define an evetn we must define a delegate type to use with the event that is delegate type that specific the signature that an event handling method must confirm to.

482

All Rights Reserved To EaglesGroup

We do this using standard delegate syntax, defining it as public inside the Eagles DefiningEvents namespace in order to make the type available to external code:

namespace Eagles_DefiningEvents { class Program { public delegate void MessageHandler(string messageText);

This delegate type, which weve called MessageHandler here, is a signature for a void function that has a single string parameter. We can use this parameter to pass an instant message received by the Connection object to the Display object. Once a delegate has been defined or a suitable existing delegate has been located we can define the event, itself, as a member of the Connection class: public class Connection {

public event MessageHandler MessageArrived; private Timer siddhuTimer; public Connection()

We simply name the event here we have use the name MessageArrived, and declare it using the event keyword and the delegate type to use the MessageHandler delegate type defined earlier.

All Rights Reserved To EaglesGroup

483

Once we have declared an evetn in this way we can raise it simply by calling it by its name as if it were a method with the signature specified by the delegate. For example, we could rise this event using: { MessageArrived("Welcome to EaglesGroup!"); }

If the delegate has been defined without any parameters we could use simply: MessageArrived();

Alternatively we could have defined more parameters, which would have required more code to raise the event. Our CheckForMessage () method looks like this:

private void CheckForMessage(object source, ElapsedEventArgs sri) { Console.WriteLine ("Checking for new messages."); Random random = new Random (); if ((random.Next (10) ==0) && (MessageArrived != null )) { MessageArrived("Welcome to EaglesGroup!"); } } We use an instance of random class that we have seen in earlier chapters to generate a random number between 0 and 9, and raise an evetn if the number generated is 0, which should happen 10% of the time. This simulates polling the connection to see if a message has arrived, which wont be the case every time we check. Note that we supply additional logic. We only raise an event if the expression MessageArrived! = null evaluate to true. This expression, which again uses the delegate syntax in a slightly unusual way, means: Does the event have any subscribers? if there are no subscriber, MessageArrived will evaluate to null, and there would be no point in raising the event.

484

All Rights Reserved To EaglesGroup

The class that will subscribe to the event is called Display, and contains the single method DisplayMessage () defined as follows: class Display { public void DisplayMessage(string message) { Console.WriteLine("Message arrived:{0}", message); } }

This method matches the delegate type method signature and is public, which is a requirement of event handlers in classes other than the class that generates the event, so we can use it to respond to the MessageArrived event. All that is left now is for the code in Main () to initialize instance of the Connection and Display classes, hook them up, and start things going. The code requires here is similar to that form the first example:

static void Main(string[] args) { Connection myConnection = new Connection(); Display myDisplay = new Display(); myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage); myConnection.Connect(); Console.ReadLine(); } Again, we call Console.Readline () to pause the processing of Main (), once we have started things moving with the Connect () method of the Connection objects.

All Rights Reserved To EaglesGroup

485

11.1.8 The Event Keyword


The solution to this dilemma is to use the event keyword. The event keyword indicates to the compiler that the delegate can only be invoked by the defining class, and that other classes can only subscribe to and unsubscribe from the delegate using the appropriate += and -= operators, respectively. To fix your program, change your definition of OnSecondChange from: public SecondChangeHandler OnSecondChange;

To the following public event SecondChangeHandler OnSecondChange

Adding the event keyword fixes both problems. Classes can no longer attempt to subscribe to the event using the assignment operator (=), as they could previously, nor can they invoke the event directly, as was done in Main( ) in the example above. Either of these attempts will now generate a compile error: The event 'Programming_CSharp.Clock.OnSecondChange' can only appear on the left hand side of += or -= (except when used from within the type 'Programming_CSharp.Clock')

There are two ways of looking at OnSecondChange now that you've modified it. In one sense, it is simply a delegate instance to which you've restricted access using the keyword event. In another, more important sense, OnSecondChange is an event, implemented by a delegate of type SecondChangeHandler. These two statements mean the same thing, but the latter is a more object-oriented way of looking at it, and better reflects the intent of this keyword: to create an event that your object can raise, and to which other objects can respond.

486

All Rights Reserved To EaglesGroup

Example 11-6 Using Event keyword

Example Try it out Eagles EventKeyword Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles Event in the directory C:\EaglesVisualCSharp\Chapter 11 - Events\Example Using Eventkeyword 2. Add the following code in the System. Namespace as follows: using System; using System.Collections.Generic; using System.Text; using System.Threading;

All Rights Reserved To EaglesGroup

487

3. Add the following code into the Program.cs body as follows: namespace Eagles_EventKeyword { class Program { // a class to hold the information about the event // in this case it will hold only information // available in the clock class, but could hold // additional state information public class TimeInfoEventArgs : EventArgs { public TimeInfoEventArgs(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } public readonly int hour; public readonly int minute; public readonly int second; } // our subject -- it is this class that other classes // will observe. This class publishes one event: // OnSecondChange. The observers subscribe to that event public class Clock

{ // the delegate the subscribers must implement public delegate void SecondChangeHandler ( object clock, TimeInfoEventArgs timeInformation ); // the keyword event controls access to the delegate public event SecondChangeHandler OnSecondChange; // set the clock running // it will raise an event for each new second public void Run() {
All Rights Reserved To EaglesGroup

488

for (; ; ) { // sleep 10 milliseconds Thread.Sleep(10); // get the current time System.DateTime dt = System.DateTime.Now; // if the second has changed // notify the subscribers if (dt.Second != second) { // create the TimeInfoEventArgs object // to pass to the subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour, dt.Minute, dt.Second); // if anyone has subscribed, notify them if (OnSecondChange != null) { OnSecondChange( this, timeInformation); } }

// update the state this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; } } private int hour; private int minute; private int second; } // an observer. DisplayClock subscribes to the // clock's events. The job of DisplayClock is // to display the current time

All Rights Reserved To EaglesGroup

489

public class DisplayClock { // given a clock, subscribe to // its SecondChangeHandler event public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(TimeHasChanged); } // the method that implements the // delegated functionality public void TimeHasChanged( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Current Time: {0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); }

// a second subscriber whose job is to write to a file public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(WriteLogEntry); } // this method should write to a file // we write to the console to see the effect // this object keeps no state public void WriteLogEntry( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Logging to file: {0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); } 490 }

All Rights Reserved To EaglesGroup

4. Now add the following code in the Main () the code as follows:

static void Main(string[] args) { // create a new clock Clock theClock = new Clock(); // create the display and tell it to // subscribe to the clock just created DisplayClock dc = new DisplayClock(); dc.Subscribe(theClock); // create a Log object and tell it // to subscribe to the clock LogCurrentTime lct = new LogCurrentTime(); lct.Subscribe(theClock); // Get the clock started theClock.Run(); }

5. Now run the program and the output you should have like this:

All Rights Reserved To EaglesGroup

491

11.1.9 Return Values and Event Handlers


All the event handlers weve seen so far have had a return type of void. It is possible a return type for an event, but this can lead to problems. This is because a given event may result in several event handlers being called. If all of these handlers return a value it leaves us in some doubt as to which value was actually returned. The system deals with this by only allowing us access to the last value returned by an event handler. This will be the value returned by the last event handler to subscribe to an event. Perhaps this functionality might be of use in some situations, although I cant think of one off the top of my head. Id recommend using void type event handlers, as well as avoiding out type parameters.

Summary
In this chapter, we have looked at the important topic of events and event handling. Although, initially difficult to get your head around, the code involved is quiet simple and youll certainly be using event handlers a lot in the rest of the book. With this chapter we have completed not only a complete description of OOP as applied to C# programming, but also a complete description of the C# language. From this point on we will be applying this knowledge to make complex scenarios, such as creating windows and web applications as well as making more use of the .Net framework. In this chapter we had look the Delegates and Events and their uses and the keywords with the proper example so far we have covered the sub topics also witch are as follows: Introduction to Delegates Using Delegates to Specify Methods at Runtime Delegates and Instance Methods Static Delegates Delegates as Properties Setting Order of Execution with Delegate Arrays Introduction to Events What is an event? Event Handlers Event Sources Using Events Handling Events Publishing and Subscribing Events and Delegates The Event Keyword Return Values and Event Handlers
All Rights Reserved To EaglesGroup

492

Chapter 12

All Rights Reserved To EaglesGroup

493

Preprocessor Directives
12.1 Introduction to Preprocessor Directives

In the examples you've seen so far, you've compiled your entire program whenever you compiled any of it. At times, however, you might want to compile only parts of your programfor example, depending on whether you are debugging or building your production code. Before your code is compiled, another program called the preprocessor runs and prepares your program for the compiler. The preprocessor examines your code for special preprocessor directives, all of which begin with the pound sign (#). These directives allow you to define identifiers and then test for their existence.

12.1.1 Defining Identifiers


#define DEBUG

defines a preprocessor identifier, DEBUG. Although other preprocessor directives can come anywhere in your code, identifiers must be defined before any other code, including using statements.

DENOTE: C and C++ programmer take note: The C# preprocessor implements only a subset of the C++ preprocessor.

You can test whether DEBUG has been defined with the #if statement. Thus, you can write: #define DEBUG //... some normal code - not affected by preprocessor #if DEBUG // code to include if debugging #else // code to include if not debugging #endif //... some normal code - not affected by preprocessor - #endif block.

494

All Rights Reserved To EaglesGroup

When the preprocessor runs, it sees the #define statement and records the identifier DEBUG. The preprocessor skips over your normal C# code and then finds the #if - #else

The #if statement tests for the identifier DEBUG, which does exist, and so the code between #if and #else is compiled into your programbut the code between #else and #endif is not compiled. That code does not appear in your assembly at all; it is as if it were left out of your source code. Had the #if statement failedthat is, if you had tested for an identifier that did not existthe code between #if and #else would not be compiled, but the code between #else and #endif would be compiled.

DENOTE: Any code not surrounded by #if - #endif is not affected by the preprocessor and is compiled into your program.

12.1.2 Undefining Identifiers


Undefine an identifier with #undef. The preprocessor works its way through the code from top to bottom, so the identifier is defined from the #define statement until the #undef statement, or until the program ends. Thus if you write: #define DEBUG #if DEBUG // this code will be compiled #endif #undef DEBUG #if DEBUG // this code will not be compiled #endif

The first #if will succeed (DEBUG is defined), but the second will fail (DEBUG has been undefined).

All Rights Reserved To EaglesGroup

495

12.1.3 #if, #elif, #else, and #endif:


There is no switch statement for the preprocessor, but the #elif and #else directives provide great flexibility. The #elif directive allows the else-if logic of "if DEBUG then action one, else if TEST then action two, else action three": #if DEBUG // compile this code if debug is defined #elif TEST // compile this code if debug is not defined // but TEST is defined #else // compile this code if neither DEBUG nor TEST // is defined #endif

In this example, the preprocessor first tests to see if the identifier DEBUG is defined. If it is, the code between #if and #elif will be compiled, and the rest of the code until #endif will not be compiled. If (and only if) DEBUG is not defined, the preprocessor next checks to see if TEST is defined. Note that the preprocessor will not check for TEST unless DEBUG is not defined. If TEST is defined, the code between the #elif and the #else directives will be compiled. If it turns out that neither DEBUG nor TEST is defined, the code between the #else and the #endif statements will be compiled.

12.2 #region:
The #region preprocessor directive marks an area of text with a comment. The principal use of this preprocessor directive is to allow tools such as Visual Studio .NET to mark off areas of code and collapse them in the editor with only the region's comment showing. For example, when you create a Windows application Visual Studio .NET creates a region for code generated by the designer. When the region is expanded, it looks like Figure 12-1. (Note: I've added the rectangle and highlighting to make it easier to find the region.)

496

All Rights Reserved To EaglesGroup

Figure 12-1. Expanding the Visual Studio .NET code region

You can see the region marked by the #region and #endregion preprocessor directives. When the region is collapsed, however, all you see is the region comment (Windows Form Designer generated code), as shown in Figure 9-2.

Figure 12-2. Code region is collapsed

Summary:
In this chapter we know about the preprocessor directives and how it works and we also see the sub topics which is useful to the preprocessor directives they are as follows: Introduction to Preprocessor Directives Defining Identifiers Undefining Identifiers #if, #elif, #else, and #endif #region

All Rights Reserved To EaglesGroup

497

Chapter 13

498

All Rights Reserved To EaglesGroup

Handling Exceptions
13.0 Introduction to Handling Exceptions:

Like many object-oriented languages, C# handles errors and abnormal conditions with exceptions. An exception is an object that encapsulates information about an unusual program occurrence. It is important to distinguish between bugs, errors, and exceptions. A bug is a programmer mistake that should be fixed before the code is shipped. Exceptions are not a protection against bugs. Although a bug might cause an exception to be thrown, you should not rely on exceptions to handle your bugs. Rather, you should fix the bugs. An error is caused by user action. For example, the user might enter a number where a letter is expected. Once again, an error might cause an exception, but you can prevent that by catching errors with validation code. Whenever possible, errors should be anticipated and prevented. Even if you remove all bugs and anticipate all user errors, you will still run into predictable but unpreventable problems, such as running out of memory or attempting to open a file that no longer exists. You cannot prevent exceptions, but you can handle them so that they do not bring down your program. When your program encounters an exceptional circumstance, such as running out of memory, it throws (or "raises") an exception. When an exception is thrown, execution of the current function halts and the stack is unwound until an appropriate exception handler is found. This means that if the currently running function does not handle the exception, the current function will terminate and the calling function will get a chance to handle the exception. If none of the calling functions handles it, the exception will ultimately be handled by the CLR, which will abruptly terminate your program. An exception handler is a block of code designed to handle the exception you've thrown. Exception handlers are implemented as catch statements. Ideally, if the exception is caught and handled, the program can fix the problem and continue. Even if your program can't continue, by catching the exception, you have an opportunity to print a meaningful error message and terminate gracefully. If there is code in your function that must run regardless of whether an exception is encountered (e.g., to release resources you've allocated), you can place that code in a finally block, where it is certain to run, even in the presence of exceptions.
All Rights Reserved To EaglesGroup

499

13.1 Throwing and Catching Exceptions

In C#, you can throw only objects of type System.Exception, or objects derived from that type. The CLR System namespace includes a number of exception types that your program can use. These exception types include ArgumentNullException, InvalidCastException, and OverflowException, as well as many others.

DENOTE: C++ programmers take note: In C#, not just any object can be thrownit must be derived from System.Exception.

13.1.1 The throw Statement


To signal an abnormal condition in a C# class, you throw an exception. To do this, use the keyword throw. This line of code creates a new instance of System.Exception and then throws it: throw new System.Exception ( ); Throwing an exception immediately halts execution while the CLR searches for an exception handler. If an exception handler cannot be found in the current method, the runtime unwinds the stack, popping up through the calling methods until a handler is found. If the runtime returns all the way through Main ( ) without finding a handler, it terminates the program. Example 13-1 illustrates.

500

All Rights Reserved To EaglesGroup

Example 13-1 throwing an exception

Example Try it out Eagles throwing an exception Step by Step Example: Using Version 2005

1. Create a new Console Application named Eagles Throwing an exception in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Throwing an exception 2. Now Enter the following code in the program.cs body and the code as follows public class Test { static void Main(string[] args) { Console.WriteLine("Enter Main..."); Test t = new Test(); t.Func1(); Console.WriteLine("Exit Main..."); } public void Func1() { Console.WriteLine("Enter Func1..."); Func2(); Console.WriteLine("Exit Func1..."); } public void Func2() { Console.WriteLine("Enter Func2..."); throw new System.Exception(); Console.WriteLine("Exit Func2..."); } } } }

All Rights Reserved To EaglesGroup

501

3. After Entering the code compile and run the application and you should have a output like this:

This simple example writes to the console as it enters and exits each method. Main ( ) creates an instance of type Test and call Func1 ( ). After printing out the Enter Func1 message, Func1 ( ) immediately calls Func2 ( ). Func2 ( ) prints out the first message and throws an object of type System.Exception. Execution immediately stops, and the CLR looks to see if there is a handler in Func2 ( ). There is not, and so the runtime unwinds the stack (never printing the exit statement) to Func1 ( ). Again, there is no handler, and the runtime unwinds the stack back to Main ( ). With no exception handler there, the default handler is called, which prints the error message.

502

All Rights Reserved To EaglesGroup

13.1.2 The catch Statement

In C#, an exception handler is called a catch block and is created with the catch keyword. In Example 13-2, the throw statement is executed within a try block, and a catch block is used to announce that the error has been handled.

Example 13-2 catching an exception

Example Try it out Eagles Catching an exception Step by Step Example: Using Version 2005
1. Create a new Console application name it as Eagles Catching an exception in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Catching an exception 2. Now enter the following code in the Program.cs as follows:

All Rights Reserved To EaglesGroup

503

public class Test { static void Main(string[] args) { Console.WriteLine("Enter Main..."); Test t = new Test( ); t.Func1( ); Console.WriteLine("Exit Main..."); } public void Func1() { Console.WriteLine("Enter Func1..."); Func2(); Console.WriteLine("Exit Func1..."); } public void Func2() { Console.WriteLine("Enter Func2..."); try { Console.WriteLine("Entering try block..."); throw new System.Exception(); Console.WriteLine("Exiting try block..."); } catch { Console.WriteLine( "Exception caught and handled."); } Console.WriteLine("Exit Func2..."); } } } }

504

All Rights Reserved To EaglesGroup

3. Now Run the application and you should see something like this:

Example 13.2is identical to Example 13-1 except that now the program includes a try/catch block. You would typically put the try block around a potentially "dangerous" statement, such as accessing a file, allocating memory, and so forth. Following the try statement is a generic catch statement. The catch statement in Example 13-2 is generic because you haven't specified what kind of exceptions to catch. In this case, the statement will catch any exceptions that are thrown. Using catch statements to catch specific types of exceptions is discussed later in this chapter.

13.1.2.1 Taking corrective action


In Example 13-2, the catch statement simply reports that the exception has been caught and handled. In a real-world example, you might take corrective action to fix the problem that caused an exception to be thrown. For example, if the user is trying to open a readonly file, you might invoke a method that allows the user to change the attributes of the file. If the program has run out of memory, you might give the user an opportunity to close other applications. If all else fails, the catch block can print an error message so that the user knows what went wrong.

All Rights Reserved To EaglesGroup

505

13.1.2.2 Unwinding the call stack

Examine the output of Example 13-2 carefully. You see the code enter Main( ), Func1( ), Func2( ), and the try block. You never see it exit the try block, though it does exit Func2( ), Func1( ), and Main( ). What happened? When the exception is thrown, execution halts immediately and is handed to the catch block. It never returns to the original code path. It never gets to the line that prints the exit statement for the try block. The catch block handles the error, and then execution falls through to the code following catch. Without catch the call stack unwinds, but with catch it does not unwind, as a result of the exception. The exception is now handled; there are no more problems, and the program continues. This becomes a bit clearer if you move the try/catch blocks up to Func1( ), as shown in Example 13-3.

Example 13-3. Catch in a calling function

Example Try it out Eagles Catch in a calling function Step by Step Example: Using Version 2005
1. Create a new Console Application named as Eagles CatchcallingFunction in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Catch in a calling function 2. Enter the following code in the Program.cs

506

All Rights Reserved To EaglesGroup

public class Test { static void Main(string[] args) { Console.WriteLine("Enter Main..."); Test t = new Test(); t.Func1(); Console.WriteLine("Exit Main..."); } public void Func1() { Console.WriteLine("Enter Func1..."); try { Console.WriteLine("Entering try block..."); Func2(); Console.WriteLine("Exiting try block..."); } catch { Console.WriteLine( "Exception caught and handled."); } Console.WriteLine("Exit Func1..."); } public void Func2() { Console.WriteLine("Enter Func2..."); throw new System.Exception(); Console.WriteLine("Exit Func2..."); } }

All Rights Reserved To EaglesGroup

507

3. Now run the application and you should have the output like this:

This time the exception is not handled in Func2( ), it is handled in Func1( ). When Func2( ) is called, it prints the Enter statement and then throws an exception. Execution halts and the runtime looks for a handler, but there isn't one. The stack unwinds, and the runtime finds a handler in Func1( ). The catch statement is called, and execution resumes immediately following the catch statement, printing the Exit statement for Func1( ) and then for Main( ). Make sure you are comfortable with why the Exiting Try Block statement and the Exit Func2 statement are not printed. This is a classic case where putting the code into a debugger and then stepping through it can make things very clear.

13.1.2.3 Creating dedicated catch statements


So far, you've been working only with generic catch statements. You can create dedicated catch statements that handle only some exceptions and not others, based on the type of exception thrown. Example 13-4 illustrates how to specify which exception you'd like to handle

Example 13-4. Specifying the exception to catch

Example Try it out Eagles exception to catch Step by Step Example: Using Version 2005

508

All Rights Reserved To EaglesGroup

1. Create a new Console Application name it as Eagles exception to catch in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Exception to catch 2. Enter the following code into the program.cs as follows:
public class eagles { static void Main(string[] args) { eagles siddhu = new eagles(); siddhu.SriFunc(); } // try to divide two numbers // handle possible exceptions public void SriFunc() { try { double a = 5; double b = 0; Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b)); } // most derived exception type first catch (System.DivideByZeroException) { Console.WriteLine("DivideByZeroException caught!"); } catch (System.ArithmeticException) { Console.WriteLine("ArithmeticException caught!"); } // generic exception type last catch { Console.WriteLine("Unknown exception caught"); } } // do the division if legal public double DoDivide(double a, double b) { if (b == 0) throw new System.DivideByZeroException(); if (a == 0) throw new System.ArithmeticException(); return a / b; } }

All Rights Reserved To EaglesGroup

509

3. Now run the application and you should have the output like this:

In this example, the DoDivide ( ) method will not let you divide zero by another number, nor will it let you divide a number by zero. It throws an instance of DivideByZeroException if you try to divide by zero. If you try to divide zero by another number, there is no appropriate exceptiondividing zero by another number is a legal mathematical operation and shouldn't throw an exception at all. For the sake of this example, assume you don't want to allow division by zero; you will throw an ArithmeticException. When the exception is thrown, the runtime examines each exception handler in order and matches the first one it can. When you run this with a=5 and b=7, the output is: 5 / 7 = 0.7142857142857143 As you'd expect, no exception is thrown. However, when you change the value of a to 0, the output is: ArithmeticException caught! The exception is thrown, and the runtime examines the first exception, DivideByZeroException. Because this does not match, it goes on to the next handler, ArithmeticException, which does match. In a final pass through, suppose you change a to 7 and b to 0. This throws the DivideByZeroException.

510

All Rights Reserved To EaglesGroup

DENOTE: You have to be particularly careful with the order of the catch statements, because the DivideByZeroException is derived from ArithmeticException. If you reverse the catch statements, the DivideByZeroException will match the ArithmeticException handler, and the exception will never get to the DivideByZeroException handler. In fact, if their order is reversed, it will be impossible for any exception to reach the DivideByZeroException handler. The compiler will recognize that the DivideByZeroException handler cannot be reached and will report a compile error!

It is possible to distribute your try/catch statements, catching some specific exceptions in one function and more generic exceptions in higher, calling functions. Your design goals should dictate the exact design. Assume you have a method A that calls another method B, which in turn calls method C. Method C calls method D, which then calls method E. Method E is deep in your code; methods B and A are higher up. If you anticipate that method E might throw an exception, you should create a try/catch block deep in your code to catch that exception as close as possible to the place where the problem arises. You might also want to create more general exception handlers higher up in the code in case unanticipated exceptions slip by.

13.1.3 The finally Statement


In some instances, throwing an exception and unwinding the stack can create a problem. For example, if you have opened a file or otherwise committed a resource, you might need an opportunity to close the file or flush the buffer.

DENOTE: In C#, this is less of a problem than in other languages, such as C++, because the garbage collection prevents the exception from causing a memory leak.

In the event, however, that there is some action you must take regardless of whether an exception is thrown (such as closing a file) you have two strategies to choose from. One approach is to enclose the dangerous action in a try block and then to close the file in both the catch and try blocks. However, this is an ugly duplication of code, and it's error prone. C# provides a better alternative in the finally block.

All Rights Reserved To EaglesGroup

511

The code in the finally block is guaranteed to be executed regardless of whether an exception is thrown. The TestFunc ( ) method in Example 13-5 simulates opening a file as its first action. The method undertakes some mathematical operations, and the file is closed. It is possible that some time between opening and closing the file an exception will be thrown. If this were to occur, it would be possible for the file to remain open. The developer knows that no matter what happens, at the end of this method the file should be closed, so the file close function call is moved to a finally block, where it will be executed regardless of whether an exception is thrown.

Example 13-5. Using a finally block

Example Try it out Eagles finally block Step by Step Example: Using Version 2005
1. Create a new Console application called it as Eagles Final bloc in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Final bloc

512

All Rights Reserved To EaglesGroup

2. Now Enter the following code into the Program.cs public class Test { static void Main(string[] args) { Test t = new Test(); t.TestFunc(); // try to divide two numbers // handle possible exceptions } public void TestFunc() { try { Console.WriteLine("Open file here"); double a = 5; double b = 0; Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b)); Console.WriteLine( "This line may or may not print"); } // most derived exception type first catch (System.DivideByZeroException) { Console.WriteLine( "DivideByZeroException caught!"); } catch { Console.WriteLine("Unknown exception caught"); } finally { Console.WriteLine("Close file here."); } } // do the division if legal public double DoDivide(double a, double b) { if (b == 0) throw new System.DivideByZeroException(); if (a == 0) throw new System.ArithmeticException(); return a / b; } }

All Rights Reserved To EaglesGroup

513

3. Now run the console application and you should see the output like this:

4. Now assign a value for b as 12 and the code as follows: public void TestFunc() { try { Console.WriteLine("Open file here"); double a = 5; double b = 12; Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b)); Console.WriteLine( "This line may or may not print"); }

514

All Rights Reserved To EaglesGroup

5. Now run the application and you should have the output like this:

In this example, one of the catch blocks has been eliminated to save space, and a finally block has been added. Whether or not an exception is thrown, the finally block is executed, and so in both output examples you see the message: Close file here.

DENOTE: A finally block can be created with or without catch blocks, but a finally block requires a try block to execute. It is an error to exit a finally block with break, continue, return, or goto.

13.2 Exception Objects


So far you've been using the exception as a sentinelthat is, the presence of the exception signals the errorbut you haven't touched or examined the Exception object itself. The System.Exception object provides a number of useful methods and properties. The Message property provides information about the exception, such as why it was thrown. The Message property is read-only; the code throwing the exception can set the Message property as an argument to the exception constructor. The Help Link property provides a link to the help file associated with the exception. This property is read/write.

All Rights Reserved To EaglesGroup

515

DENOTE: VB6 programmers take note: In C#, you need to be careful when declaring and instantiating object variables on the same line of code. If there is a possibility that an error could be thrown in the constructor method, then you might be temped to put the variable declaration and instantiation inside the try block. But if you do that, the variable will only be scoped within the try block and it can't be referenced within the catch or finally blocks. The best approach is to declare the object variable before the try block and instantiate it within the try block. The Stack Trace property is read-only and is set by the runtime. In Example 13-6, the Exception.HelpLink property is set and retrieved to provide information to the user about the DivideByZeroException. The Stack Trace property of the exception is used to provide a stack trace for the error statement. A stack trace displays the call stack: the series of method calls that lead to the method in which the exception was thrown.

Example 13-6. Working with an exception object

Example Try it out Eagles Exception object Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles Exception object in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Eagles Exception object

516

All Rights Reserved To EaglesGroup

2. Now enter the following code in the program.cs.


public class Test { static void Main(string[] args) { Test t = new Test(); t.TestFunc(); } // try to divide two numbers // handle possible exceptions public void TestFunc() { try { Console.WriteLine("Open file here"); double a = 12; double b = 0; Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b)); Console.WriteLine( "This line may or may not print"); } // most derived exception type first catch (System.DivideByZeroException e) { Console.WriteLine( "\nDivideByZeroException! Msg: {0}",e.Message); Console.WriteLine(\nHelpLink: {0}", e.HelpLink); Console.WriteLine("\nHere's a stack trace: {0}\n", e.StackTrace); } catch { Console.WriteLine( "Unknown exception caught"); } finally { Console.WriteLine( "Close file here."); } } // do the division if legal public double DoDivide(double a, double b) { if (b == 0) { DivideByZeroException e = new DivideByZeroException(); e.HelpLink = "http://www.eaglesgroup.com"; throw e; } if (a == 0) throw new ArithmeticException(); return a / b; }

All Rights Reserved To EaglesGroup

517

3. Now run the console application and you should see some thing like this:

In the output, the stack trace lists the methods in the reverse order in which they were called; that is, it shows that the error occurred in DoDivide( ), which was called by TestFunc( ). When methods are deeply nested, the stack trace can help you understand the order of method calls. In this example, rather than simply throwing a DivideByZeroException, you create a new instance of the exception: DivideByZeroException e = new DivideByZeroException ( ); you do not pass in a custom message, and so the default message will be printed: DivideByZeroException! Msg: Attempted to divide by zero. You can modify this line of code to pass in a default message: new DivideByZeroException ("You tried to divide by zero which is not meaningful"); In this case, the output message will reflect the custom message: DivideByZeroException! Msg: You tried to divide by zero which is not meaningful Before throwing the exception, set the HelpLink property: e.HelpLink = http://www.eaglesgroup.com"; When this exception is caught, the program prints the message and the HelpLink: catch (System.DivideByZeroException e) { Console.WriteLine("\nDivideByZeroException! Msg: {0}", e.Message); Console.WriteLine("\nHelpLink: {0}", e.HelpLink);

518

All Rights Reserved To EaglesGroup

This allows you to provide useful information to the user. In addition, it prints the StackTrace by getting the StackTrace property of the exception object: Console.WriteLine("\nHere's a stack trace: {0}\n", e.StackTrace);

13.3 Custom Exceptions


The intrinsic exception types the CLR provides, coupled with the custom messages shown in the previous example, will often be all you need to provide extensive information to a catch block when an exception is thrown. There will be times, however, when you want to provide more extensive information or need special capabilities in your exception. It is a trivial matter to create your own custom exception class; the only restriction is that it must derive (directly or indirectly) from System.ApplicationException. Example 13-7 illustrates the creation of a custom exception.

Example 13-7. Creating a custom exception

Example Try it out Eagles Custom Exception Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles Custom exception in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Custom Exception 2. Now enter the following code in the program.cs as follows:

All Rights Reserved To EaglesGroup

519

public class SiddhuEagles : System.ApplicationException { public SiddhuEagles(string message) : base(message) { } } public class Sri { public static void Main() { Sri t = new Sri(); t.TestFunc(); } // try to divide two numbers // handle possible exceptions public void TestFunc() { try { Console.WriteLine("Open file here"); double a = 0; double b = 5; Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b)); Console.WriteLine( "This line may or may not print"); } // most derived exception type first catch (System.DivideByZeroException e) { Console.WriteLine( "\nDivideByZeroException! Msg: {0}", e.Message); Console.WriteLine( "\nHelpLink: {0}\n", e.HelpLink); } catch (SiddhuEagles e) { Console.WriteLine( "\nMyCustomException! Msg: {0}", e.Message); Console.WriteLine( "\nHelpLink: {0}\n", e.HelpLink); } catch

520

All Rights Reserved To EaglesGroup

{ Console.WriteLine( "Unknown exception caught"); } finally { Console.WriteLine("Close file here."); } } // do the division if legal public double DoDivide(double a, double b) { if (b == 0) { DivideByZeroException e = new DivideByZeroException(); e.HelpLink = "http://www.eaglesgroup.com"; throw e; } if (a == 0) { SiddhuEagles e = new SiddhuEagles ( "Can't have zero divisor"); e.HelpLink = "http://www.eaglesgroup.com/ZeroDivider.aspx"; throw e; } return a / b; } }

All Rights Reserved To EaglesGroup

521

3. Now run the application and you should have a output like this:

SiddhuEagles is derived from System.ApplicationException and consists of nothing more than a constructor that takes a string message that it passes to its base class. In this case, the advantage of creating this custom exception class is that it better reflects the particular design of the Test class, in which it is not legal to have a zero divisor. Using the ArithmeticException rather than a custom exception would work as well, but it might confuse other programmers because a zero divisor wouldn't normally be considered an arithmetic error.

13.4 Rethrowing Exceptions


You might want your catch block to take some initial corrective action and then rethrow the exception to an outer try block (in a calling function). It might rethrow the same exception, or it might throw a different one. If it throws a different one, it may want to embed the original exception inside the new one so that the calling method can understand the exception history. The Inner Exception property of the new exception retrieves the original exception. Because the Inner Exception is also an exception, it too might have an inner exception. Thus, an entire chain of exceptions can be nested one within the other, much like Ukrainian dolls are contained one within the other. Example 13-8 illustrates.

522

All Rights Reserved To EaglesGroup

Example 13-8. Rethrowing inner exceptions

Example Try it out Eagles Inner Exceptions Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles Inner Exceptions in the directory C:\EaglesVisualCSharp\Chapter 13 Handling Exceptions\Example Using Inner Exceptions 2. Now enter the following code into the Program.cs as follows: public class SiddhuEagles : System.ApplicationException { public SiddhuEagles( string message, Exception inner) : base(message, inner) { } } public class Test { public static void Main() { Test t = new Test(); t.TestFunc(); } public void TestFunc() { try { DangerousFunc1(); } // if you catch a custom exception // print the exception history catch (SiddhuEagles e) { Console.WriteLine("\n{0}", e.Message); Console.WriteLine( "Retrieving exception history..."); Exception inner = e.InnerException; while (inner != null) { Console.WriteLine( "{0}", inner.Message); inner = inner.InnerException; } } }
All Rights Reserved To EaglesGroup

523

public void DangerousFunc1() { try { DangerousFunc2(); } // if you catch any exception here // throw a custom exception catch (System.Exception e) { SiddhuEagles ex = new SiddhuEagles ( "E3 - Custom Exception Situation!", e); throw ex; } }

public void DangerousFunc2() { try { DangerousFunc3(); } // if you catch a DivideByZeroException take some // corrective action and then throw a general exception catch (System.DivideByZeroException e) { Exception ex = new Exception( "E2 - Func2 caught divide by zero", e); throw ex; } }

524

All Rights Reserved To EaglesGroup

public void DangerousFunc3() { try { DangerousFunc4(); } catch (System.ArithmeticException) { throw; } catch (System.Exception) { Console.WriteLine( "Exception handled here."); } } public void DangerousFunc4() { throw new DivideByZeroException("E1 - DivideByZero Exception"); }

3. Now run the application and you should see the output like this

Because this code has been stripped to the essentials, the output might leave you scratching your head. The best way to see how this code works is to use the debugger to step through it.

All Rights Reserved To EaglesGroup

525

Begin by calling DangerousFunc1( ) in a try block: try { DangerousFunc1 ( ); }

DangerousFunc1 ( ) calls DangerousFunc2 ( ), which calls DangerousFunc3 ( ), which in turn calls DangerousFunc4 ( ). All these calls are in their own try blocks. At the end, DangerousFunc4 ( ) throws a DivideByZeroException. System.DivideByZeroException normally has its own error message, but you are free

to pass in a custom message. Here, to make it easier to identify the sequence of events, the custom message E1 - DivideByZeroException is passed in. The exception thrown in DangerousFunc4 ( ) is caught in the catch block in DangerousFunc3 ( ). The logic in DangerousFunc3 ( ) is that if any ArithmeticException is caught (such as DivideByZeroException), it takes no action; it just rethrows the exception: catch (System.ArithmeticException) { throw; }

The syntax to rethrow the exact same exception (without modifying it) is just the word throw. The exception is thus rethrown to DangerousFunc2 ( ), which catches it, takes some corrective action, and throws a new exception of type Exception. In the constructor to that new exception, DangerousFunc2 ( ) passes in a custom message (E2 - Func2 caught divide by zero) and the original exception. Thus, the original exception (E1) becomes the Inner Exception for the new exception (E2). DangerousFunc2 ( ) then throws this new E2 exception to DangerousFunc1 ( ).
DangerousFunc1 ( ) catches the exception, does some work, and creates a new exception of type SiddhuEagles. It passes a new string (E3 - Custom Exception Situation!) to the constructor as well as the exception it just caught (E2). Remember, the exception it just caught is the exception with a DivideByZeroException (E1) as its inner exception. At this point, you have an exception of type SiddhuEagles (E3), with an inner exception of type Exception (E2), which in turn has an inner exception of type DivideByZeroException (E1). All this is then thrown to the test function, where it is

caught.

526

All Rights Reserved To EaglesGroup

When the catch function runs, it prints the message: E3 - Custom Exception Situation! and then drills down through the layers of inner exceptions, printing their messages: while (inner != null) { Console.WriteLine("{0}",inner.Message); inner = inner.InnerException; }

The output reflects the chain of exceptions thrown and caught:

All Rights Reserved To EaglesGroup

527

Summary
In this chapter we had known more knowledge of the Handling Exceptions and the sections we covered are as follows:

Introduction to Handling Exceptions Throwing and Catching Exceptions The throw Statement The catch Statement Taking corrective action Unwinding the call stack Creating dedicated catch statements The finally Statement Exception Objects Custom Exceptions Rethrowing Exceptions

528

All Rights Reserved To EaglesGroup

Chapter 14

All Rights Reserved To EaglesGroup

529

Strings and Regular Expressions


14.1 Introduction to Strings and Regular Expressions
There was a time when people thought of computers exclusively as manipulating numeric values. Early computers were first used to calculate missile trajectories, and programming was taught in the math department of major universities. Today, most programs are concerned more with strings of characters than with strings of numbers. Typically these strings are used for word processing, document manipulation, and creation of web pages. C# provides built-in support for a fully functional string type. More importantly, C# treats strings as objects that encapsulate all the manipulation, sorting, and searching methods normally applied to strings of characters. Complex string manipulation and pattern matching is aided by the use of regular expressions. C# combines the power and complexity of regular expression syntax, originally found only in string manipulation languages such as awk and Perl, with a fully object-oriented design. In this chapter, you will learn to work with the C# string type and the .NET Framework System.String class that it aliases. You will see how to extract substrings, manipulate and concatenate strings, and build new strings with the StringBuilder class. In addition, you will learn how to use the RegEx class to match strings based on complex regular expressions.

14.2 Strings
C# treats strings as first-class types that are flexible, powerful, and easy to use. Each string object is an immutable sequence of Unicode characters. In other words, methods that appear to change the string actually return a modified copy; the original string remains intact. When you declare a C# string using the string keyword, you are in fact declaring the object to be of the type System.String, one of the built-in types provided by the .NET Framework Class Library. A C# string type is a System.String type, and we will use the names interchangeably throughout the chapter.

530

All Rights Reserved To EaglesGroup

The declaration of the System.String class is: public sealed class String: IComparable, ICloneable, IConvertible, IEnumerable This declaration reveals that the class is sealed, meaning that it is not possible to derive from the string class. The class also implements four system interfacesIComparable, ICloneable, IConvertible, and IEnumerablethat dictate functionality that System.String shares with other classes in the .NET Framework.

DENOTE: C and C++ programmers take note: C# strings are immutable; modifying a string does not modify it in place. This may have performance implications. If you plan to do significant string manipulation, use a StringBuilder.

The IComparable interface is implemented by types whose values can be ordered. Strings, for example, can be alphabetized; any given string can be compared with another string to determine which should come first in an ordered list. IComparable classes implement the CompareTo method. Lets you use the foreach construct to enumerate a string as a collection of chars.
ICloneable

objects can create new instances with the same value as the original instance. In this case, it is possible to clone a string to produce a new string with the same values (characters) as the original. ICloneable classes implement the Clone ( ) method.
IConvertible classes provide methods to facilitate as ToInt32 ( ), ToDouble ( ), ToDecimal ( ), etc.

conversion to other primitive types such

All Rights Reserved To EaglesGroup

531

14.2.1 Creating Strings


The most common way to create a string is to assign a quoted string of characters, known as a string literal, to a user-defined variable of type string: string newString = "This is a string literal";

Quoted strings can include escape characters, such as "\n" or "\t," which begin with a backslash character (\) and are used to indicate where line breaks or tabs are to appear. Because the backslash is itself used in some command-line syntax, such as URLs or directory paths, in a quoted string the backslash must be preceded by another backslash. Strings can also be created using verbatim string literals, which start with the (@) symbol. This tells the String constructor that the string should be used verbatim, even if it spans multiple lines or includes escape characters. In a verbatim string literal, backslashes and the characters that follow them are simply considered additional characters of the string. Thus, the following two definitions are equivalent: string literalOne = "\\\\MySystem\\MyDirectory\\ProgrammingC#.cs"; string verbatimLiteralOne = @"\\MySystem\MyDirectory\ProgrammingC#.cs"; In the first line, a nonverbatim string literal is used, and so the backslash characters (\) must be escaped. This means it must be preceded by a second backslash character. In the second line, a verbatim literal string is used, so the extra backslash is not needed. A second example illustrates multiline verbatim strings: string literalTwo = "Line One\nLine Two"; string verbatimLiteralTwo = @"Line One, Line Two";

Again, these declarations are interchangeable. Which one you use is a matter of convenience and personal style.

532

All Rights Reserved To EaglesGroup

14.2.2 The ToString ( ) Method


Another common way to create a string is to call the ToString ( ) method on an object and assign the result to a string variable. All the built-in types override this method to simplify the task of converting a value (often a numeric value) to a string representation of that value. In the following example, the ToString ( ) method of an integer type is called to store its value in a string: int myInteger = 5; string integerString = myInteger.ToString( );

The call to myInteger.ToString ( ) returns a String object, which is then assigned to integerString. The .NET String class provides a wealth of overloaded constructors that support a variety of techniques for assigning string values to string types. Some of these constructors enable you to create a string by passing in a character array or character pointer. Passing in a character array as a parameter to the constructor of the String creates a CLR-compliant new instance of a string. Passing in a character pointer creates a noncompliant, "unsafe" instance.

14.2.3 Manipulating Strings


The string class provides a host of methods for comparing, searching, and manipulating strings, as shown in Table 14-1.

All Rights Reserved To EaglesGroup

533

Table 14-1. Methods and fields for the string class

Method or field
Empty

Purpose

Public static field that represents the empty string. Overloaded public static method that compares two strings. Overloaded public static method that compares two strings without regard to local or culture.

Compare( )

CompareOrdinal( )

Concat( )

Copy( ) Equals( )

Format( )

Intern( )

IsInterned( ) Join( )

Chars Length Clone( ) CompareTo( ) CopyTo( )

Overloaded public static method that creates a new string from one or more strings. Public static method that creates a new string by copying another. Overloaded public static and instance method that determines if two strings have the same value. Overloaded public static method that formats a string using a format specification. Public static method that returns a reference to the specified instance of a string. Public static method that returns a reference for the string. Overloaded public static method that concatenates a specified string between each element of a string array. The string indexer. The number of characters in the instance. Returns the string. Compares this string with another. Copies the specified number of characters to an array of Unicode characters.

534

All Rights Reserved To EaglesGroup

EndsWith( ) Equals( ) Insert( ) LastIndexOf( )

PadLeft( )

Indicates whether the specified string matches the end of this string. Determines if two strings have the same value. Returns a new string with the specified string inserted. Reports the index of the last occurrence of a specified character or string within the string. Right-aligns the characters in the string, padding to the left with spaces or a specified character.

PadRight( )

Remove( ) Split( ) StartsWith( ) Substring( ) ToCharArray( ) ToLower( ) ToUpper( )

Left-aligns the characters in the string, padding to the right with spaces or a specified character. Deletes the specified number of characters. Returns the substrings delimited by the specified characters in a string array. Indicates if the string starts with the specified characters. Retrieves a substring. Copies the characters from the string to a character array. Returns a copy of the string in lowercase. Returns a copy of the string in uppercase. Removes all occurrences of a set of specified characters from beginning and end of the string.

Trim( )

TrimEnd( ) TrimStart( )

Behaves like Trim ( ), but only at the end. Behaves like Trim ( ), but only at the start.

All Rights Reserved To EaglesGroup

535

Example 14.1 illustrates the use of some of these methods, including Compare ( ), Concat ( ) (and the overloaded + operator), Copy ( ) (and the = operator), Insert ( ), EndsWith ( ), and IndexOf ( ).

Example 14-1 Working with strings

Example Try it out Eagles WorkingStrings Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles WorkingStrings in the directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using Working with strings 2. And enter the following code in the program.cs body inside the main : static void Main(string[] args) { // create some strings to work with string eagles1 = "abcd"; string eagles2 = "ABCD"; string eagles3 = @"EaglesGroup Application Software's, Inc. provides custom .NET development,Training, Siddhu"; int result; // hold the results of comparisons // compare two strings, case sensitive result = string.Compare(eagles1, eagles2); Console.WriteLine("compare eagles1: {0}, eagles2: {1}, result: {2}\n", eagles1, eagles2, result); // overloaded compare, takes boolean "ignore case" //(true = ignore case) result = string.Compare(eagles1, eagles2, true); Console.WriteLine("compare insensitive\n"); Console.WriteLine("String4: {0}, eagles2: {1}, result: {2}\n", eagles1, eagles2, result); // concatenation method string string6 = string.Concat(eagles1, eagles2); Console.WriteLine( "String6 concatenated from eagles1 and eagles2: {0}", string6);

536

All Rights Reserved To EaglesGroup

// use the overloaded operator string string7 = eagles1 + eagles2; Console.WriteLine( "String7 concatenated from eagles1 + eagles2: {0}", string7); // the string copy method string string8 = string.Copy(string7); Console.WriteLine( "String8 copied from string7: {0}", string8); // use the overloaded operator string string9 = string8; Console.WriteLine("string9 = string8: {0}", string9); // three ways to compare. Console.WriteLine( "\nDoes string9.Equals(string8)?: {0}", string9.Equals(string8)); Console.WriteLine( "Does Equals(string9,string8)?: {0}", string.Equals(string9,string8)); Console.WriteLine( "Does string9==string8?: {0}", string9 == string8); // Two useful properties: the index and the length Console.WriteLine( "\nString string9 is {0} characters long. ", string9.Length); Console.WriteLine( "The 5th character is {1}\n", string9.Length, string9[4]); // test whether a string ends with a set of characters

All Rights Reserved To EaglesGroup

537

Console.WriteLine("eagles3:{0}\nEnds with Training?: {1}\n", eagles3, eagles3.EndsWith("Training")); Console.WriteLine( "Ends with Siddhu?: {0}", eagles3.EndsWith("Siddhu")); // return the index of the substring Console.WriteLine( "\nThe first occurrence of Training "); Console.WriteLine ("in eagles3 is {0}\n", eagles3.IndexOf("Training")); // insert the word excellent before "training" string string10 = eagles3.Insert(101, "excellent "); Console.WriteLine("string10: {0}\n",string10); // you can combine the two as follows: string string11 = eagles3.Insert(eagles3.IndexOf("Training"), "excellent "); Console.WriteLine("string11: {0}\n",string11); }

538

All Rights Reserved To EaglesGroup

3. Now run the console application and you should have the result like this:

Now lets see how the above program works string eagles1 = "abcd"; string eagles2 = "ABCD"; string eagles3 = @"EaglesGroup Application Software's, Inc. provides custom .NET development,Training, Siddhu";

The first two are string literals, and the third is a verbatim string literal. We begin by comparing eagles1 to eagles2. The Compare ( ) method is a public static method of string, and it is overloaded. The first overloaded version takes two strings and compares them: // compare two strings, case sensitive result = string.Compare(eagles1, eagles2); Console.WriteLine("compare eagles1: {0}, eagles2: {1}, result: {2}\n", eagles1, eagles2, result);

All Rights Reserved To EaglesGroup

539

This is a case-sensitive comparison and returns different values, depending on the results of the comparison: A negative integer, if the first string is less than the second string 0, if the strings are equal A positive integer, if the first string is greater than the second string In this case, the output properly indicates that eagles1 is "less than" eagles2. In Unicode (as in ASCII), a lowercase letter has a smaller value than an uppercase letter: compare eagles1: abcd, eagles2: ABCD, result: -1

The second comparison uses an overloaded version of Compare ( ) that takes a third, Boolean parameter, whose value determines whether case should be ignored in the comparison. If the value of this "ignore case" parameter is true, the comparison is made without regard to case, as in the following: result = string.Compare(eagles1,eagles2, true); Console.WriteLine("compare insensitive\n"); Console.WriteLine("eagles4: {0}, eagles2: {1}, result: {2}\n", eagles1, eagles2, result);

DENOTE: The result is written with two WriteLine ( ) statements to keep the lines short enough to print properly in this book. This time the case is ignored and the result is 0, indicating that the two strings are identical (without regard to case): compare insensitive string4: abcd, eagles2: ABCD, result: 0

Then concatenates some strings. There are a couple of ways to accomplish this. You can use the Concat ( ) method, which is a static public method of string:

540

All Rights Reserved To EaglesGroup

string string6 = string.Concat(eagles1,eagles2);or you can simply use the overloaded concatenation (+) operator: string string7 = eagles1 + eagles2;

In both cases, the output reflects that the concatenation was successful: string6 concatenated from eagles1 and eagles2: abcdABCD string7 concatenated from eagles1 + eagles2: abcdABCD Similarly, creating a new copy of a string can be accomplished in two ways. First, you can use the static Copy( ) method string string8 = string.Copy(string7);

Otherwise, for convenience, you might instead use the overloaded assignment operator (=), which will implicitly make a copy: string string9 = string8;

Once again, the output reflects that each method has worked: string8 copied from string7: abcdABCD string9 = string8: abcdABCD The .NET String class provides three ways to test for the equality of two strings. First, you can use the overloaded Equals ( ) method and ask string9 directly whether string8 is of equal value: Console.WriteLine("\nDoes string9.Equals(string8)?: {0}", string9.Equals(string8));

All Rights Reserved To EaglesGroup

541

A second technique is to pass both strings to String's static method Equals( ): Console.WriteLine("Does Equals(s9,s8)?: {0}", string.Equals(s9,s8));

A final method is to use the overloaded equality operator (==) of String: Console.WriteLine("Does string9==string8?: {0}", string9 == string8);

In each of these cases, the returned result is a Boolean value, as shown in the output: Does string9.Equals(string8)?: True Does Equals(string9,string8)?: True Does string9==string8?: True

The equality operator is the most natural when you have two string objects. However, some languages, such as VB.NET, do not support operator overloading, so be sure to override the Equals ( ) instance method as well. The next several lines in program use the index operator ([]) to find a particular character within a string, and use the Length property to return the length of the entire string: Console.WriteLine("\nString string9 is {0} characters long., string9.Length); Console.WriteLine("The 5th character is {1}\n", string9.Length, string9[4]); And you should have the output as follows: String s9 is 8 characters long. The 5th character is A

542

All Rights Reserved To EaglesGroup

The EndsWith ( ) method asks a string whether a substring is found at the end of the string. Thus, you might first ask eagles3 if it ends with Training (which it does not) and then if it ends with Siddhu (which it does): // test whether a string ends with a set of characters Console.WriteLine("eagles3:{0}\nEnds with Training?: {1}\n", eagles3, eagles3.EndsWith("Training") ); Console.WriteLine("Ends with Siddhu?: {0}", eagles3.EndsWith("Siddhu"));

And you should have the output reflects that the first test fails and the second succeeds: eagles3: @"EaglesGroup Application Software's, Inc. provides custom .NET development,Training, Siddhu"; Ends with Training?: False Ends with Siddhu?: True

The IndexOf ( ) method locates a substring within our string, and the Insert ( ) method inserts a new substring into a copy of the original string. The following code locates the first occurrence of Training in eagles3: Console.WriteLine("\nThe first occurrence of Training "); Console.WriteLine ("in eagles3 is {0}\n", eagles3.IndexOf("Training"));

The output indicates that the offset is 101: The first occurrence of Training in string3 is 101

All Rights Reserved To EaglesGroup

543

You can then use that value to insert the word excellent, followed by a space, into that string. Actually, the insertion is into a copy of the string returned by the Insert ( ) method and assigned to string10: string string10 = string3.Insert(101,"excellent"); Console.WriteLine("string10: {0}\n",string10); Here's the output: eagles3 = @"EaglesGroup Application Software's, Inc. provides custom .NET development,Training, Siddhu";

Finally, you can combine these operations to make a more efficient insertion statement: string string11 = string3.Insert(string3.IndexOf("Training"),"excellent "); Console.WriteLine("string11: {0}\n",string11); with the identical output: string11: EaglesGroup Application Softwares, Inc. provides custom .NET development, on-site excellent Training, Siddhu;

544

All Rights Reserved To EaglesGroup

14.2.4 Finding Substrings


The String type provides an overloaded Substring ( ) method for extracting substrings from within strings. Both versions take an index indicating where to begin the extraction, and one of the two versions takes a second index to indicate where to end the search. The Substring( ) method is illustrated in Example 14-2.

Example 14-2.Using the Substring ( ) method

Example Try it out Eagles Substring Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles Substring in the directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using Substring 2. And add the following code in the body of the program.cs and the code as follows: static void Main(string[] args) {// create some strings to work with string eagles1 = "One Two Three Four"; int ix; // get the index of the last space ix=eagles1.LastIndexOf(" "); // get the last word. string string2 = eagles1.Substring(ix + 1); // set eagles1 to the substring starting at 0 // and ending at ix (the start of the last word // thus eagles1 has one two three eagles1 = eagles1.Substring(0,ix); // find the last space in eagles1 (after two) ix = eagles1.LastIndexOf(" "); // set string3 to the substring starting at // ix, the space after "two" plus one more // thus string3 = "three" string string3 = eagles1.Substring(ix + 1);

All Rights Reserved To EaglesGroup

545

// reset string1 to the substring starting at 0 // and ending at ix, thus the string "one two" eagles1 = eagles1.Substring(0,ix); // reset ix to the space between // "one" and "two" ix = eagles1.LastIndexOf(" "); // set string4 to the substring starting one // space after ix, thus the substring "two" string string4 = eagles1.Substring(ix + 1); // reset string1 to the substring starting at 0 // and ending at ix, thus "one" eagles1 = eagles1.Substring(0,ix); // set ix to the last space, but there is // none so ix now = -1 ix = eagles1.LastIndexOf(" "); // set string5 to the substring at one past // the last space. there was no last space // so this sets string5 to the substring starting // at zero string string5 = eagles1.Substring(ix + 1); Console.WriteLine("string2: {0}\nstring3: {1}", string2, string3); Console.WriteLine("string4: {0}\nstring5: {1}\n", string4, string5); Console.WriteLine ("eagles1: {0}\n",eagles1); } }

546

All Rights Reserved To EaglesGroup

3. Now run the application and you should have the result like this:

Now lets see how the above code works: Example 14-2 is not an elegant solution to the problem of extracting words from a string, but it is a good first approximation, and it illustrates a useful technique. The example begins by creating a string, eagles1: string eagles1 = "One Two Three Four";

Then ix is assigned the value of the last space in the string: ix=eagles1.LastIndexOf(" ");

Then the substring that begins one space later is assigned to the new string, string2: string string2 = eagles1.Substring(ix+1);

This extracts from x1+1 to the end of the line, assigning to string2 the value Four.

All Rights Reserved To EaglesGroup

547

The next step is to remove the word Four from eagles1. You can do this by assigning to eagles1 the substring of eagles1, which begins at 0 and ends at ix: eagles1 = eagles1.Substring(0,ix);

Reassign ix to the last (remaining) space, which points you to the beginning of the word Three, which we then extract into string string3. Continue like this until string4 and string5 are populated. Finally, print the results: string2: Four string3: Three string4: Two string5: One eagles1: One This isn't elegant, but it works and it illustrates the use of Substring. This is not unlike using pointer arithmetic in C++, but without the pointers and unsafe code.

14.2.5 Splitting Strings


A more effective solution to the problem illustrated in Example 14-2 is to use the Split ( ) method of String, whose job is to parse a string into substrings. To use Split ( ), pass in an array of delimiters (characters that will indicate a split in the words), and the method returns an array of substrings. Example 14-3 illustrates.

Example 14-3.Using the Split ( ) method

Example Try it out Eagles UsingSplit Step by Step Example: Using Version 2005

548

All Rights Reserved To EaglesGroup

1. Create a new console application named it as Eagles UsingSplit in the directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using UsingSplit 2. Now add the following code to the program.cs

static void Main(string[] args) { // create some strings to work with string eagles1 = "One,Two,Three EaglesGroup Application Software's, Inc."; // constants for the space and comma characters const char Space = ' '; const char Comma = ','; // array of delimiters to split the sentence with char[] delimiters = new char[] { Space, Comma }; string output = ""; int ctr = 1; // split the string and then iterate over the // resulting array of strings foreach (string subString in eagles1.Split(delimiters)) { output += ctr++; output += ": "; output += subString; output += "\n"; } Console.WriteLine(output); } }

All Rights Reserved To EaglesGroup

549

3. Now run the application and you should see the output like this:

Now lets see how the above program works: You start by creating a string to parse: string eagles1 = "One,Two,Three EaglesGroup Application Software's, Inc.";

The delimiters are set to the space and comma characters. You then call Split ( ) on this string, and pass the results to the foreach loop: foreach (string subString in eagles1.Split(delimiters))

Start by initializing output to an empty string and then build up the output string in four steps. Concatenate the value of ctr. Next add the colon, then the substring returned by split, then the newline. With each concatenation, a new copy of the string is made, and all four steps are repeated for each substring found by Split ( ). This repeated copying of string is terribly inefficient.

550

All Rights Reserved To EaglesGroup

The problem is that the string type is not designed for this kind of operation. What you want is to create a new string by appending a formatted string each time through the loop. The class you need is StringBuilder.

14.2.6 Manipulating Dynamic Strings


The System.Text.StringBuilder class is used for creating and modifying strings. Semantically, it is the encapsulation of a constructor for a String. The important members of StringBuilder are summarized in Table 14-2. Table 14-2.StringBuilder methods Method
Capacity

Explanation

Chars

Retrieves or assigns the number of characters the StringBuilder is capable of holding. The indexer.

Length MaxCapacity Append( )

AppendFormat( )

Retrieves or assigns the length of the StringBuilder. Retrieves the maximum capacity of the StringBuilder. Overloaded public method that appends a typed object to the end of the current StringBuilder. Overloaded public method that replaces format specifiers with the formatted value of an object.

EnsureCapacity( )

Insert( )

Ensures the current StringBuilder has a capacity at least as large as the specified value. Overloaded public method that inserts an object at the specified position.

Remove( )

Removes the specified characters.

All Rights Reserved To EaglesGroup

551

Replace( )

Overloaded public method that replaces all instances of specified characters with new characters.

Unlike String, StringBuilder is mutable; when you modify a StringBuilder, you modify the actual string, not a copy. Example 14-4 replaces the String object in Example 14-3 with a StringBuilder object.

Example 14-4.Using a StringBuilder

Example Try it out Eagles StringBuilder Step by Step Example: Using Version 2005
1. Create a new console application and name it as Eagles StringBuilder in the directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using StringBuilder

552

All Rights Reserved To EaglesGroup

2. Now enter the following code into the program.cs as follows:

static void Main(string[] args) { // create some strings to work with string eagles1 = "One,Two,Three EaglesGroup Application Software's, Inc."; // constants for the space and comma characters const char Space = ' '; const char Comma = ','; // array of delimiters to split the sentence with char[] delimiters = new char[] { Space, Comma }; // use a StringBuilder class to build the // output string StringBuilder output = new StringBuilder( ); int ctr = 1; // split the string and then iterate over the // resulting array of strings foreach (string subString in eagles1.Split(delimiters)) { // AppendFormat appends a formatted string output.AppendFormat("{0}: {1}\n",ctr++,subString); } Console.WriteLine(output); } }

All Rights Reserved To EaglesGroup

553

3. Now run the console application and you will have a output like this:

The above code works exactly. Only the last part of the program is modified. Rather than using the concatenation operator to modify the string, use the AppendFormat ( ) method of StringBuilder to append new, formatted strings as you create them. This is much easier and far more efficient. The output is identical:

DENOTE: Because you passed in delimiters of both comma and space, the space after the comma between "Associates" and "Inc." is returned as a word, numbered 6 as shown. That is not what you want. To eliminate this you need to tell split to match a comma (as between One, Two, and Three), or a space (as between Liberty and Associates), or a comma followed by a space. It is that last bit that is tricky and requires that you use a regular expression.

554

All Rights Reserved To EaglesGroup

14.3.1 Regular Expressions


Regular expressions are a powerful language for describing and manipulating text. A regular expression is applied to a string that is, to a set of characters. Often that string is an entire text document. The result of applying a regular expression to a string is either to return a substring, or to return a new string representing a modification of some part of the original string. Remember that strings are immutable and so cannot be changed by the regular expression. By applying a properly constructed regular expression to the following string: One,Two,Three EaglesGroup Application Softwares, Inc.

As, you can return any or all of its substrings (e.g., Liberty or One), or modified versions of its substrings (e.g., EAGleSgRouP or OnE). What the regular expression does is determined by the syntax of the regular expression itself. A regular expression consists of two types of characters: literals and metacharacters. A literal is a character you wish to match in the target string. A metacharacter is a special symbol that acts as a command to the regular expression parser. The parser is the engine responsible for understanding the regular expression. For example, if you create a regular expression: ^ (From|To|Subject|Date):

This will match any substring with the letters "From," "To," "Subject," or "Date," so long as those letters start a new line (^) and end with a colon (:). The caret (^) in this case indicates to the regular expression parser that the string you're searching for must begin a new line. The letters "From" and "To" are literals, and the metacharacters left and right parentheses ( (, ) ) and vertical bar (|) are all used to group sets of literals and indicate that any of the choices should match. (Note that ^ is a
metacharacter as well, used to indicate the start of the line.)

All Rights Reserved To EaglesGroup

555

Thus you would read this line: ^ (From|To|Subject|Date):

As follows: "Match any string that begins a new line followed by any of the four literal strings From, To, Subject, or Date followed by a colon."

14.3.2 Using Regular Expressions: RegEx


The .NET Framework provides an object-oriented approach to regular expression matching and replacement. DENOTE: C#'s regular expressions are based on Perl5 regexp, including lazy quantifiers (??, *?, +?, {n, m}?), positive and negative look ahead, and conditional evaluation. The Base Class Library namespace System.Text.RegularExpressions is the home to all the .NET Framework objects associated with regular expressions. The central class for regular expression support is Regex, which represents an immutable, compiled regular expression. Although instances of Regex can be created, the class also provides a number of useful static methods. The use of Regex is illustrated in Example 14-5.

Example 14-5.Using the Regex class for regular expressions

Example Try it out Eagles RegexClass Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles RegexClass in the directory as follows C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Uisng RegexClass 2. Now enter the following code in the System. Namespace as follows: using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions;

556

All Rights Reserved To EaglesGroup

3. Now enter the following code into the program.cs body and the code as follows: static void Main(string[] args) { string eagles1 = "One,Two,Three EaglesGroup Application Software's, Inc."; Regex theRegex = new Regex(" |, |,"); StringBuilder siddhuBuilder = new StringBuilder( ); int id = 1; foreach (string subString in theRegex.Split(eagles1)) { siddhuBuilder.AppendFormat( "{0}: {1}\n", id++, subString); } Console.WriteLine("{0}", siddhuBuilder); } }

4. Now run the application and you should have the output like this:

All Rights Reserved To EaglesGroup

557

Now lets see how the above program works Example 14-5 begins by creating a string, eagles1, that is identical to the string used in Example 14-4. string eagles1 = "One,Two,Three EaglesGroup Application Software's, Inc.";

It also creates a regular expression, which will be used to search that string: Regex theRegex = new Regex(" |,|, ");

One of the overloaded constructors for Regex takes a regular expression string as its parameter. This is a bit confusing. In the context of a C# program, which is the regular expression? Is it the text passed in to the constructor, or the Regex object itself? It is true that the text string passed to the constructor is a regular expression in the traditional sense of the term. From an object-oriented C# point of view, however, the argument to the constructor is just a string of characters; it is theRegex that is the regular expression object. The rest of the program proceeds like the earlier Example 14-4, except that rather than calling Split ( ) on string eagles1, the Split ( ) method of Regex is called. Regex.Split ( ) acts in much the same way as String.Split ( ), returning an array of strings as a result of matching the regular expression pattern within theRegex.
Regex.Split ( )

is overloaded. The simplest version is called on an instance of Regex, as shown in Example 14-5. There is also a static version of this method, which takes a string to search and the pattern to search with, as illustrated in Example 14-6.

558

All Rights Reserved To EaglesGroup

Example 14-6.Using static Regex.Split ( ):

Example Try it out Eagles RegexSplit Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles RegexSplit in the Directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Exmaple Using RegexSplit 2. Now enter the following code in the System. Namespace as follows: using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; 3. After enter the code for the system namespace enter the following code in the body of the program.cs as follows: static void Main(string[] args) { string eagles1 = "One,Two,Three EaglesGroup Application Software's, Inc."; StringBuilder siddhuBuilder = new StringBuilder( ); int id = 1; foreach (string subStr in Regex.Split(eagles1," |, |,")) { siddhuBuilder.AppendFormat("{0}: {1}\n", id++, subStr); } Console.WriteLine("{0}", siddhuBuilder); }

All Rights Reserved To EaglesGroup

559

4. Now run the program and you should have a output like this:

The way the above program works is Example 14.6 is identical to Example 14-5, except that the latter example does not instantiate an object of type Regex. Instead, Example 146 uses the static version of Split ( ), which takes two arguments: a string to search for and a regular expression string that represents the pattern to match. The instance method of Split ( ) is also overloaded with versions that limit the number of times the split will occur and also determine the position within the target string where the search will begin.

14.3.3 Using Regex Match Collections


Two additional classes in the .NET Regular Expressions namespace allow you to search a string repeatedly, and to return the results in a collection. The collection returned is of type MatchCollection, which consists of zero or more Match objects. Two important properties of a Match object are its length and its value, each of which can be read as illustrated in Example 14-7.

560

All Rights Reserved To EaglesGroup

Example 14-7.Using MatchCollection and Match

Example Try it out Eagles MatchCollection Step by Step Example: Using Version 2005
1. Create a new Console application and name it as Eagles MatchCollection in the directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using MatchCollection 2. Enter the following code in the namespace as follows: using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; 3. Now enter the following code in the program .cs and the code as follows: static void Main(string[] args) { string string1 = Welcome Siddhu!"; // find any nonwhitespace followed by whitespace Regex theReg = new Regex(@"(\S+)\s"); // get the collection of matches MatchCollection theMatches = theReg.Matches(string1); // iterate through the collection foreach (Match theMatch in theMatches) { Console.WriteLine( "theMatch.Length: {0}", theMatch.Length); if (theMatch.Length != 0) { Console.WriteLine("theMatch: {0}", theMatch.ToString()); } }

All Rights Reserved To EaglesGroup

561

4. Now run the program and you should have the output like this:

Now lets see how the above program works Example 14.7 creates a simple string to search: string string1 = "Welcome Siddhu!"; And a trivial regular expression to search it: Regex theReg = new Regex(@"(\S+)\s");

The string \S finds no white space, and the plus sign indicates one or more. The string \s (note lowercase) indicates white space. Thus, together, this string looks for any no white space characters followed by white space.

DENOTE: Remember that at (@) symbol before the string creates a verbatim string, which avoids the necessity of escaping the backslash (\) character.

The output shows that the first four words were found. The final word was not found because it is not followed by a space. If you insert a space after the word string and before the closing quotation marks, this program will find that word as well.

562

All Rights Reserved To EaglesGroup

The length property is the length of the captured substring, and is discussed in Section 14.3.6, later in this chapter.

14.3.4 Using Regex Groups


It is often convenient to group sub expression matches together so that you can parse out pieces of the matching string. For example, you might want to match on IP addresses and group all IP addresses found anywhere within the string.

DENOTE: IP addresses are used to locate computers on a network, and typically have the form x.x.x.x, where x is generally any digit between 0 and 255 (such as 192.168.0.1). The Group class allows you to create groups of matches based on regular expression syntax, and represents the results from a single grouping expression. A grouping expression names a group and provides a regular expression; any substring matching the regular expression will be added to the group. For example, to create an ip group you might write: @"(? <Ip> (\d|\.)+)\s"

The Match class derives from Group, and has a collection called "Groups" that contains all the groups your Match finds. Creation and use of the Groups collection and Group classes is illustrated in Example 14-8.

All Rights Reserved To EaglesGroup

563

Example 14-8.Using the Group class

Example Try it out Eagles Group Class Step by Step Example: Using Version 2005
1. Create a new Console Application name it as Eagles Group Class in the directory D:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using Group Class 2. Now enter the following in the System. Namespace. using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions;

564

All Rights Reserved To EaglesGroup

3. Enter the following code into the program.cs body as follows: static void Main(string[] args) { string string1 = "05:11:25 127.0.0.0 eaglesgroup.com"; // group time = one or more digits or colons followed by space Regex theReg = new Regex(@"(?<time>(\d|\:)+)\s" + // ip address = one or more digits or dots followed by space @"(?<ip>(\d|\.)+)\s" + // site = one or more characters @"(?<site>\S+)"); // get the collection of matches MatchCollection theMatches = theReg.Matches(string1); // iterate through the collection foreach (Match theMatch in theMatches) { if (theMatch.Length != 0) { Console.WriteLine("\ntheMatch: {0}", theMatch.ToString()); Console.WriteLine("time: {0}", theMatch.Groups["time"]); Console.WriteLine("ip: {0}", theMatch.Groups["ip"]); Console.WriteLine("site: {0}", theMatch.Groups["site"]); } }

All Rights Reserved To EaglesGroup

565

4. Now run the application and you should have a output like this:

Now lets see how the above program works: Again, Example 14-8 begins by creating a string to search: string string1 = "05:11:25 127.0.0.0 eaglesgroup.com";

This string might be one of many recorded in a web server log file or produced as the result of a search of the database. In this simple example, there are three columns: one for the time of the log entry, one for an IP address, and one for the site, each separated by spaces. Of course, in an example solving a real-life problem, you might need to do more complex searches and choose to use other delimiters and more complex searches. In Example 14-8, we want to create a single Regex object to search strings of this type and break them into three groups: time, ip address, and site. The regular expression string is fairly simple, so the example is easy to understand. However, keep in mind that in a real search, you would probably only use a part of the source string rather than the entire source string, as shown here:

566

All Rights Reserved To EaglesGroup

// group time = one or more digits or colons // followed by space Regex theReg = new Regex(@"(?<time>(\d|\:)+)\s" + // ip address = one or more digits or dots // followed by space @"(?<ip>(\d|\.)+)\s" + // site = one or more characters @"(?<site>\S+)"); Let's focus on the characters that create the group:

(@"(?<time>(\d|\:)+)

The parentheses create a group. Everything between the opening parenthesis (just before the question mark) and the closing parenthesis (in this case, after the + sign) is a single unnamed group. The string ?<time> names that group time, and the group is associated with the matching text, which is the regular expression (\d|\:)+)\s". This regular expression can be interpreted as "one or more digits or colons followed by a space." Similarly, the string ?<ip> names the ip group, and ?<site> names the site group. As Example 14-7 does, Example 14-8 asks for a collection of all the matches: MatchCollection theMatches = theReg.Matches(string1);

Example 14-8 iterates through the Matches collection, finding each Match object. If the Length of the Match is greater than 0, a Match was found; it prints the entire match: Console.WriteLine("\ntheMatch: {0}", theMatch.ToString( ));

All Rights Reserved To EaglesGroup

567

It then gets the "time" group from theMatch.Groups collection and prints that value: Console.WriteLine("time: {0}", theMatch.Groups["time"]);

This produces the output: time: 05:11:25

The code then obtains ip and site groups: Console.WriteLine("ip: {0}", theMatch.Groups["ip"]); Console.WriteLine("site: {0}", theMatch.Groups["site"]);

This produces the output: ip: 127.0.0.0 site: eaglesgroup.com In Example 14-8, the Matches collection has only one Match. It is possible, however, to match more than one expression within a string. To see this, modify string1 in Example 14-8 to provide several logFile entries instead of one, as follows: string string1 = "05:11:25 127.0.0.0 eaglesgroup.com " + "05:12:28 127.0.0.0 siddhu.com " + "05:12:29 127.0.0.0 sri.com " ;

568

All Rights Reserved To EaglesGroup

In this example, theMatches contains three Match objects. Each time through the outer foreach loop we find the next Match in the collection and display its contents: foreach (Match theMatch in theMatches) For each of the Match items found, you can print out the entire match, various groups, or both.

14.3.5 Using CaptureCollection

Each time a Regex object matches a subexpression, a Capture instance is created and added to a CaptureCollection collection. Each capture object represents a single capture. Each group has its own capture collection of the matches for the subexpression associated with the group. A key property of the Capture object is its length, which is the length of the captured substring. When you ask Match for its length, it is Capture.Length that you retrieve, because Match derives from Group, which in turn derives from Capture.

DENOTE: The regular expression inheritance scheme in .NET allows Match to include in its interface the methods and properties of these parent classes. In a sense, a Group is-a capture: it is a capture that encapsulates the idea of grouping subexpressions. A Match, in turn, is-a Group: it is the encapsulation of all the groups of subexpressions making up the entire match for this regular expression.

All Rights Reserved To EaglesGroup

569

Typically, you will find only a single Capture in a CaptureCollection, but that need not be so. Consider what would happen if you were parsing a string in which the company name might occur in either of two positions. To group these together in a single match, create the? <Company> group in two places in your regular expression pattern: Regex theReg = new Regex(@"(?<time>(\d|\:)+)\s" + @"(?<company>\S+)\s" + @"(?<ip>(\d|\.)+)\s" + @"(?<company>\S+)\s");

This regular expression group captures any matching string of characters that follows time, and also any matching string of characters that follows ip. Given this regular expression, you are ready to parse the following string: string string1 = "05:11:25 127.0.0.0 eaglesgroup.com ";

The string includes names in both the positions specified. Here is the result: theMatch: 05:11:25 127.0.0.0 eaglesgroup.com time: 05:11:25 ip: 0.0.0.127 Company: EaglesGroup What happened? Why is the Company group showing EaglesGroup? Where is the first term, which also matched? The answer is that the second term overwrote the first. The group, however, has captured both. Its Captures collection can demonstrate, as illustrated in Example 14-9.

570

All Rights Reserved To EaglesGroup

Example 14-9.Examining the capture collection

Example Try it out Eagles CaptureCollection Step by Step Example: Using Version 2005
1. Create a new Console Application and name it as Eagles CaptureCollection in the directory C:\EaglesVisualCSharp\Chapter 14 Strings and Regular Expressions\Example Using CaptureCollection 2. Enter the following code in the System. Namespace using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; 3. Now enter the following code in the program.cs body as follows:

All Rights Reserved To EaglesGroup

571

static void Main(string[] args) { // the string to parse // note that names appear in both // searchable positions string string1 = "05:11:25 Siddhu 0.0.0.127 EaglesGroup "; // regular expression which groups company twice Regex theReg = new Regex(@"(?<time>(\d|\:)+)\s" + @"(?<company>\S+)\s" + @"(?<ip>(\d|\.)+)\s" + @"(?<company>\S+)\s"); // get the collection of matches MatchCollection theMatches = theReg.Matches(string1); // iterate through the collection foreach (Match theMatch in theMatches) { if (theMatch.Length != 0) { Console.WriteLine("theMatch: {0}", theMatch.ToString( )); Console.WriteLine("time: {0}", theMatch.Groups["time"]); Console.WriteLine("ip: {0}", theMatch.Groups["ip"]); Console.WriteLine("Company: {0}", theMatch.Groups["company"]); // iterate over the captures collection // in the company group within the // groups collection in the match foreach (Capture cap in theMatch.Groups["company"].Captures) { Console.WriteLine("cap: {0}",cap.ToString( )); } } } }

572

All Rights Reserved To EaglesGroup

4. Now run the program and you should have the following output like this:

The following code iterates through the Captures collection for the Company group: foreach (Capture cap in theMatch.Groups["company"].Captures)

Let's review how this line is parsed. The compiler begins by finding the collection that it will iterate over. theMatch is an object that has a collection named Groups. The Groups collection has an indexer that takes a string and returns a single Group object. Thus, the following line returns a single Group object: theMatch.Groups["company"]

The Group object has a collection named Captures. Thus, the following line returns a Captures collection for the Group stored at Groups["company"] within the theMatch object: theMatch.Groups["company"].Captures

The foreach loop iterates over the Captures collection, extracting each element in turn and assigning it to the local variable cap, which is of type Capture. You can see from the output that there are two capture elements: Siddhu and EaglesGroup. The second one overwrites the first in the group, and so the displayed value is just EaglesGroup. However, by examining the Captures collection, you can find both values that were captured.

All Rights Reserved To EaglesGroup

573

Summary
In this chapter we had look the String and Regular expression which we used in the Visual C#.NET and the topics we covered so far are as follows: Introduction to Strings and Regular Expressions Strings Creating Strings The ToString( ) Method Manipulating Strings Finding Substrings Splitting Strings Manipulating Dynamic Strings Regular Expressions Using Regular Expressions Using Regex Match Collections Using Regex Groups Using CaptureCollection

574

All Rights Reserved To EaglesGroup

Chapter 15

All Rights Reserved To EaglesGroup

575

Using Windows Form Controls


15.1 Introduction to Windows Form Controls
In this chapter, well look at working with windows forms, and use some of the many controls that ship with the .NET Framework. These controls cover a wide range of functionality, and through, and through the design capabilities of Visual Studio.NET, developing user interfaces and handling user interaction is very straightforward and fun! Presenting all of the controls in the Visual Studion.NET would be impossible within the scope of this book, and so in this chapter well look at some of the most commonly used controls, ranging from labels and textboxes to list views and status bar, and some of the important controls and some of the project controls. In recent years Visual Basic has won great acclaim for granting programmers the tools for creating highly detailed user interfaces via an intuitive from designers, along with an easy to learn programming language that together produced probably the best environment for rapid application development out there, once of the advantages offered by Rapid Application Development (RAD) tools such as Visual Basic is that is provided access to a number of prefabricated controls that could be used to quick build the user interface for an application. At the heart of the development of the most Visual Basic Windows application is the form designer. You create a user interface by dragging and dropping controls from a toolbox to you form, placing them where you want them to be when you run the program, double clicking the control adds a handler for that control. The controls provided by Microsoft along with further custom controls that could be bought at reasonable prices have supplied programmers with an unprecedented pool to reusable, thoroughly tested code that is no more than a mouse click away. Such application development is now available to C# developers through Visual Studio.NET.

576

All Rights Reserved To EaglesGroup

15.2 Working With Windows Forms (WoW)


Lets start straight away create a new Windows application called FormEagles in the C:\EaglesVisaulCSharp\Chapter15 folder. You will see the Windows Form Designer, the main surface for the design of you r user interface:

From the design view, we can drag and drop controls onto our form, adjust their size, position and a great many more properties that range from determining the text displayed on the control to specifying a data source from which to populate the control. Before we look at the controls available, lets take a look at the from itself right click on the form, select View Code from the menu that appears, and youll be taken to the code editor. Here; the top portion of the code that youll see:

All Rights Reserved To EaglesGroup

577

As you can see, there is a number of using directives at the top of the code for importing a number of namespaces that are commonly using in writing Windows applications weve highlighted the System.Windows.Forms namespace. The functionality for creating Windows application such as interface display, and user interaction is provided by the classes in this namespace. The other line highlighted above is the class definition for the Form1 class the: System.Windows.Forms.Form syntax indicates that this class derives form the Form class of the System.Windows.Forms namespace. The form that is displayed to user with all its control making up carefully crafted user interface is in fact an instance of a class that derives from System.Windows.Forms.Form (in System.Windows.Forms.Form class. Well see in a moment where the instance of the class is actually created in the code. Click on the Fom1.cs [Design] tab to return to the design view, click on the form to select it, and then set its Name property to MyForm in the Properties window. Now if you return to the code view, you will find the class has been renamed: public MyForm() However, if you attempt to run the application at this point you will receive the error the type or namespace name Form1 could not be found it seems that not allowed not all reference to the Form1 have been changed to MyForm. The culprit is found in the Main () method:

578

All Rights Reserved To EaglesGroup

static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);


Application.Run(new Form1());

} Application is a class of the System.Windows.Forms namespace, providing the functionally that takes cares of the behind the scene activities for the execution of Windows applications. Here a new instance of our Form1 class is passed to the Run () method, which starts our application and displays the form. This is code we dont have to worry about, except when we change the name of the form in the form designer in Visual Studio.NET, if you change the name of the form in the form designer, you have to manually change its name in the Run () parameter in the Main() method as well. Thus, our Main () method needs to become: static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyForm());

} Well keep reminding you of this point when we change then name of forms in our examples its easy to forget!

All Rights Reserved To EaglesGroup

579

15.3 The Toolbox


Lets have a closer look at Toolbox. If you havent already, move you mouse pointer over the toolbox on the left of the screen, and pin it to the foreground by clicking the pin at the top right of the panel that unfolds. DENOTE: If you accidentally remove the toolbox by clciking the X instead, you make it reappeard by selecting Toolbox from the View menu, or by pressing Ctrl Alt + X The toolbox contains a selection of all the controls available to you as a .NET developer. The controls available form the Windows Forms section of the Toolbox are the ones of interest to us in this chapter, and as you can see, theres quite a few of them , hence we only show some of them here!

580

All Rights Reserved To EaglesGroup

The Toolbox consists of the controls that ship with the .NET Framework you are not limited to use this selection, and if is possible to customizing the Toolbox by adding you own custom built or bought controls. Building custom controls is something well look at this in the later chapter, but for now well concentrate on a sunset of the controls that we will be looking below:Now that you Toolbox is open, double click on the Button control, and an instance will appear on you form. Drag the button to the middle of the form:

Well, weve not written Microsoft Word just yet, but its start! Double click on the Button and youll be taken back to the code editor with the following method signature provided for you: private void button1_Click(object sender, EventArgs e) { } The code is generated by Visual Studio.NET is the event handler for the Button controls click event, well take a closer look at the events look at the events available to control in a movement, but for now well just mention the Click event is the event raised when the Button is clicked with the left mouse button. Each control has a default event, and when you double click on the control in the design view of Visual Studio.NET, code will be added to your file that allows the control to subscribe to the event, and the

All Rights Reserved To EaglesGroup

581

method signature for handling the event will also be added, and you will be taken to this code. Weve see the event handler, but were is the code subscribing to the event? If you look through the file you will find a form1.designer.cs when you expand this region,

You will see the following option and just click on the Form1.Designer.cs and you will see the following

Just expand it and you will see the following code: #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(94, 111); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(107, 32); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click);

// // MyForm //

582

All Rights Reserved To EaglesGroup

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.Add (this.button1); this.Name = "MyForm"; this.Text = "Fom1"; this.ResumeLayout(false); } #endregion The InitializeComponent () method contains the code automatically generated by Visual Studio.NET. DENOTE: Be careful if you modify the code in this method, (the comment before the method advise you against it!) since it is possible to introduce errors that prevent youre form from being displayed in the designer until you have corrected the error. The highlighted lines above show the Button Controls (button1) contribution to this method including the line that subscribes the Button to Click event: this.button1.Click += new System.EventHandler(this.button1_Click); You should take a minute to look over the statements in this section. You will see exactly why it is possible to create a Windows Application without using the Visual Studio.NET. Every thing in this section could simply be entered in Notepad or a similar text editor and compiled. You will also see why that is not advisable. Keeping track of everything in here is difficult at the best of times; it is easy to introduce errors and , because you cannot se the effects f what you are doing, arranging the controls on the form to look right is a cumbersome task. This does, however, open the door for third party software producers to write their own programming environments to rival Visual Studio.NET because the compilers used to create the actual applications are included with the .NET Framework rather than being dedicated to Visual Studio.NET. Now that we know where well be doing our work, and weve had a quick peek behind the scenes, lets look at controls in general.

All Rights Reserved To EaglesGroup

583

15.4 Controls

Most controls in .NET derive form the System.Windows.Forms.Control class. This class defines the basic functionality of the control, which is why many properties and events in the controls well see are identical. Many of those classes are themselves base classes for other controls, as is the case with the Label and Textbox Base classes in the diagram below:

DENOTE: some, named custom or user controls, derive from another class: System.Windows.Forms.UserControl. This class is itself derived form the Control class and provided the functionality we need to create controls over selves. Incidentally, controls used for designing web user interface from yet another class, System.Web.UI.Control.

584

All Rights Reserved To EaglesGroup

15.5 Properties
All controls have a number of properties that are used to manipulate the behavior of the control. The base class of the most controls, System.Windows.Forms.Control, has a number of properties that other controls either inherit directly or override to provide some kind of custom behavior. The table below shows some of the most common properties of the Control class, these properties will be present in most of the controls well visit in this chapter, and they will therefore not be explained in details again, unless the behavior of the properties is change d for the control in questions. DENOTE: That this table is not meant to exhaustive; if you want to see all the properties in the class, please refer to the .NET Framework SDK Documentation

All Rights Reserved To EaglesGroup

585

Name Anchor Back Color Bottom Dock Enabled ForeColor Height Left Name Parent Right TabIndex TabStop Tag

Text Top Visible Width

Description Using this property, you can specify how the controls behave when its container is resized. See below for the detailed explanation of this property. The background color of a control By setting this property, you specify the distance from the top of the window to the bottom of the control. This is not the same as specifying the height of the control. Allows you to make a control dock to the edge of a window. See below for more detailed expatiation of this property Setting Enabled to true usually mean that the control that control can receive input from the user. Setting Enabled to false usually means that it cannot. The foreground color of the control The distance from the top to the bottom of the control. The name of the control. This name can be used to reference the control in code. The name of the control. This name can be used to reference the control in code. The parent of the control. The right edge of the control relative to the left edge of the window. The number the control has in the tab order of its container. Specifies whether the control can be accessed by the Tab key This value is usually not used by the control itself and is there for you to store information about the control on the control itself. When this property is assigned a vale through the Windows Form designer, you can only assign a string to it. Holds the text that is associated with this control The top edge of the control relative to the top of the window. Specifies whether or not the control is visible at runtime. The width of the control

586

All Rights Reserved To EaglesGroup

DENOTE: if you have experienced with Visual Basic you may notice that in .NET the Text property is used to set the text that is displayed, rather than a Caption property. You will find that all intrinsic .NET controls use the name Text to describe the main text for a control. Before .NET, Caption and Text were used interchangeable between different controls.

15.6 Anchor and Dock Properties


These two properties are especially useful when you are designing you form, ensuring that a window doesnt become a mess to look at if the user decides to resize the window is a far from trivial, and numerous lines of code have been written to achieve this. Many programs solve the problem by simply disallowing the window from being resized, which is clearly the easiest way around the problem, but not always the best. The anchor and dock properties that have been introduced within .NET let you solve this problem without witting a single line of code. The Anchor property is used to specify how the control behave when a user resize the window. You can specify if the control should resize itself, anchoring itself in proportion to its own edge, or stay the same size, anchoring its position relative to the windows edges. The dock property is used to specify that a control should dock to an edge of its container, if a user resizes the window, the control will continue to be docked to the edge of the window. If for instance, you specify that a control should dock with the button of its container, the control will resize and/or move itself to always occupy the bottom part of the window, no matter how the window is resized. See the text box example later in this chapter for the exact use of the Anchor property.

All Rights Reserved To EaglesGroup

587

15.7 Events
In the last section, we saw what events are, ands how we can use them. Here we will talk about a particular kind of events, specifically the events generated by Windows Forms controls. These events are usually associated with actions of the user. For example, when the user clicks or presses a button, that button generates an event in which it says what just happened to it. Handling the events is then means by which the programmer can provide some functionality for that button. The control class defines a number of events that are common to controls well use this chapter. The table below describes a number of those events. DENOTE: That this table is not meant to exhaustive; if you want to see all the properties in the class, please refer to the .NET Framework SDK Documentation Name Click DoubleClick Description Occurs when a control is click. In some cases, these events will also occur when a user presses Enter. Occurs when a control is double clicked. Handling the Click event on some controls, such as the Button control will mean that the DoubleClick event can be called. Occurs when a drag and drop operation in completed, in other words, when an object has been dragged over the control, and user release the mouse button Occurs when an object begging dragged enters then bounds of the control Occurs when an object being dragged leaves the bounds of the control Occurs when an object has been dragged over the control. Occurs when a key becomes pressed while the control has focus. This event always occurs before KeyPress and KeyUp. Occurs when a key becomes pressed while a control has focus. This event always occurs after KeyDown and before KeyUp. The difference between KeyDown and KeyPress is that KeyDown passes the keyboard code of the key that has been pressed, while KeyPress passes the corresponding Char value for the key

DragDrop DragEnter DrageLeave DragOver KeyDown KeyPress

588

All Rights Reserved To EaglesGroup

KeyUp GotFouces LostFocus MouseDown

MouseMove MouseUp Paint Validated

Validating

Occurs when a key is released while a control has focus. This event always occurs after KeyDown and KeyPress. Occurs when a control receives focus. Dont not use this event to perform validation of controls. Use validating instead Occurs when a control loses focus. Do not use this event to perform validation of controls. Use validating and validate instead. Occurs when the mouse pointer is over a control and a mouse button is pressed. This is not the same as a click event because MouseDown occurs as soon as then button is pressed and before it is released. Occurs continually as the mouse travels over the control. Occurs when then mouse pointers is over a control and mouse button is released. Occurs when then control is drawn This event is fired when a control with the CasueValidation property set to true is about to receive focus. It fires after the Validation event finishes and indicates that validation is complete. Fires when a control with the CauseValidation property set to true is about to recive focus. Note that the control which is to be validated is the control which is losing focus, not then one that is reciving it.

We will see many of these events in the examples in the rest of the chapter. All our example will follow the same format, where we first create the forms visual appearance, choosing and positioning controls, etc... Before we then move onto adding then event handlers this is where the main work of our examples takes places. To handle a particular event there are three basic ways of going about it. The first is to double click on the control in question, any you will be taken to the event handler for the controls default event this event different from then default one of the control, there are two possible ways of proceeding. One way is to use the Events list in the Properties windows:

All Rights Reserved To EaglesGroup

589

The grayed event is that controls default event. To add handler for a particular event, double click on that event in the Events list, and the code to subscribe the control to the event will be generated, along with the method signature to handle the event. Alternatively, you can type a name for the method to handle then particular event next to that event in the Events lists, and when you press enter the event handler will be generated with your chosen name. Another option is to add the code to subscribe to the event yourself well do this often in this and then next chapter by adding the code to the forms constructor after the InitializeComponent () call. Of Course, we still have to add the method signature to handle the event ourselves as well, and this method has then drawback that you need to know the exact method signature for the event.

590

All Rights Reserved To EaglesGroup

Note that each of these two options requires two steps subscription to the event and the correct signature for the method handler. If you double click on a control and true to handle another event by editing then method signature of the default event for the event for the event that you actually want handled, you will fail you also need to alter the event subscriptions code in InitializeComponent (), and so this cheating method is method is not really a quick way to handle particular events. We are now ready to start looking at the controls themselves, and well start with one that weve seen in then pervious chapter, the Button Control.

15.8 The Button Control


When you think of a button, you are probably thinking of a rectangle button that can be clicked to perform some task. However, the .NET Framework provides a class derived from Control System.Windows.Forms.ButtonsBase -- that implements the basic functionality needed in button controls, so any programmers can derive from this class and create his or her custom button controls. The System.Windows.Forms namespace provides us with three controls that derive from ButtonBase Button, CheckBox and RadioButton. In this section we will focus on the Button control (which is the standard, well known rectangular button), and well cover two later in this chapter. The Button control exists on just about any Windows dialog you can think of. A button is primarily used to perform three kinds of task: To close a dialog with a state (for example, OK and Cancel button) To perform an action on data entered on a dialog (for example clicking Search after entering some search criteria) To open another dialog or application (for example, Help Button) Working with the button control is very straightforward. It usually consists the control to your form and double clicking it to add the code to the click event, which will probably be enough for most applications youll work on. Lets look at some of the commonly used properties and events of the control. This will give you an idea what can be done wit it. After that, well create a small example that demonstrates some of the basic properties and events of a button.

All Rights Reserved To EaglesGroup

591

15.9 Button Properties


Well list the most commonly used properties of the Button class, even if technically they are defined in the ButtonBase base class

DENOTE: That this table is not meant to exhaustive; if you want to see all the properties in the class, please refer to the .NET Framework SDK Documentation

Name FlatStyle

Enabled

Image ImageAlign

Description The style of the button can be changed with this property. If you set the style to Popup, the button will appear flat until the user moves the mouse pointer over it. When that happen, the button pop up to its normal 3D look. Well mention this here even though it is derived from Control, because its a very important property for a button. Setting the Enabled property to false means that the button becomes grayed out and something happens when you click it. Allows you to specify an image (bitmap, icon, etc), which will be displayed on the button. With this property, you can set where the image on the button should appear.

15.10 Button Events


By far the most used event of a button is the Click event. This happens whenever a user clicks the button, by which we mean pressing the left mouse button and releasing it again while over the button. This means that if you left clicks on the button and then draw the mouse away from the button before releasing it the Click event will be not raised. Also, the Click event is raised when the button has focus and the user presses Enter. If you have a button on a form, you should always handle this event. Lets move to the example. Well create a dialog with three buttons. Two of the buttons will change then language used form English to Danish and Back (Feel Free to Use whatever language you prefer). The last button closes the dialog.

592

All Rights Reserved To EaglesGroup

Example Try it out Button Test Step by Step Example:


1. Create a new Windows Application called ButtonTest in the directory C:\EaglesVisualCSharp\Chapter15. 2. Pin the Toolbox down and double click the button control three times. Then move the buttons and resize the form as shown in the picture below.

3. Right Click a button and select Properties. Then change the name of each button as indicated in the picture above by selecting then (Name) edit filed in the Properties window and typing the relevant text 4. Change the Text property of each button the be the same as the name, but omit the btn prefix for the Text property value. 5. We want to display a flag in front of the text to make it clear what we are talking about. Select the English Button and find the Image property. Click () to the right it to bring up a dialog where you can select an image. The flag icons we want to display come with Visual Studio.NET. If you installed to the default location (on an English language installation) they should be located in C:\ Program Files \ Microsoft Visual Studio.NET \ Common7\ Graphics\icons\Flags. Select the icon flguk.ico. Repeat this process with the Danish button, selecting the flgden.ico file instead (If you want to use a different flag here, then this directory will have other flags to choose from.) 6. Youll notice at this point that the button text and icon are placed on top of each other, so we need to change the alignment of the icon. For both English and Danish buttons, change the Image Align property to Middle Left. 7. At this point you may want to adjust the width of the buttons so that the text doesnt start right where the images end. Do this by selecting each of the buttons and pulling the notch on the right handed edge of the button.

All Rights Reserved To EaglesGroup

593

8. Finally, click on the form and change the Text property to Do You Speak English? Thats it for the user interface of our dialog. You should now have something that look like this:

Now we are ready to add the event handlers to the dialog. Double click the English button. This will take you directly to the event handlers for the controls default event the Click event is the default event for the buttons and so that is the handler created.

Adding the Event handlers


Double click on the Button and add on the following code to the event handler: private void btnenglish_Click(object sender, EventArgs e) { this.Text = "Do you Speak English?"; } When Visual Studio .NET creates a method to handle such an event, the method name is concatenation of the name of the control, followed by an underscore and the name of the event that is handled. For the Click event, the first parameter, object sender, will hold the control that was clicked. In this example, this will always be the control indicated by the name of the method, but in other cases many controls may use the same method to handle an event, and in that case you can find out exactly which control is calling by checking this value. The text box example later in this chapter demonstrates how to use a single method for multiple controls. The other parameters, System.EventArgs e, hold information about what actually happened. In this case, well not need any of this information.

594

All Rights Reserved To EaglesGroup

Return to the design view and Double click the Danish Button and you will be taken to the event handler for that button. Here is the code: private void btndanish_Click(object sender, EventArgs e) { this.Text = "Taler du dansk?"; } This method is identical to the btnEnglish_Click, except that the text is in Danish. Finally, we add the event handler for the OK button in the same way as weve done twice now. The code is little different though: private void btnok_Click(object sender, EventArgs e) { Application.Exit () } With this we exit the appliation and, with it, this first example.Compile it, run it and press a few of the buttons. You will get the output simiular to this:

15. 11 The Label and LinkLabel Controls


The Label control is probably the most used control of them all. Look at any Windows applications and youll see a Label on just any dialog you can find. This Label is a simple control with one purpose only to display text on the form. The .NET Framework includes two label controls that present themselves to user in two distinct ways: Label, the standard Windows Label LinkLabel, a label similar to the standard one (and derived from it), but presents itself as on Internet link (a hyperlink)
All Rights Reserved To EaglesGroup

595

And thats it for most user of the Label control. Usually you need to add no event handling code for a standard Label, although it does support events like all controls. In the case of the LinkLabel, however, some extra code is needed if you want to allow the user to click it and take him or her to the web page show in the text. The Label control has a surprising number of properties that can be set. Most of these are derived from control, but some are new. The following table lists the most common ones. Unless stated otherwise, the properties are common to both the Label and LinkLabel controls. DENOTE: That this table is not meant to exhaustive; if you want to see all the properties in the class, please refer to the .NET Framework SDK Documentation Name Description Allows you to specify the style of the border the label. Border Style The default is no border. (LinkLabel only) the color of the LinkLabel after the DisabledLinkColor user has clicked it. Controls how the control is displayed. Setting this Flat Style property to Popup will make the control appear flat the user moves the mouse pointer over the control. At that time, the control will appear raised. This property allows you to specify a single image Image (bitmap, icon, etc...), to be displayed in the Label. (Read/Read) Where in the Label the image is shown. ImageAlign (LinkLabel only) The range in the text that should Link Area displayed as link. (LinkLabel only) It is possible for LinkLabel to Link Color contain more than one link. This property allows you to find the link you want. The control keeps track of the links displayed in the text. Not available at design time. (Link Label only) Returns whether a link has been Link Visited visited or not. Where in the control the text is shown. Text Align

596

All Rights Reserved To EaglesGroup

15.12 The TextBox Control


Text boxes should be used when you want the user to enter text that you have no knowledge of at design time (for example the name of the user). The primary function of a text box is for the user to enter text, but any characters can be entered, and it is quit possible to force the user to enter numeric values only. The .NET Framework comes with two basic controls to take text input from the user: TextBox and RichTextBox. Both controls are derived from a base class called TextBoxBase which itself is derived from Control. TextBoxesBase provides the base functionally for text manipulation in a text box, such as selecting text, cutting to and pasting from the Clipboard, and wide range of events. Well not focus so much now on what is derived from where, but instead look at the simpler of the two controls first TextBox. Well build one example that demonstrate the TextBox properties and build on that to demonstrate the RichTextBox control later.

15.13 TextBox Properties


As has been stated earlier in this chapter, there are simply too many properties for us to describe them all, and so this listing includes only the most common ones. DENOTE: That this table is not meant to exhaustive; if you want to see all the properties in the class, please refer to the .NET Framework SDK Documentation Name Cause Validation Description When a control that has this property set to true is about to recive focus, two events are fired: Validating and Validated. You can handle these events in order to Validate data in the control that is losing focus. This may cause the control never to recive focus. The related events are discussed below. A value indicating if the TextBox changes the case of the text entered. The possible values are: Lower: All text entered is converted lowercase. Normal: No changes are made to the text. Upper: All the text entered in converted to uppercase. A value that specifies the maximum length in characters of any text, entered into the TextBox. Set this value to zero if the maximum limit is limited

Character Casing

Max Length

All Rights Reserved To EaglesGroup

597

only by available memory. Multiline Indicates if this is a multiline control, which means it is able to show multiple lines of text. When Multiline property is set to true, youll usually want to set Word-Wrap to true as well. Specifies if a password character should replace the actual characters entered into a single line TextBox. If the Multiline property is true then this has no effect. A Boolean indicating if the text is read only. Specifies if a multiline TextBox should display scrollbars. The Text that is selected in the TextBox. The Number of characters selected in the text. If this value is set to be larger than the total number of characters in the text, it is reset by the control to be the total number of characters minus the value of Selection Start. The start of the selected text in a TextBox. Specifies if a multiline TextBox should automatically wrap words if a line exceeds the width of the control.

Password Char

Read Only Scroll Bars Selected Text Selection Length

Selection Start Word-Wrap

15.14 TextBox Events


Careful validation of the TextBox controls on a form can make the difference between happy users and angry ones. You have probably experienced how annoying it is when a dialog only validating its contents when you click OK. This approach to validating the data usually results in a message box being displayed informing you that the data in TextBox number three is incorrect. You can then continue to click OK until all the data is correct. Clearly this is not a good approach to validating data, so what can we do instead? The answer lies in handling the validation events a TextBox control provides. If you want to make sure that invalid characters are not entered in the text box or only values within a certain range are allowed, then you will want to indicate to the user of the control whether the value entered is valid or not. The TextBox control provides these events (all of which are inherited from Control):

598

All Rights Reserved To EaglesGroup

Name

Enter Got Focus Leave Validating Validated LostFocus

Key Down Key Press Key UP

Description These six events occur in the order they are listed here. They are known as Focus Events and are fired whenever a controls focus changes, with two exceptions. Validating and Validated are only fired if the control that receives focus has the Causes Validation property set to true. The reason why its the reciving control that fires the events is that there are times where you do not want to validate the control, even if focus changes. An example of this is if the user clicks a Help button. These three events are known as Key Events. They allow you to monitor and change what is entered into you controls. Key Down and Key Up recive the key code corresponding to the key that was pressed. This allows you to determine if special keys such as Shift or Control and F1 were pressed. Key Press, on the other hand, receives the character corresponding to a keyboard key. This means that the value for the letter a is not the same as the letter A. it is useful if you want to exclude a range of characters, for example, only allowing numeric value to be entered. Occurs when ever the text in the TextBox is changed, no matter what the change.

Text Changed

All Rights Reserved To EaglesGroup

599

Example Try it Out TextBox Test Step by Step Example:


Well create a dialog on which you can enter your name, address, occupation, and age. The purpose of this example is to give you a good grounding in manipulating properties and using events, not to create something that is incredibly useful.

Well build the user interface first.


1. Create a new Windows application called TextBoxText in the directory C:\EaglesVisualCSharp\Chapter15. 2. Create the form show below by dragging some Label, TextBox, and Button controls onto the design surface. Before you resize the two TextBox controls txtAddress and txtOutput as shown you must set their Multiline property to true. Do this by right clicking the controls and select Properties.

600

All Rights Reserved To EaglesGroup

3. Name the controls as indicated in the picture above. 4. Set the Text property of each Text Box to an empty string, which means that they will contain noting when the application is first run. 5. Set the Text property of all the other controls to the same as the name of the control, except for the first three letters. Set the Text property to Eagles TextBoxText. 6. Set the Scrollbars property to the two controls txtOutput and txtAddress to Vertical. 7. Set the ReadOnly property to the txtOutput control to true. 8. Set the CasusesValidation property to the btnHelp Button to false.

9. When you have sized the from to fit snugly around the controls, it is time to anchor the controls so they behave properly when the from is resized. Lets set the Anchor property for each type of control in one go first of all, select all the Label controls by holding down the Ctrl key while you select each Label in turn. Once youve selected them all, set the anchor property to Top, Left from the Properties window, and the Anchor property for each of the selected Label controls will be set as well. Repeat this procedure to set the Anchor property for each TextBox to Top, Left, and Right and additionally set the Anchor property txtOutpt TextBox to Top, Bottom, Left, and Right. Now set the Anchor property for both Button controls to Top, Right. The reason why txtOutput is anchored rather than docked to the bottom of the form is that we want the output text area to be resized as we pull the form. If we had docked the control to the bottom of the form, it would be moved to stay at the bottom, but it would not be resized. 10. One final thing should be set. On the form, find the Size and MinimumSize properties. Our form has little meaning if it is sized to some thing smaller that it is now, therefore you should set the MinimumSize property to the same as the Size property. The job of setting up the visual part of the form is now complete. If you run it nothing will happen when you click the button s or enter text, but if you maximize or pull in the dialog, the control behave exactly as you want them to in a proper user interface, staying put and resizing to fill the whole of the dialog.

All Rights Reserved To EaglesGroup

601

Adding the Event Handlers


Form the design view, double click the btnOk button. Repeat this which the other button. As we saw in the button example earlier in this chapter this cause event handlers for the Click event of the buttons to be created. When the OK button is clicked, we want to transfer the text in the input text boxes to the read only box. Here is the code for the two Click events handlers. private void btnOk_Click(object sender, EventArgs e) { // No Testing for invlid vlaues are made, as that should not be necessayr // EaglesSiddhu //SriJai string output; //Concatenate the text values of the four TextBoxes output = "Name:" + this.txtName.Text + "\r\n"; output = "Address:" + this.txtAddress.Text + "\r\n"; output = "Occupation:" + this.txtOccupation.Text + "r\n"; output = "Age" + this.txtAge.Text + "r\n"; // Insert the new text this.txtOutput.Text = output; }

private void btnHelp_Click(object sender, EventArgs e) { // Write a short description of each TextBox in the OutPut TextBox //EaglesSiddhu //SriJai string output; output = "Name = Your Name \r\n"; output += "Address = Your address \r\n"; output += "Occupation = Only allowed value os 'Programmer'\r\n"; output += "Age = Your Age"; //Insert the new text this.txtOutput.Text = output; }

602

All Rights Reserved To EaglesGroup

In both functions the Text property of each TextBox is used, either retervied, set in the btnOk_Click () function, or simply set as in the btnHelp_Clcik () function. We insert information the user has entered without bothering to check if it is correct. This means that we must do the checking elsewhere. In this example, there are a number of criteria that we wish to enforce in order to be correct: The name of user cannot be empty The age of the user must be number grater than or equal to zero The address of the user cannot be empty From this we can see that the check that must be done for two of the textboxes (txtName and txtAddress) is the same. We also see that we should prevent the user form entering anything invalid into the Age box, and finally, we must check if the user claims to be a programmer. To prevent the user form clicking OK before anything is entered we start by setting the OK buttons Enabled property to false this time well for it in the constructor of our form rather than from the Properties window. If you do set properties in the constructor, make sure not to set them until after the generated code in InitizliaeComponmnet () has been called. public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); this.btnOk.Enabled = false; } Now well create the handler for the two text boxes that must be checked to see if they are empty. We do this by subscribing to the Validating event of the text boxes. We inform the control that the event should be handled by a method named txtBoxEmpty_Validating (), so thats a single event handling method for two different controls. We also need a way to know the stat of our control. For this purpose, we use the Tag property of the TextBox control. If you recall the discussion of this property from earlier in this chapter, we said that only strings can be assigned to the Tag property from the Forms Designer. However, as we are setting the Tag value from code, we can of pretty much what we want with it, since the Tag property takes an object, and it is more appropriate to enter a Boolean value here.
All Rights Reserved To EaglesGroup

603

To the constructors we add the following statements:

this.btnOk.Enabled = false; // Tag Values for texting if the data is valid this.txtAddress.Tag = false; this.txtAge.Tag = false; this.txtName.Tag = false; this.txtOccupation.Tag = false; // Subscription to events this.txtName.Validating += new System.ComponentModel.CancelEventHandler(this.txtBoxEmpty_Validating); this.txtAddress.Validating += new System.ComponentModel.CancelEventHandler(this.txtBoxEmpty_Validating); Unlike the button event handler weve seen previously, the event handler for the Validating event is a specialized version of the standard handler System.EventHandler. The Reason this event needs a special handler is that should the validation fail, there must be a way to prevent any further processing. If we were to cancel further processing, that would effectively mean that it would be impossible to leave a text box until the data entered is valid. The Validating and Validated events combined with the Causes Validation property fix a nasty problem that occurred when using the GotFouces and LostFocus events to perform validation of controls. The problem occurred when the GotFouces and LostFocus events were continually fired because validation code was attempting to shift the focus between controls, which created an infinite loop. We add the following event handler as follows:

604

All Rights Reserved To EaglesGroup

private void txtBoxEmpty_Validating(object sender, System.ComponentModel.CancelEventArgs e ) { // We know the sender is a TextBox, so we cast the sender object to that TextBox tb = (TextBox) sender; TextBox tb = (TextBox)sender; // if the text is empty we set the back ground color of the // TextBox to read to indicate a problem, we use the tag value // of the control to indicate if the control contains valid // information. if (tb.TextLength == 0) { tb.BackColor = Color.Red; tb.Tag = false; // In this case we do not want to cancel further processing, // but if we had wanted to do this, we would have added this lione; // e.Cancel = true; } else { tb.BackColor = System.Drawing.SystemColors.Window; tb.Tag = true; } //Finally, we call ValidateAll which will set the value of // the OK button. ValidateAll } Because more than one text box is using this method to handle the event, we cannot be sure which is calling the function. We do know, that the effect of calling the method should be the same no matter who is calling, so we can simply cast the sender parameter to TextBox and work on that: TextBox tb = (TextBox) sender; If the length of the text in the text box is zero, we set the background color to red and the Tag to false. If it is not, we set the background color to the standard Windows color for a window.

All Rights Reserved To EaglesGroup

605

DENOTE: Should always use the color found in the System.Drawing.SystemColors enumerations when you want to set a standard color in a control. If you simply set the color to white, you application will look strange if the user has changed the default color setting. Well postpone our description of the ValidateAll () function until the end of this example. Keeping with the validating event, the next handler well add is for the Occupation text box. The procedure is exactly the same as for the two previous handlers, but the validation code is different because occupation must be Programmer or an empty string to be valid. We therefore add a new line to the constructor. This.txtOccupation.Validating += new System.ComponentModel.CancelEventHandler(this.txtOccupation_Validating); And then the handler itself:

private void txtOccupation_TextChanged(object sender, EventArgs e) { // Case the sender object to a textbox TextBox tb = (TextBox)sender; // Check if the values are correct if (tb.Text.CompareTo("Programmer") == 0 || tb.Text.Length == 0) { tb.Tag = true; tb.BackColor = System.Drawing.SystemColors.Window; } else { tb.Tag = false; tb.BackColor = Color.Red; } // Set the state of the OK button ValidateAll(); } Our second to last challenge is the age text box. We dont want the user to type anything but positive numbers (including 0 to make the test simpler). To achieve this well use the KeyPress event to remove any unwanted characters before they are shown in the text box.

606

All Rights Reserved To EaglesGroup

First, we subscribe to the KeyPress event. Select the txtAge text box and double click on the KeyPress event in the Events list of the Properties window. The KeyPress event handler is specialized as well. The System.Windows.Forms.KeyPressEventHandler is supplied because the event needs information about the key that was pressed.

Add the following code to the event handler itself: private void txtAge_keyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if ((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8) e.Handled = true; // remove the character } The ASCII values for the character between 0 and 9 lie between 48 and 57, so we make sure that the characters within this range. We make one exception though. The ASCII value 8 is the Backspace key, and for editing reasons, we allow this to slip through. Setting the Handled property of KeyPressEventArgs to true tell the control that it shouldnt do anything else with the character, and so if the Key pressed isnt a digit or a backspace, it is not shown. As it is now, the control is not marked as invalid or valid. This is because we need another check to see if anything was entered at all. This is a simple thing as weve already written the method to perform this check and we simply subscribe to the Validating event for this Age control as well by adding this line to the constructor: This.txtAge.Validating += new System.ComponentModel.CancelEventsHandler(this.txtBoxEmpty_Validating); One last case must be handled for all the controls. If the user has entered valid text in all the textboxes and then changes something, making the text invalid, the OK button remains enabled. So we have to handle one last event handler for all of the text boxes: the Change which will disable the OK button should any text filed contain invalid data. The TextChanged event is fired whenever the text in the control changes. We subscribing to the event by adding the following lines to the constructor:

All Rights Reserved To EaglesGroup

607

//TextChangd event this.txtName.TextChanged += new System.EventHandler(this.txtBox_TextChanged); this.txtAddress.TextChanged += new System.EventHandler(this.txtBox_TextChanged); this.txtAge.TextChanged += new System.EventHandler(this.txtBox_TextChanged); this.txtOccupation.TextChanged += new System.EventHandler(this.txtBox_TextChanged); The TextChanged event uses the standard event handler we know form the Click event. Finally, we add the event itself. private void txtBox_TextChanged(object sender, System.EventArgs e) { // Case the sender object to a TextBox TextBox tb = (TextBox)sender; // Test if the data is valid and set the tag and background //color accordingly if (tb.Text.Length == 0 && tb != txtOccupation) { tb.Tag = false; tb.BackColor = Color.Red; } else if (tb == txtOccupation && (tb.Text.Length != 0 && tb.Text.CompareTo("Programmer") != 0)) { // Don't set the color here, as it will color changes while the user is typing tb.Tag = false; } else { tb.Tag = false; tb.BackColor = SystemColors.Window; } //Call ValidateAll to Set the OK Button ValidateAll(); } This time we must find out exactly which control is calling the event handler, because we dont have want the background color of the Occupation text box to change to red when the user starts typing. We do this by checking the Name property of the text box that was passed to us in the sender parameter. Only one this remains: the ValidateAll method that enables or disables the OK button.

608

All Rights Reserved To EaglesGroup

private void ValidateAll() { // Set the OK Butotn to enabled if all the Tag are True this.btnOk.Enabled = ((bool)(this.txtAddress.Tag) && (bool)(this.txtAge.Tag) && (bool)(this.txtName.Tag) && (bool)(this.txtOccupation.Tag)); } The method simply sets the value of the Enabled property of the OK button to true if all of the Tag properties are true. We need to case the value of the Tag properties to a Boolean because it is stored as an object type. If you test the program now, you should see something like this:

Notice that you can click the Help button while you are in the text box with invalid data without the background color changing to red. The example weve just completed is quit long compared to the others you will see in this chapter this is because well build on this example rather than starting form scratch with example:
All Rights Reserved To EaglesGroup

609

DENOTE: Remember that you can have the example source code form the CD which is a in-built function in this Book make use of the CD to run the example thank you Enjoy Programming.

15.15 The RadioButton and CheckBox Controls


As mentioned earlier, the RadioButton and CheckBox controls share their base class with the Button control, although their appearance and use differs substantially from the button. Radio buttons traditionally, displays themselves as a label with a dot to the left of it, which can be either selected or not. You should use the radio buttons when you want to give the user a choice between several mutually exclusive options. An example of this could be, if you want to ask for the gender of the user. To group radio boxes together so that they create one logical unit you must use a GroupBox control. By first placing a GroupBox onto a form, and then placing the RadioButton controls you need within the borders of the GroupBox, the RadioButton controls will know to change their state to reflect that only one within the group box can be selected. If you do not place them within a GroupBox, only one RadioButton on the form can be selected at any given time. A CheckBox traditionally displays itself as a label with a small box with a checkmark to the left of it. You should use the check box when you want to allow the user to choose one or more option. An example could be a questionnaire asking which Operating System the user has tired (for Example, Windows 98, Windows XP, Linux, etc). Well look at the important properties and events of the two controls, starting with the RadioButton, and then move on to quick example of their use.

15.16 RadioButton Properties


As the control derives from ButtonBase and weve already seen in our example that used the button earlier, there are only a few properties to describe. As always, should you need to complete list, please refer to the .NET Framework SDK Documentation. Name Appearance Description A RadioButton can be displayed either as a label with a circular check to the left,
All Rights Reserved To EaglesGroup

610

AutoCheck

CheckAlign

Checked

middle or right of it, or as a standard button. When it is displayed as button, the control will appear pressed when selected and not pressed otherwise. When his property is true, a check mark is displayed when the user clicks the radio button. When it is false the radio button must be manually checked in code from the Click event handler. By using this property, you can change the alignment of the check box portion of radio button. Then default is ContentAlignemnt.MiddleLeft. Indicates the status of the control. It is true if the control has a check mark, and false otherwise.

You will commonly use one event when working with RadioButton controls, but as always there are many others that can be subscribe to. Well only cover two in this chapter, and the only reason the second event is mentioned is that there is subtle difference between the two that should be noted. Name CheckedChanged Click Description This event is sent when the check of the RadioButton changes. This event is sent every time the RadioButton is clicked. This is not the same as the CheckedChanged event, because clicking a RadioButton two or more times in succession only changes the Checked property once and only if it wasnt checked already. Moreover, if the AutoCheck property of the button being clicked is false, the button will not get checked at all, and again only the Click event will be sent.

15.17 CheckBox Properties


As you would imagine, the properties and events of this control are very similar to those of the RadioButton, but there are two new ones. Name Description
All Rights Reserved To EaglesGroup

611

CheckState

Unlike the RadioButton, a CheckBox can have three states: Checked Indeterminate Unchecked When the state of the check box is Indeterminate, the control check next to the label is usually grayed, indicating that the current value of the check is not valid or has no meaning or has meaning under the current circumstances. When this property if false, the user will not be able to change the CheckState state to Indeterminate. You can, however, still change the CheckState property to Indeterminate from code.

ThreeState

15.18 CheckBox Events


You will normally use only one or two events on this control. Note that, even though the CheckChanged event exists on both the RadioButton and the CheckBox controls, the effects of the events differ. Name CheckedChanged Description Occurs whenever the Checked property of the check box changes. Note that in a CheckBox where the ThreeState property is true, it is possible to click the check box without changing the Checked property. This happens when the check box changes from checked to indeterminate state. Occurs whenever the CheckedState property changes. As Checked and UnChecked are both possible values of the CheckedState property, this event will be sent whenever the Checked property changes. In addition to that, it will also be Indeterminate.

CheckedStateChanged

This concludes the events and properties of the RadioButton and CheckBox controls. But before we look at an example using these, lets take a look at the GroupBox control which we mentioned earlier.

612

All Rights Reserved To EaglesGroup

15.19 The GroupBox Control


The GroupBox control is often used to logically group a set of controls such as the RadioButton and CheckBox, and provide a caption and a frame around this set. Using the group box is as simple as dragging in onto a form, and then dragging the controls it should contain onto it but not the other way round- you cant lay a group box over some pre- existing controls. The effect of this is that the parent of the control becomes the group box, rather than the form, and it is therefore possible to have more than one RadioButton selected at any given time. Within the group box, however, only one RadioButton can be selected. The relation between parent and the child probably needs to be explained a bit more. When a control is placed on a form, the form is said to become the parent of the control, and hence the control is the child of the form. When you place a GroupBox on a form, it becomes a child of a form. As a group box can itself contain controls, it becomes the parent of these controls. The effect of this is that moving the GroupBox will move all of the controls placed on it. Another effect of placing controls on a group box is that it allows you to affect the contained controls by setting the corresponding property on the group box. For instance if you want to disable all the controls within a group box. You can simply set the Enabled property of the GroupBox to false.

We will demonstrate the use of the GroupBox in the following example.

Example Try it Out Step by Step Example:


Well modify the Eagles TextBoxText example we created earlier when we demonstrated the use of text boxes. In that example, the only possible occupation was programmer. Instead of forcing the user to type this out in full, well change this textbox to check box. To demonstrate the use of the RadioButton, well ask the user to provide one more piece of information: their gender.

Change the text box example like this:

All Rights Reserved To EaglesGroup

613

1. Remove the label named lblOccupation and the text box named txtOccupation. 2. Add a CheckBox, a GroupBox and two RadioButton controls, and name the new controls as shown in the picture below.

3. The Text Property of the RadioButton and CheckBox control should be the same as the named of the controls without the first three letters, and for the GroupBox the Text Property should be Sex. 4. Set the Checked property of the chkProgrammer check box to true.

5. Set the Checked property of either rdoMale or rdoFemale to true. Note that you cannot set both to true. If you try to, the value of the other RadioButton is automatically changed to

false. No more needs to be done on the visual part of the example, but there are number of changed in the code. First, we need to remove all the references to the text box that weve removed. Go to the code and complete the following steps.
All Rights Reserved To EaglesGroup

614

6. In the constructor to the form, remove the three lines which refer to txtOccupation. This includes subscription to the Validating and TextChanged events and the lines which sets the Tag property to false. 7. Remove the txtOccupation_Validating () method entirely.

Adding the Event Handlers


The txtBox_TextChanged methods include tests to see if the calling control was the txtOccupation TextBox. We know for sure that it will not be (since we removed it), and so we change the method by removing the else if block and modify the text as follows: private void txtBox_TextChanged(object sender, System.EventArgs e) { // Case the sender object to a TextBox TextBox tb = (TextBox)sender; // Test if the data is valid and set the tag and background //color accordingly if (tb.Text.Length == 0) { tb.Tag = false; tb.BackColor = Color.Red; } // Don't set the color here, as it will color changes while the user is typing else { tb.Tag = true; tb.BackColor = SystemColors.Window; } //Call ValidateAll to Set the OK Button ValidateAll(); } Another place in which we check the value of the text box weve removed is in the ValidateAll () method. Remove the check entirely so the code becomes: private void ValidateAll() { // Set the OK Butotn to enabled if all the Tag are True this.btnOk.Enabled = ((bool)(this.txtAddress.Tag) && (bool)(this.txtAge.Tag) && (bool)(this.txtName.Tag) );

All Rights Reserved To EaglesGroup

615

} Since we are using a check box rather than a text box we know that the user cannot enter any invalid information, as he or she will always be either a programmer or not. We also know that the user is either male or female, and become we set the property of one of the radiobutton to true. The user is prevented from choosing an invalid value. Therefore, the only thing left to do is change the help text and the output. We do this in the button event handlers: private void btnHelp_Click(object sender, EventArgs e) { // Write a short description of each TextBox in the OutPut TextBox //EaglesSiddhu //SriJai string output; output = "Name = Your Name \r\n"; output += "Address = Your address \r\n"; output += "Programmer = Check 'Programmer' if you are a programmer \r\n"; output += "Sex = Choose your sex\r\n"; output += "Age = Your Age"; //Insert the new text this.txtOutput.Text = output; } Only the help text is changed, so nothing surprising in the help method. It gets slightly more interesting in the OK method: private void btnOk_Click(object sender, EventArgs e) { // No Testing for invlid vlaues are made, as that should not be necessayr // EaglesSiddhu //SriJai string output; //Concatenate the text values of the four TextBoxes output = "Name:" + this.txtName.Text + "\r\n"; output += "Address:" + this.txtAddress.Text + "\r\n"; output += "Occupation:" + (string)(this.chkProgrammer.Checked ? " Programmer" : "Not a Programmer") + "\r\n"; output += "Sex:" + (string)(this.rdoFemale.Checked ? "Female" : "Male") + "\r\rn"; output+= "Age" + this.txtAge.Text + "r\n"; // Insert the new text this.txtOutput.Text = output;

616

All Rights Reserved To EaglesGroup

} The first of the highlighted lines is the line in which the occupation of the user is printed. We investigate the Checked property of the CheckBox, and if it is true, we write the string Programmer. If it is false, we write Not a programmer. The second line examines only the radio button rdoFemale. If the Checked property is true on that control. We know that the user claims to be female. If it is false we know that the user claims to be male. It is possioble to have radio buttons without any of them being checked when we start the program but become we checked one of the radio button at the design time, we know for sure that one of the two radio buttons will always be checked. When you run the example now, you should get a result similar to this:

All Rights Reserved To EaglesGroup

617

15.20 The RichTextBox Control


Like the normal TextBox, the RichTextBox control is derived from TextBoxBase. Because of this, it shares a number of features with the TextBox, but is much more diverse.where a TextBox is commany used with the purpose of obtaining short text strings from the user, the RichTextBox is used to display and enter formatted text (for example Bold, Underline, and italic). It does so using a standard for formatted text called Rich Text Format or RTF. In the previous example, we used a standard TextBox. We could just sa well have used a RichTextBox to do the job. In fact, as well see in the example later, you can remove the TextBox name txtOutput and insert a RichTextBox in its place with the same name, and the examample behaves excatly as it did before. Like This:

618

All Rights Reserved To EaglesGroup

15.21 RichTextBox Properties


If this kind of text box is more advanced than the one we explored in the previous section, ypud expect there are new properties that can be used, and youd be correct. Here are description of the most commonly used properties of the RichTexBox.

Name CanRedo CanUndo

RedoActiveName DetectUrls Rtf SelectedRtf

SelectedText

SelectionAlignment SelectionBullet BulletIndent SelectionColor SelectionFont

Description This property is true when the last undone operation can be reapplied using Redo. This property is true if it is possiable to undo the last action on the RichTextBox. Note that CanUndo is defined in TextBoxeBase, so it is availabel to TextBox controls as well. This property holds the name of an action that would be preformed by Redo method. Set this property to true to make the control detect URLs and format them (underline as in a browser) This corresponding to the Text property, except that this holds the text in RTF. Use this property to get or set the selected text in the control, in RTF. If you copy this text to another applications, for example, Word, it will retain all formating. Like SelectedRtf you can use this property to get or set the selected text. However, unlike the RTF version of the property, all formating is lost. This represents the alignment of the selected text. It can be Center, Left, or Right. Use this property to find out if the selection is formatted with a bullet in front of it, or use it to insert or remove bullets. Use this property to specify the number of pixels a bullet should be indented. Allows you to change the color of the text in the selection. Allow you to change the font of the text in the selection.

All Rights Reserved To EaglesGroup

619

SelectionLength SelectionType

ShowSelectionMargin

UndoActiveName SelectionProtected

Using this property, you either set or retervie the length of a selection. This property holds information about the selection. It will tell you if one or more OLE objects are selected or if only text is selected. If you set this property to trye, a margin will be shown at the left of the RichTextBox. This will make it easier for the user to select text. Gets the name of action that will be used if user chooses to undo something. You can specify that certain parts of the text should not be changed by setting this property to true.

As you can see from the listing above, most of the new properties have to do with s selection. This is because, any formating you will applying when a user is working on his or her text will propably be done on a selection made by that user. In case no selection made by user. In case no selection is made, the formating will start from the point in the text where the cursor is located, called the insertion point.

15.22 RichTextBox Events


Most of the events used by the RichTextBox are the same as those used by the TextBox. There are a few new ones of interest though:

Name LinkedClcik Protected SelectionChanged

Description This event is sent when a user clcik on a link within the text. This event is sent when a user attempts to modify text that has been marked as protected. This event is sent when the selection changes. If for some reason you dont want the user to change the selection, you can prevent the change here.

620

All Rights Reserved To EaglesGroup

Example Try it Out RichTextBox Test Step by Step Example:


Well create a very basic text editor in this example. demonstrates how to change basic formattting of text and how to load and save the text from the RichTextBox. For the sake of simplicity, the example loads from and saves to a fixed file. As always, well start by designing the form: 1. Create a new C# Windows application called EaglesRichTextBoxTest in the C:EaglesVisualCSharp\Chapter15 directory. 2. Create the form as shown in the picture below. The text box named txtSize should be TextBox control. The text box named rtfText should be a RichTextBox control.

3. Name the controls as indicated in the picture above and clear the Text Property of both rtfText and rtfSize. 4. Apart from the text boxes, set the Text of all controls to the same as the names except for the first three letters. 5. Change the Text propertyt of the txtSize text box to 10. 6. Anchor the controls as in the following table.

All Rights Reserved To EaglesGroup

621

Control name btnLoad and btnSave and others rtfText

Anchor value Top Top, Left, bottom, Right

7. Set the MinimumSize property of the form to the same as the size property.

Adding the Event Handlers


That concludes the visual part of the example and well move straight to the coe. Double click the Bold button to add the Clcik event handler to the code. Here is the code for the event : private void btnBold_Click(object sender, EventArgs e) { Font oldFont; Font newFont; //Get the font that is being used in the selected text oldFont = this.rtfText.SelectionFont; // If the font is using bold style now, we should remove the Formatting if (oldFont.Bold) newFont = new Font(oldFont, oldFont.Style & ~FontStyle.Bold); else newFont = new Font(oldFont, oldFont.Style | FontStyle.Bold); // Insert the new font and return focus to the RichTexBox this.rtfText.SelectionFont = newFont; this.rtfText.Focus(); } We start by getting the font that is being used in the current selection and assigning it to a local variable oldFont. Then we check if this selection is already bold. If it is, we want to remove the bold setting; otherwise we want to set it. We create a new font using oldFont as the prototype but add or remove the bold style as needed. Finally. We assign the new font to the selection and return focus to the RichTextBox well look more at the Font object in the later chapters.

622

All Rights Reserved To EaglesGroup

The event handlers for btnItalic and btnUnderline are the same as the one above, except we are checking the appropriate styles. Double click the two buttons Italic and Underline and add this code:

private void btnBold_Click(object sender, EventArgs e) { Font oldFont; Font newFont; //Get the font that is being used in the selected text oldFont = this.rtfText.SelectionFont; // If the font is using bold style now, we should remove the Formatting if (oldFont.Bold) newFont = new Font(oldFont, oldFont.Style & ~FontStyle. Italic); else newFont = new Font(oldFont, oldFont.Style | FontStyle. Italic); // Insert the new font and return focus to the RichTexBox this.rtfText.SelectionFont = newFont; this.rtfText.Focus(); } private void btnBold_Click(object sender, EventArgs e) { Font oldFont; Font newFont; //Get the font that is being used in the selected text oldFont = this.rtfText.SelectionFont; // If the font is using bold style now, we should remove the Formatting if (oldFont.Bold) newFont = new Font(oldFont, oldFont.Style & ~FontStyle. Underline); else newFont = new Font(oldFont, oldFont.Style | FontStyle. Underline); // Insert the new font and return focus to the RichTexBox this.rtfText.SelectionFont = newFont; this.rtfText.Focus(); } Double Clcik the last of the formatting buttons, Center, and add the following code:

All Rights Reserved To EaglesGroup

623

private void btnCenter_Click(object sender, EventArgs e) { if (this.rtfText.SelectionAlignment == HorizontalAlignment.Center) this.rtfText.SelectionAlignment = HorizontalAlignment.Left; else this.rtfText.SelectionAlignment = HorizontalAlignment.Center; this.rtfText.Focus(); } Here we must check another property, SelectionAlignment, to see if the text in the selection is already centered. HorizontalAlignment is an enumeration with values Left, Right, Center, Justify, and NotSet. In this case we simply check if Center is set, and if it is, we set the alignment to left. If isnt we set it to Center. The final formatting our little text editor will be able to perform is setting the size of text. Well add two event handlers for the text box Size, one for controlling the input, and one to detect when the user has finished entering a value. Add the following lines to the constructor of the form: public Form1() { InitializeComponent(); // Event Subscription this.txtSize.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtSize_KeyPress); this.txtSize.Validating += new System.ComponentModel.CancelEventHandler(this.txtSize_Validating); }

We saw these two event handlers in the previous examples. Both of the events use a helper method called AppllyTextSize that takes a string with the size of the text.

624

All Rights Reserved To EaglesGroup

private void txtSize_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { // Remove all characters that are not numbers, backspace and enter if ((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8 && e.KeyChar != 13) { e.Handled = true; } else if (e.KeyChar == 13) { // Apply size if the user hits enter TextBox txt = (TextBox)sender; if (txt.Text.Length > 0) ApplyTextSize(txt.Text); e.Handled = true; this.rtfText.Focus(); } } private void txtSize_Validating(object sender, System.ComponentModel.CancelEventArgs e) { TextBox txt = (TextBox)sender; ApplyTextSize(txt.Text); this.rtfText.Focus(); } private void ApplyTextSize (string textSize) { //Convert the text to a float because we'll be needing a flot shortly float newSize = Convert.ToSingle(txtSize); FontFamily currentFontFamily; Font newFont; //Create a new font of the same family but with the new size currentFontFamily = this.rtfText.SelectionFont.FontFamily; newFont = new Font (currentFontFamily, newSize ); // Set the font of the selected text to the new font this.rtfText.SelectionFont = newFont; }

All Rights Reserved To EaglesGroup

625

The work we are interested in takes place in the helper method ApplyTextSize (). It starts by converting the size from a string to a float. Weve prevented the user entering anything but when we create the new font, we need a float, so convert it to the correct type. After that, we get the family to which the font belongs and we create a new font from that family with the new size. Finally, we set the font the selection to the new font. Thats all the formatting we can do, but some is handled by the RichTextBox itself. If you try to run the example now, you will be able to set the txt to Bold, Italic, and Underline, and you can center the text. That is what you except, but there is something else that is interesting try to type a web address, for example www.eaglesgroup.com in the text. The text recognized by the control as an Internet address, is underlined, and the mouse pointer changes to a hand when you move it over the text. If that leads you to believe that you can click it and brought to the page, you are almost correct. We need to handle the event that is sent when the user clicks a link: LinkClciked. We do this by subscribing to the event in the constructor: this.rtfText.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.rtfText_LinkedClick);

We havent seen this event handler before it is used to provide the text of the link that was clicked. The handler is surprisingly simple and looks like this: private void rtfText_LinkedClick(object sender, System.Windows.Forms.LinkClickedEventArgs e) { System.Diagnostics.Process.Start(e.LinkText); } This code opens the default browser if isnt open already and navigates to the site to which the link that was clicked is pointing. This editing part of the application is now done. All that remains is to load and save the contents of the control. Well use a fixed file to do this.

626

All Rights Reserved To EaglesGroup

Double click the Load button, and add the following code:

private void btnLoad_Click(object sender, EventArgs e) { // Load the file into the RichTextBox try { rtfText.LoadFile("../..Text.rtf"); } catch (System.IO.FileNotFoundException) { MessageBox.Show("NoFiles To Load Yet", "EaglesGroup", MessageBoxButtons.OK, MessageBoxIcon.Error); } } Thats it! Nothing else had to be done. Because we are dealing with files, there is always a change that we might encounter exception, and we have to handle these. In the Load method we handle the exception that is thrown if the doesnt exit. It is equally simple to save the file. Double click the Save button and add this: private void btnSave_Click(object sender, EventArgs e) { //Save the Text try { rtfText.SaveFile("../../Text.rtf"); } catch (System.Exception eagles) { MessageBox.Show("EaglesGroup", eagles.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); } }

All Rights Reserved To EaglesGroup

627

Run the example now, format some text and click Save. Clear the text box and click Load and the text you just saved should reappear. This concludes the RichTextBox example. When you run it, you should be able to produce something like this:

15.23 The ListBox and CheckedListBox Controls


List boxes are used to show a list of strings from which one or more can be selected at a time. Just like check boxes and radio buttons, the list box provides a means of asking the user to make one or more selections. You should use a list box when at design time you dont know the actual number of values selections. You should use a list box when at design time you dont know all the possible values at design time, you should consider using a list box if there are great number of values. The ListBox class is derived from the ListControl class, which provides the basic functionality for list type controls that ship with the .NET Framework.

628

All Rights Reserved To EaglesGroup

Another kind of list box available is called CheckedListBox and is derived from the ListBox class. It provides a list just the ListBox, but in addition to the text strings it provides a check for each item in the list. Another kind of list box available is called CheckedListBox and is derived form the ListBox class. It provides just like the ListBox, but in addition to the text strings it provides a check for each item in the list.

15.24 ListBox Properties


In the list below all the properties exists in both the ListBox class and CheckedListBox class unless explicitly stated. Name BackColor ForeColor Font Items SelectedIndex Description The background color of the list box. The text color for the list box. The font to be used for displaying the text strings. The list of strings displayed in the list box. This value indicates the zero based index of the selected item in the list box. If the list box can contain multiple selections at the same time, this property holds the index of the first item in the selected list. In a list box with multiple columns, this property specifies the width of the columns. The items collection contains all of the items in the list box. You use the property of this collection to add a remove items. A list box can have more than one column. Use this property to get or set the number of columns in the list box. This property is a collection, which holds the entire zero based indices of the selected items in the list box. In a list box where only one time can be selected, this property contains the selected item if any. In a list box where more than one selection can be made, it will contain the first of the selected items.

ColownWidth

Items MultiColumn SelectedIndices SelectedItems

All Rights Reserved To EaglesGroup

629

SelectedItem SelectionMode

This property is a collection, which contains all of the items currently selected. You can choose between four different modes of selection from the ListSelectionMode enumeration in a list box: None: No items can be selected One: Only one item can be selected at any time MultiSimple: Multiple items can be selected MultiExtended: Multiple items can be selected and the user can use the Ctrl, Shift, and arrows keys to make selections.

Sorted Text

CheckedIndices

CheckedItems CheckedClick ThreeDCheckBoxes

Setting this property to true will cause the ListBox to sort the items it contains alphabetically. Weve seen Text properties on a number of controls, but this one works differently from any weve seen so far. If you set the Text property of the list box control, it searches for an item that matches the text, and selects it. If you get the Text property the value returned is the first selected item in the list. This property cannot be used if the SelectionMode is None. (CheckedListBox only) This property is a collection which contains indexes of all the items in the CheckedListBox that have a checked or indeterminate state. (CheckedListBox only) This is a collection of all the items in a CheckedListBox that are in a checked or indeterminate state. (CheckedListBox only) If this property is true, an item will change its state whenever the user clicks it. (CheckedListBox only) You can choose between CheckBoxes that are flat or normal by setting this property.

630

All Rights Reserved To EaglesGroup

15.25 ListBox Methods


In order to work efficiently with a list box, you should know a number of methods that can be called. The following table lists the most common methods. Unless indicated, the methods belong to both the ListBox and CheckedListBox classed: DENOTE: That this table is not meant to exhaustive; if you want to see all the properties in the class, please refer to the .NET Framework SDK Documentation Name ClearSelected() FindString () Description Clears all selection in the ListBox. Finds the first string in the ListBox beginning with a string you specify(for example FindString(a) will find the first string in the ListBox beginning with a. Like FindString but the entire string must be matched. Returns a value that indicates whether an item is selected. Sets or clear the selection of an item. Returns the currenly selected item. (CheckedListBox only) Returns a value indicating if an item is checked or not. (CheckedListBox only) Returns a value indicating the check state of an item. (CheckedListBox only) Sets the item specified to a checked state. (CheckedListBox only) Sets the check state of an item.

FindStringExact () GetSelected () SetSelected () ToString() GetItemChecked() GetItemCheckState () SetItemChecked () SetItemCheckState()

15.26 ListBox Events

All Rights Reserved To EaglesGroup

631

Normally the events you will want to be aware of when working with a ListBox or CheckedListBox are those that have to do with the selections that are being made by the user:

Name ItemCheck SelectedIndexChanged

Description (CheckedListBox only) Occurs when the check state of the list items changes. Occurs when the index of the selected item changes.

Example Try it Out ListBox and CheckedListBox Test Step by Step Example:
Well create a small example with both a ListBox and a CheckedListBox. The user can check items in the CheckedListBox and then click a button which will move the checked items to the normal ListBox. We create the dialog as follows: 1. Create a new Windows application called Eagles Lists in directory C:\EaglesVisualCShap\Chapter 15 2. Add a List Box, a CheckedListBox and a button to the form and change the names as shown in the picture below:

632

All Rights Reserved To EaglesGroup

All Rights Reserved To EaglesGroup

633

3. Change the Text property of the button to Move. 4. Change the CheckOnClick property of the CheckedListBox to true.

Adding the Event Handlers


Now we are ready to add some code. When the user clicks the Move button, we want to find the items that are checked, and copy those into the right handed list box. Double click the button and enter this code: private void btnMove_Click(object sender, EventArgs e) { // Check if there are any checked items in the CheckedListBox. if (this.chkListPossibleValue.CheckedItems.Count > 0) { // Clear the ListBox we'll move the selections to this.lstSelected.Items.Clear(); // Loop through the checkedItems collection of the CheckedListBox //and add the items in the Selected ListBox foreach (string item in this.chkListPossibleValue.CheckedItems) { this.lstSelected.Items.Add(item.ToString()); } // Clear all the checks in the CheckedListBox for (int i = 0; i < this.chkListPossibleValue.Items.Count; i++) this.chkListPossibleValue.SetItemChecked(i, false); } }

We start by checking the Count property of the CheckedItems collection. This will be grater than zero if any items in the collection are checked. We then clear all items in the lstSelected list box, and loop though the CheckedItems collection, adding each item to the lstSelected list box. Finally, we remove all the checks in the CheckedListBox. Now we just need something in the CheckedListBox to move. We can add the items while in design mode, by selecting the Items property in the Properties window and adding the items there:

634

All Rights Reserved To EaglesGroup

Also we can add item in code, for example in the constructor of our form:

public Form1() { InitializeComponent(); // EaglesSiddhu //Sri Jai //Add a eleventh element to the CheckedListBox this.chkListPossibleValue.Items.Add("Eleven"); } Here we add the eleventh element to the CheckedListBox, since we already have entered ten from the designer: This concludes the list box example, and if you run it now, you will get something like this:

All Rights Reserved To EaglesGroup

635

15.27 The ListView Control


The list from which you select to open the standard dialog boxes in windows is a ListView control. Everything you can do the view in the standard list view dialog (Large icons, details view, etc...), you can do with the ListView control provided with the .NET Framework.

636

All Rights Reserved To EaglesGroup

The list view is usually used to present data where the user is allowed some control over the detail and style of the presentation. It is possible to display the data contained in the columns and rows much like in a grid, as a single column or with varying icon representations. The most commonly used list view is like the one seen above which is used to navigate the folders on a computer. The ListView control is easily the most complex control were going to encounter in this chapter, and covering all of it is beyond the scope of this book. What well do is provide a solid base for you to work on by writing an example that utilizes many of the most important features of the ListView control, and by a through description of the numerous proprieties, events, and methods that can be used. Well also take a look at the ImageList control, which is used to store the images used in a ListView control.

15.28 ListView Properties


Name Activation Description By using this property, you can control how a user activates an item in the list view. The Possible values are: Standard: This setting is that which the user has chosen for his or her machine. OneClick: Clicking an item activates it.

All Rights Reserved To EaglesGroup

637

Alignment

TwoClick: Double clicking an item activates it. This property allows you to control how the items in the list view are aligned. The four possible values are: Default: If the user drags and drops an item it remains where he or she dropped it. Left: Items are aligned to the left edge of the ListView control Top: Items are aligned to the top edge of the ListView control SnapToGrid: The ListView control contains an invisible grid to which the items will snap.

AllowColumnReorder

AutoArrange

CheckBoxes

CheckedIndices CheckedItems

If you set this property to true, you allow the user to change the order of the columns in a list view. If you do so, you should be sure that the routines that fill the list view are able to insert the items properly; event the order of the columns is changed. If you set this property to true, items will automatically arrange them according to the alignment property. If the user drags an item to the center of the list view, and Alignment is Left, then the item will automatically jump to the left of the list view. This property is only meaningful if the View property is LargeIcon or Small Icon. If you set this property to true, every time in the list view will have a CheckBox displayed to the left of it. This property is only meaningful if the view property is Details or Left. These two properties give you access to a collection of indices and items respectively, containing the checked item

638

All Rights Reserved To EaglesGroup

Columns

FocusedItem FullRowSelect

GridLines

HeaderStyle

HoverSelection Items LabelEdit LabelWrap LargeImageList

in the list. A list view can contain columns. This property gives you access to the collection of columns through which you can add or remove columns. This property holds the item that has focus in the list view. If nothing is selected, it is null. When this property is true, and an item is clicked, the entire row in which the item resides will be highlighted. If it is false, only the item itself will be highlighted. Setting this property to true will cause the list view to draw grid lines between rows and columns. This property is only meaningful when the View property is Details. You can control how the column headers are displayed. There are three styles: Default: if the user drags and drops an item it remains where he or she dropped it. Left: Items are aligned to the left edge of the ListView control. Top: Items are aligned to the top edge of the ListView Control SnapToGrid: The ListView control contains an invisible grid to which the items will snap. When this property is true, the user can select an item in the list view by hovering the mouse pointer over it. The collection of items in the list view. When this property is true, the user can edit the content of the first column in a Details view. If this property is true, labels will wrap over as many lines is needed to display all the text This property holds the ImageList, which holds large images. These images can be

All Rights Reserved To EaglesGroup

639

MultiSelect Scrollable SelectedIndices SelectedItems SmallImageList Sorting

used when the View property is LargeIcon. Set this property to true to allow the user to select multiple items. Set this property to true to display scrollbars. These two properties contain the collections that hold the indices and items that are selected, respectively. When the View property is SmallICon this property holds the ImageList that contain the images used. You can allow the list view to sort the items it contains. There are three possible modes: Ascending Descending None The ImageList contains masks for images that are used as overlays on the LargeList and SmallImageList images to represent custom states. Returns the item at the top of the list view. A list view can display its items in four different modes: LargeIcon: All items are displayed with a large icon (32x32) and a label. SmallICon: All the items are displayed with a small icon (16x16) and a label List: Only one column is displayed. That column can contain an icon and label. Details: Any number of columns can be displayed. Only the first column can contains an icon.

StateImageList

TopItem View

640

All Rights Reserved To EaglesGroup

15.29 ListView Methods


For a control as complex as the list view, there are surprisingly few methods specific to it. They are described in the table below:

Name BeginUpdate ()

Clear () EndUpdate ()

Description By calling this method you tell the list view to stop drawing updates until EndUpdate () is called. This is useful when you are interesting many items at once, because it stops the view from flickering and dramatically. Clear the list view completely. All items and columns are removed. Call this method, after calling BegingUpdate. When you call this method, the list view will draw all of its items. When you call this method, the list view will scroll itself to make the item with the index you specified visible. Returns the ListViewItem at position x, y in the list view.

EnsureVisible() GetItemAt()

15.30 ListView Events


The ListView control events that you might want to handle are: Name AfterLabledEdit BeforelabeldEdit ColumnClcik ItemActivate Description This event occurs after a lable has been edited. This event occurs before a user begins editing a label. This event occurs when a column is clicked. This event occurs when an item is

All Rights Reserved To EaglesGroup

641

activated.

15.31 ListViewItem
An item in a list view is always an instance of the ListViewItem class. The ListViewItem holds information such as text and the index of the icon to display. ListViewItem objects have s SubItems property that holds instances of another class, ListViewSubItem. These sub items are displayed if the ListView control is in Details mode. Each of the sub items represents a column in the list view. The main difference of sub items and the main items is that a sub item cannot display an icon. You add ListViewItem to the ListView thorough the Items Collection and ListViewSubItems to a ListViewItem through the SubItems collection on the ListViewItem.

15.32 CoumnHeader
To make a list view display column headers you add instances of class called ColumnHeader to the Columns collection of the ListView. ColumnHeaders provide a caption for the columns that can be displayed when the ListView is in Details mode.

15.33 The ImageList Control


The ImageList control provides a collection that can be used to store images used in other controls on your form. You can store images of any size in an image list, but within each control every image must be the same size. In case of the ListView, this means that you need two ImageList controls to be able to display both large and small images. The ImageList is the first control weve visited in this chapter that does not display itself at runtime. When you drag it to a form you are developing, itll not be placed on the form itself, but below it in a tray, which contains all such components. This nice feature is provided to stop controls that are not part same way as any other control, except that you cannot move it around. You can ad images to the ImageList at both design time and run times. If you know at design time what images you want to display, you can add the images by clicking the button at the right handed side of the Images property. This will bring up a dialog on which you can browse to images you wish to insert. If you choose to add the images ar run time, you add them through the Images collection.

642

All Rights Reserved To EaglesGroup

Example Try it Out ListView Test Step by Step Example:


The best way of learning about using the ListView Control and its associated image lists is through an example. Well create a dialog with a ListView and two ImageLists. The ListView Will display files and folders on your hard drive. For example the sake of simplicity, we will not be extracting the correct icons from the files and folders, but rather use a standard folder icon for the folder and an information icon for files. By double clicking the folder you can browse into the folder tree and a back button is provided to move up the tree. Four radio buttons are used to change the mode of the list view at run time. If a file is double click well attempt to execute it.

As always well start by creating the user interface


1. Create a new Windows application called Eagles ListView in the C:\Eagles\VisualCShapr\Chapter 15 directory. 2. Add a ListView, a button, a label, and a GroupBox to the form. Then, add four radio buttons to the group box to get a form looking like the picture below.

3. Name the controls as shown in the picture above. The ListView will not display its name as in the picture above; Ive added an extra item just to show the name here you dont need to add this item.

All Rights Reserved To EaglesGroup

643

4. Change the Text property of the radiobutton and button to the same as the name, except the for the first three letters, and the Text Property of the form to ListView. 5. Clear the Text property of the label. 6. Add two ImageList control to the form by double clicking the controls icon in the Toolbox. Rename the control ilSmall, and ilLarge. 7. Change the size property of the ImageList named ilLarge to 32, 32 8. Click the button to the right of the Images property of the ilLarge image list to bring up the dialog on which you can browse to the images you want to insert. 9. Click Add and browse to the folder under Visual Studio.NET that contains the images. The files are: <Drive>: \Program Files\Microsoft Visual studio .NET\Common7\Graphics\Icons\clsdfold.icon and <Drive>:\Program Files\Microsoft Visual studio .NET\Common\Graphics\Computer\msgbox04.ico 10. Make sure the folder icon is at the top of the list 11. Repeat steps 8 and 9 with the other ImagesList, ilSmall. 12. Set the Checked property of the radio button rdoDetails to true. 13. Set the following properties on the list view:

Property MultiSelect LargeImageList SmallImageList View

Value True ilLarge ilSmall Details

Adding the Event Handlers


That concludes our user interface and we can move on to the code. First of all, well need to field to hold the folders weve browsed through in order to be able to return to them when the back button is clicked. We will store the absolute path of the folders, and so we choose a StringCollection for the job:

public partial class Form1 : Form { private System.Collections.Specialized.StringCollection folderCol;

644

All Rights Reserved To EaglesGroup

public Form1() { InitializeComponent(); } }

We didnt create any column headers in the forms designer, so well have to do that now. We create them in a method called CreateHeadersAndFileListView (): private void CreateHeadersAndFileListView() { ColumnHeader colHead; //First header colHead = new ColumnHeader(); colHead.Text = "Filename"; this.lwFilesAndFolders.Columns.Add(colHead); // Insert the header //Second Header colHead = new ColumnHeader(); colHead.Text = "Size"; this.lwFilesAndFolders.Columns.Add(colHead); //This will insert the header // Third header colHead = new ColumnHeader(); colHead.Text = "last Accesses"; this.lwFilesAndFolders.Columns.Add(colHead); // This will Insert eh header }

We start by declaring a single variable, colHead, which we will use to create the three column headers. For each of the three headers we declare the variable as new, and assign the Text to it before adding it to the Columns collection of the ListView. The final initialization of the form as it is displayed the first time is to fill the list view files and folders form your hard disk. This is done in another method:

All Rights Reserved To EaglesGroup

645

private void PaintListView(string root) { try { // EaglesGroup //Siddhu //Sri Jai // Two local varibales that is used to create the items to insert ListViewItem lvi; ListViewItem.ListViewSubItem lvsi; // If there's no root folder, we can't insert anything if (root.CompareTo("") == 0) return; // Get information about the root folder. System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(root); // Reterive the files and folders form the root folder. DirectoryInfo[] dirs = dir.GetDirectories(); // This is for Folders/ FileInfo[] files = dir.GetFiles(); // This is for to get the Files // Clear the ListView. Note that we are not calling the Clear mehod on the // Items collection rather than on the ListView itself. //The clear method method of the ListView remove everthing, including column //headers, and we only want to remove the items from the view. this.lwFilesAndFolders.Items.Clear(); //Now we set the label with the current path this.lblCurrentPath.Text = root; // Now we better Lock the ListView for updates this.lwFilesAndFolders.BeginUpdate(); // Now let us Loop through all folders in the root and insert them foreach (System.IO.DirectoryInfo di in dirs) { // Create the main ListViewItem lvi = new ListViewItem(); lvi.Text = di.Name; // FolderName lvi.ImageIndex = 0; // The folder icon had index 0 lvi.Tag = di.FullName; // Set the tag to the qualified path of the folder

646

All Rights Reserved To EaglesGroup

// Create the two ListViewSubItems. lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = ""; //Size - a folder has no size so this column is empty lvi.SubItems.Add(lvsi); // Adding the sub item to the LsitViewItem lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = di.LastAccessTime.ToString(); // Last accessed Column lvi.SubItems.Add(lvsi); //Add the sub item to the ListView this.lwFilesAndFolders.Items.Add(lvi); } // Now we Loop through all files in the root folder foreach (System.IO.FileInfo fi in files) { // Create the main ListViewItem lvi = new ListViewItem(); lvi.Text = fi.Name; // Filename lvi.ImageIndex = 1; // The icon we use to represent a folder has index 1 lvi.Tag = fi.FullName; // Set the tag to the qualified path of the file //Create the two sub items lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = fi.Length.ToString(); // length of the file lvi.SubItems.Add(lvsi); //Add to the SubItems Collection // Add the item to the Items collection of the ListView this.lwFilesAndFolders.Items.Add(lvi); } //Unlock the ListView. The item that have been inserted will now be displayed this.lwFilesAndFolders.EndUpdate(); } catch (System.Exception err) { MessageBox.Show("Error:", "EaglesGroup" + err.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); } }

All Rights Reserved To EaglesGroup

647

Before the first of the two foreach blocks we call BeginUpdate () on the ListView Control. Remember that the BeginUpdate () method on the ListView signals that ListView Control to stop updating its visible area until EndUpdate () is called. If we did not call this method, filling the list view would be slower and the list may flicker as the items are added. Just after the second foreach block we call EndUpdate (), which makes the ListView control draw the items weve filled it with. The two foreach blocks contains the code we are interested in. we start by creating a new instance of a ListViewItem and then setting the Text property to the name of the file or folder we are going to insert. The ImageIndex of the ListViewItem refers to the index of an item in one of the ImageLists. We use the Tag property to save the fully qualified path to both folders and files, for use when the user double clicks the item. Then, we create the two sub items. These are simply assigned the text to display and then added to the SubItems collection of the ListViewItem. Finally, the ListViewItem is added to the Items collection to the ListView. The ListView is smart enough to simply ignore the sub items, if the view mode is anything but Details, so we add the sub items no matter what the view mode is now. Note that there are some aspects of the code we havent discussed here - namely the lines that actually obtain information about the files: // Get information about the root folder. System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(root); // Reterive the files and folders form the root folder. DirectoryInfo[] dirs = dir.GetDirectories(); // This is for Folders/ FileInfo[] files = dir.GetFiles(); // This is for to get the Files

These lines use classes from the System.IO namespace for accessing files, so we need to add the following using directive to the top of our code: Which you need to do the following:using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; 648
All Rights Reserved To EaglesGroup

Well talk more about file access and System.IO later, but to give you an idea of whats going on, the GetDirectories () method of the DirectoryInfo object returns a collection of object that represent the folders in the directory were looking in , and the GetFiles () method return a collection of objects that represent the files in the current directory. We can loop through these collections, as we do in the code above, using the objects Name property to return the name of the relevant directory or file, and create a ListViewItem to hold this string. All that remains to be done for the list view to display the root folder is to call the functions in the constructor of the form. At the same time we instantiate the folderCol StringCollection with the root folder: public Form1() { InitializeComponent(); // init ListView and folder collection folderCol = new System.Collections.Specialized.StringCollection(); CreateHeadersAndFileListView(); PaintListView(@"C:\"); folderCol.Add(@"C:\"); } In order to allow the user to double click an item in the ListView to browse the folders, we need to subscribe to the ItemActivate event. We add the subscription to the constructor:

this.lwFilesAndFolders.ItemActivate += new System.EventHandler(this.lwFilesAndFolders_ItemActive);


All Rights Reserved To EaglesGroup

649

The corresponding event handler looks like this: private void lwFilesAndFolders_ItemActive(object sender, System.EventArgs e) { // Cast the sendere to a ListView and get the tag of the first selected item System.Windows.Forms.ListView lw = (System.Windows.Forms.ListView)sender; string filename = lw.SelectedItems[0].Tag.ToString(); if (lw.SelectedItems[0].ImageIndex != 0) { try { //Attempt to run the file System.Diagnostics.Process.Start(filename); } catch { // If the attempt fails we simply exit the method return; } } else { // Insert the items PaintListView(filename); folderCol.Add(filename); } } The tag of the selected item contains the fully qualified path to the file or folder that was double clicked. We know that the image with index 0 is a folder, so we can determine whether the item is a file or a folder by looking at the index. If it is a file we attempt to load the file. If it is a folder, we call PaintListView () with the new folder and then the new folder to the folderCol collection. Before we move on to the radio buttons well complete the browsing ability by adding the click event to the Back button. Double click the button and fill the event handle with this code:

650

All Rights Reserved To EaglesGroup

private void btnBack_Click(object sender, EventArgs e) { if (folderCol.Count > 1) { PaintListView(folderCol[folderCol.Count - 2].ToString()); folderCol.RemoveAt(folderCol.Count - 1); } else { . PaintListView(folderCol[0].ToString()); } If there is more than one item in the folderCol collection them we are not at the root of the browser, and we call PaintListView () with the path to the previous folder. The last item in the folderCol collection is the current folder, which is why we need to take the second to last item. We them remove the last item in the collection, and make the new last item the current colder. If there is only one item ion the collection we simple call PaintListView () with that item. All that remains is to able to change the view type of the list view. Double clicks each of the radio buttons and add the following code: private void rdoLargeIcon_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton ) sender ; if (rdb.Checked ) this.lwFilesAndFolders.View = View.LargeIcon ; }

private void rdoSmallIcon_CheckedChanged(object sender, EventArgs e) { RadioButton siddhu = (RadioButton)sender; if (siddhu.Checked) this.lwFilesAndFolders.View = View.List; }

All Rights Reserved To EaglesGroup

651

private void rdoList_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) this.lwFilesAndFolders.View = View.List; }

private void rdoDetails_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton ) sender ; if (rdb.Checked ) this.lwFilesAndFolders.View = View.Details ; } We check the radio button to see if it has been changes to Checked if it has we set the View property of the ListView accordingly. That concludes the ListView example. When you run it, you should see something like this:

652

All Rights Reserved To EaglesGroup

15.34 The StatusBar Control


A status bar is commonly used to provide hints for the selected item or information about an action currently being performed on the dialog. Normally the status bar is placed at the button of the screen, as it is in Microsoft Office Applications, but it can be located anywhere you like. The StatusBar control provided with the .NET Framework can be used to simply display text, or you can add panel to it and display text, or create you r own routines for drawing the content of the panel.

The above picture shows the status bar as it looks in Word. The panels in the status bar can be identified as the section that appears sunken. DENOTE: Now we will be seeing the Adding item to Toolbox For some reasons. In 2005.NET version the Status bar control is not there so we follow the steps below Enjoy Programming.

Adding Items to ToolBox


In this section we will pay attention to the old Status bars that have been retained like Toolbars and main menus in the current version of Visual Studio.NET. You may see any of these old controls on your Toolbox, but you can bring these controls and many more on the Toolbox by selecting Choose Items.. menu item from the right click menu of Toolbox and selecting the desired controls form the Choose Toolbox Items dialog box, as shown in the following picture: First Step:Right Click the Toolbox and select the Choose Items...

All Rights Reserved To EaglesGroup

653

Second Step:-

After the dialog appears select the StatusBar and the click ok to exit the dialog and see in the toolbox. Third Step:

654

All Rights Reserved To EaglesGroup

You should now see Status Bar control in the Toolbox.

15.35 StatusBar Properties


As mentioned above, you can simply assign to the Text property of the StatusBar control to display simple text to the user, but it is possible to create panels and use them to the same effect.

Name BackgroundImage Panels ShowPanles Text Dock Font

Description It is possible to assign an image to the status bar that will be drawn in the background. This is the collection of panels in the status bar. Use this collection to add and remove panels. If you want to display, this property must be set to true. When you are not using panels this property holds the text that is displayed in the status bar. Obtains a Status bars docking behavior Obtains the font for the Status bar.

15.36 StatusBar Events

All Rights Reserved To EaglesGroup

655

There are not a whole lot of nee events for the status bar, but if you are drawing a panel manually, the DrawItem event is of crucial importance. Name DrawItem Description Occurs when a panel that has the OwnerDraw style set needs to be redrawn. You must subscribe to this event if you want to draw the contents of a panel yourself. Occurs when the panel is clicked. It occurs when the value of the ImeMode property has been edited.

PanelClick ImeModeChanged

15.37 The StatusBarPanel Class


Each panel in a status bar is an instance of the StatusBarPanel Class. This Class contains all the information about the individual panels in the Panel collection. The information that can be set ranges from simple text and alignment of the text to icons to be displayed and the style of the panel. If you want to draw the panel yourself, you must set the Style property of the panel to OwnerDraw and handle the DrawItem event of the StatusBar.

Example Try it Out StatusBar Test Step by Step Example:


Well change the ListView example we created earlier to demonstrate the use of the StatusBar control. Well remove the label used to display the current folder and move the piece of information to a panel on a status bar. Well also display a second panel, which will display the current view mode of the list view. 1. Remove the label lblCurrentFolder. 2. Double click the StatusBar control in the toolbox to add it to the form (again is it neat to the bottom of the list). The new control will automatically dock with the bottom edge of the form. 3. Change the name of the StatusBar to sbInfo and clear the Text property. 4. Find the Panels property and double click the button to the right of it bring up a dialog to add panels.

656

All Rights Reserved To EaglesGroup

5. Click Add to add a panel to the collection. Set the AutoSize property to Spring. This means that the panel will share the space in the StatusBar with other panels. 6. Click Add again, and change the AutoSize property to Contents. This means that the panel will resize itself to the size of the text it contains. Set the MiniSize property to 0. 7. Click OK to close the dialog. 8. Set the ShowPanles property on the StatusBar to true.

Adding the Event Handlers


Thats it for the user interface and well move on to the code. Well start by setting the current path in the PaintListView method. Remove the line that set the text in the label and insert the following in its place: this.sbInfo.Panels [0].Text = root; The first panel has index 0, and we simply set its Text property just as we set the Text property of the label. Finally we change the four radio button CheckedChanged events to set the text of the second panel: private void rdoLargeIcon_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) { this.lwFilesAndFolders.View = View.LargeIcon; this.sbInfo.Panels[1].Text = "Large Icon"; } }

private void rdoSmallIcon_CheckedChanged(object sender, EventArgs e) { RadioButton siddhu = (RadioButton)sender; if (siddhu.Checked) { this.lwFilesAndFolders.View = View.SmallIcon; this.sbInfo.Panels[1].Text = "Small Icon"; } }

All Rights Reserved To EaglesGroup

657

private void rdoList_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) { this.lwFilesAndFolders.View = View.List; this.sbInfo.Panels[1].Text = "List"; } }

private void rdoDetails_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) { this.lwFilesAndFolders.View = View.Details; this.sbInfo.Panels[1].Text = "Details"; } } The panel text is set in exactly the same way as in PaintListView above. That concludes the StatusBar example. If you run it now, you should see something like this:

658

All Rights Reserved To EaglesGroup

15.38 The TabControl Control:


The TabControl provides an easy way of organizing into logical parts that can be accessed through tabs located at the top of the control. A TabControl contains TabPages that essentially work like a GroupBox control, in that they group controls together, although they are somewhat more complex.

All Rights Reserved To EaglesGroup

659

The above screenshot shows the Options dialog in Microsoft Word 2003 as it is typically configured. Notice the two rows of tabs at the top of the dialog. Clicking each of them will show a different selection of controls in the rest of the dialog. This is a very good example of how to use a tab control to group related information together, making it easier for the user to find the information she or her is looking for. Using the tab control is easy. You simply add the number of tabs you want to display to the controls collection of TabPage objects and then drag the controls you want to display to the respective pages.

660

All Rights Reserved To EaglesGroup

15.39 TabControl Properties


The properties of the TabControl are largely used to control the appearance of the container of TabPage objects, in particular the tab displayed. Name Alignment Appearance HotTrack Description Control where on the tab control the tabs are displayed. The default is at the top. Control how the tabs are displayed. The tabs can be displayed as normal buttons or with flat style. If this property is set to true the appearance of the tabs on the control changes as the mouse pointer passes over them. If this property is set to true, it is possible to have several rows of tabs. Returns the number of rows of tabs that is currently displayed. Returns or sets the index of the selected tab. Returns the total number of tabs. This is the collection of TabPag objects in the control. Use this collection to add and remove TabPage objects. Obtains the images to show in tabs Obtains the bounding rectangle of the tab pages. It finds whether a tabs tool tip can be displayed. Obtains the selected tab page.

Multiline RowCount SelectedIndex TabCount TabPages Image List DispalyRectange ShowToolTips SelectedTab

All Rights Reserved To EaglesGroup

661

15.40 TabControl Events


Name SelectedIndexChanged Description It occurs when the SelectedIndex property is changed.

15. 41 TabPage properties


Name ImageIndex Text ToolTipText Description Obtains the index of the image in this tab. Obtains the text to show in the tab. Obtains the tabs tool tip text.

15. 42 Working with the TabControl


The TabControl works slightly different from all other controls weve seen so far. When you drag the control on to a form, you will see a gray rectangle that doesnt look much like the control in the screenshot as shown above. You will also , see below the Properties window, two buttons that look like links with the captions Add Tab and Remove Tab. Clicking Add Tab will insert a new tab pages on the control and the control and the control will start to be recognizable. Obviously, you can remove the tab with the Remove tab link button. The above procedure is provided in order for you to get up and running quickly with the control. If, on the other hand, you want to change the behavior or style of the tabs you should use the TabPages dialog accessed through the button when you select TabPages in the Properties window. The TabPages property is also the collection used to access the individual pages on a tab control. Lets create an example to demonstrate the basics of the control. The example demonstrates how to develop controls located on different pages on the tab control.

662

All Rights Reserved To EaglesGroup

Example Try it Out TabControl Test Step by Step Example:


1. Create a new Windows Application called TabControl in the directory C:\EaglesVisualCSharp\Chapter 15. 2. Drag a TabControl control from the ToolBox to the form. 3. Click Add Tab from under the Properties window to add a tab page to control. 4. Find the Tab Pages property and click the buttons to the right of it after selecting it, to bring up the following

5. Add another tab page to control by clicking Add. 6. Change the Text property of the tab pages to Tab One and Tab two respectively, and click OK to close the dialog. 7. You can select the tab pages to work on by clicking on the tabs at the top of the control. Select the tab with the text Tab One. Drag a button on the control. Be sure to place the button within the frame of the TabControl. If you place it outside then the button will be placed on the form rather than on the control. 8. Change the name of the button to btnShowMessage and the text of the button to Show Message. 9. Click on the tab with the Text property Tab Two. Drag a TextBox control onto the TabControl surface. Name this control txtMessage and clear the Text property. 10. The two tabs should be look like these two screenshots:

All Rights Reserved To EaglesGroup

663

Adding the Event Handler


We are now ready to access the controls. If you run the code as it is you, will see the tab pages displayed properly. All that remains for us to do demonstrate the use of the tab control is to add some code such that when the user clicks the ShowMessage button on the tab, the text entered in the other tab will be displayed in a message box. First, we add a handler for the Click event by double- clicking the button on the first tab adding the following code: private void btnShowMessage_Click(object sender, EventArgs e) { // EaglesGroup //Siddhi //Jai Sri MessageBox.Show(this.txtMessage.Text); }

664

All Rights Reserved To EaglesGroup

You access a control on a tab just you would any other control on the form. We get the Text property of the TextBox and display it in a message box. Earlier in the chapter, we saw that it is only possible to have one radio button selected at a time on a form (unless you put them in group boxes). The TabPages work is precisely the same way as group boxes and it is therefore possible to have multiple sets of radio buttons on different tabs without the need to have group boxes. The last thing you must know to be able to work with a tab control is how to determine which tab is currently being displayed. There are two properties you can use for this purpose: SelectedTab and SelectedIndex. As the names imply, SelectedIndex will return the index of the tab or 1 if no tab is selected.

Summary
In this chapter we visited some of the most commonly used controls when we creating Windows Application and saw how they can be used to create a simple, yet powerful user interface. We discussed the properties and events of these controls, with examples of their use, and looked at how to add event handlers for the particular events of a control. The controls discussed in this chapter were:

Label Button RadioButton CheckBox ListBox ListView GroupBox RichTextBox StatusBar ImageList TabControl

In the next chapter, we will be looking at more complex control, and more advanced controls.

All Rights Reserved To EaglesGroup

665

Chapter 16

666

All Rights Reserved To EaglesGroup

Advanced Windows Forms Features


16.1 Advance Windows Form Features
The core of the .NET system is its base class library. This core set of libraries and components make up all the functionality shared across all development environments. In this chapter, you get more intimately involved in understanding what makes up the visual aspects of the .NET base class library, for using your own Windows Internet applications.

As a developer, you generally think of the application as the set of objects that converse and work together to implement the functionality of the system. To user, however, the application is generally perceived as the GUI elements that allow them to interact with that functionality. User is less impressed by the way data is stored on the persistent storage device. Since they are accustomed with this style of storage, the system allows them to find and sort the data. The way in which data is presented is generally the way in which the program is thought about, when it is used or reviewed. For this reason, you should strongly consider the GUI elements when you are writing applications. Too often, developers think more in terms of features and less in terms of how the pieces of an overall application flow together. By using the .NET base class library visual and other elements properly, you wont has this problem in your applications.

When we talk about Visual Elements, we are generally talking about two specific concepts elements appear directly on Windows Forms, and elements are visible to users. This combination is important because many elements in the .NET base class library are available to you as a developer to use directly on a form without being directly visible to users. Elements in the .NET base class library and its extensions break down into three general categories, which we look at in this chapter:

In the previous chapter we looked at some of the most common control used in Windows Application development. With controls such as these it is possible to create impressive dialogs, but very few full scale Windows applications have a user interface consisting solely of a single dialog. Rather, these applications use a Single Document Interface (SDI), or a Multiple Document Interface (MDI). Applications of either of these types usually make heavy use of menus and toolbars, neither of which we discussed in the previous chapter, but well make compensation for that now. We will start this chapter as we left of the previous one, by looking at controls, starting with the menu controls and then moving on to toolbars, where well see how to link buttons on toolbars to specific menu items and vice versa. Then well move on to creating SDI and MDI applications, with the focus on MDI applications, as SDI applications are basically subsets of MDI applications.

All Rights Reserved To EaglesGroup

667

So far weve only consumed controls that ship with the .NET Framework. These controls are, ad weve seen, very powerful and provide a wide range of functionality, but there are times where they are not sufficient. To overcome this, it is possible to create custom controls, and well look at how that is done towards the end of this chapter.

General Components The general components that the .NET base class library supports and that you can place directly on your forms this category, the largest by far, occupies most of this chapter. Set of user defined components The .NET base class library and C# permit you to create your own components this process. These components can be either visual elements written from scratch to perform a specific action or extensions to the existing .NET base class library components such as owner drawn components. Other components in the visual spectrum The examples are Standardized dialog boxes, Tool tips, and Printing support.

16.2 General Components


The general category of the .NET base class library consists of the standard Windows controls, wrapped up nicely in C# components. This category contains buttons, check boxes, radio buttons, list boxes, edit controls, and other simple controls that the user are accustomed to work with in the Windows Operation System. But most of the controls which belong to this category are been seen in the last chapter. Now we will move to the Menu item, and User defined Components:

16.3 Menus
How many Windows applications can you think of that do not contain a menu of some kind? The chances are that the number is very close to none. Menus are therefore likely to be important part of any applications you will write for the Windows Operating System. To assist us in creating menus for our applications, Visual Studio .NET provides us with that lets us create simple menus quickly, and more refined with a little more work.

16.4 Using the MenuStrip Control


The MenuStrip control well be using here is called MainMenu and its like the two other kinds of menus that come with Visual Studio .NET, derived from a base class called MenuStrip located in the System.Windows.Forms namespace. There is another kind of menu that well discuss briefly after the discussion of the MainMenu the ContextMenuStrip. A context menu appears when a user right clicks 668
All Rights Reserved To EaglesGroup

on an item, and will typically display information relevant to that item. Technically there is a third menu type, named MenuItem, which is also derived fro the Menu Class. A MenuItem represents the individual items displayed in a menu. In the picture below, the Type Here field represents a MenuItem. The MenuItem will be discussed in detail shortly. ContextMenuStrip and MenuItem are also derived from the base class Menu.

When you drag the MenuStrip control from the Toolbox to the design surface you will see that this control places itself both on the form itself and in the control tray, but can be edited directly on the form. To create new menu items you simply place the pointer in the box marked Type Here as shown in the following picture:

All Rights Reserved To EaglesGroup

669

Type the caption of the menu in the highlighted box, including an ampersand (&) in front of the letter you want to function as the mnemonic character for the menu item this is the character that appears underlined in the menus item and which can be selected pressing Alt and the key together.

670

All Rights Reserved To EaglesGroup

DENOTE: That it is quite possible create several menu items in the same menu with the same mnemonic character. The rule, is that a character can be used only once for each pop up menu (Rules are meant to Broken, but this rule is cannot broken as Microsoft decide to do that so on). For example in the Files pop up menu, once in the View menu etc. if you accidentally assign the same mnemonic character to multiple menu items in the same pop up menu, you ll find that only the one closest to the top of the control will respond to the character.

To create a separator in the menu, you simple type a single dash (-) as the text. DENOTE: That you cannot do this for top level menu items, only for submenus items, which we will come to very shortly.

When you click in the highlighted box, you will notice that the properties displayed in the Properties window changed. This is because the majority of the properties that can be used with menus are used with respect to the individual menu items.

16.5 The MenuStrip Control


If you select a MenuItem by clicking on it in the MainMenu control, you will see several properties that are used to control the appearance and behavior of the item. Each menu item can contain other menu items, which allows you to create submenus for each item in the main menu. A collection is defined in the base Menu class to hold the entire MenuItem object, MenuItemCollection, as shown in the class diagram earlier. Now lets look at the properties by MenuStrip Item. Some of these properties are inherited from Menu. This list is not exhaustive if you require a complete listing please refer to the .NET Framework SDK Documentation.

Name Bar Break

Description By setting this value to true, you specify that the menu should appear on a new line. Using this property you can create menus with multiple top level rows. Submenu items with this property set will be placed in a new column. This property is not visible in the Properties Window.

All Rights Reserved To EaglesGroup

671

Checked Default Item

Enabled MdiList Merge Order

Mnemonic

Owner Draw

Radio Check Shortcut

Show Shortcut Text

Indicates whether the menu is checked. A default item is drawn with boldface. If a user doubles click a MenuItem that contains sub items, and one of these items is a default item that item is selected. An item with Enabled set to false will be graved and cannot be selected. Indicates whether the menu will be populated with a list of the child windows in an MDI. This property indicates where a menu will be positioned when it is merged with another menu. Well look at menu merging when we discuss MDI applications later in this chapter. This property returns the mnemonic character that is associated with the MenuStrip Item. The mnemonic character is the first character following an ampersand (&). This property is not visible in the Properties windows. If you set this property to true, you take responsibility for all drawing of the MenuItem. If you want to add images to your menus, you must set this property to true and implement handlers for the items Drawn Item and Measure Item events. If this property is set to true, a check is displayed as radio button rather than a check mark. The shortcut is key combination which access the menu item directly for example, Ctrl + Shift + B for build function in the Visual Studio .NET Environment Setting this property to true means that the shortcut text is displayed in the Menu Item. The text of the MenuStrip item. Include an ampersand (&) before a character in the string to assign the mnemonic character.

16.6 MenuStrip Item Events


672
All Rights Reserved To EaglesGroup

How many events are needed for a MenuItem? One you would think the Click event. In fact there are five events of interest you can subscribe to , two of which you must use if you drawing the items yourself. Lets look at the events now, and then move on to an example using this control. Name Click () Description This event occurs when a user clicks a menu item. You can also raise this event manually by calling the Perform Click () method of the MenuItem. Occurs when the MenuItem need to be drawn. If you set the Owner Draw property to true, you must handle this event. Occurs before a MenuItem is drawn. If you are drawing the Menu Item yourself, you should calculate and return the width and height for the item in this event. Occurs when the MenuStrip item list of sub items is displayed. You can use this event to perform validation of the availability of the items and set their state appropriately. Occurs when a user places the mouse pointer over the item or when he or she changes the focus using the keyboard.

Draw Item()

Measure Item()

Popup ()

Select ()

16.7 The ContextMenuStrip Control


A context menu strip control that is opened when the user right clicks on an item on the form. The context menu in the screenshot below is the menu I get when I right click the desktop of my computer.

All Rights Reserved To EaglesGroup

673

In Visual Studio.NET, you can create a context menu strip by dragging it onto the form and adding items to it, in exactly the same way as you would a MainMenu control. The only difference is that you cannot have any top level items in a context menu. To bind the context menu to a particular control on the form, you select the control and sets its ContextMenu property to point to the context menu youve created. We are now ready to create an example using the menus. Well keep this example basic as well see more advanced example of menus as we discus MDI application. Well create one main menu and a context menu strip in this example: Now lets try it by examples:

Example Try it out Eagles Usingmenus Step by Step Example: Using Version 2005
1. Create a new Windows application called Eagles Usingmenu in the directory C:\EaglesVisualCSharp\Chapter 16\Example Using Menu. 2. Add a MenuStrip control and a ContextMenuStrip control to the form by selecting it from the toolbox (menu and toolbars). Name the controls as MainMenuFiles and ContextMenuFonts respectively. 3. Add the following items to the MenuStrip control by selecting it and typing the text into the menu items. When you type text in the menu item using the designer, you are setting the Text property of the item. After setting the text for an item, use the Properties window to change the default name chosen by Visual Studio .NET. The menu names MenuItemFiles is know as top level menu. Remember that you create a separator by typing a single dash in the menu and create a mnemonic characters by adding an ampersand (&) in front of the letter you wish to choose: Name Text &Files &New &Open &Save E&xit

EaglesMenuItemFiles menuItemNew menuItemOpen menuItemSave menuItemSeperator0 menuItemExit

4. Now select the contextmenustrip, and create the following menu item just as you did above. Name menuItemBold menuItemItalic Text &Bold &Italic

674

All Rights Reserved To EaglesGroup

menuItemUnderline

&Underline

5. Now add a single RichTextBox control to the form. Name it as rtfText and set its Dock property to fill to make it fill the entire form, and clear its Text Property. 6. Select the RichTextBox control and select the ContextMenu property. From the drop down list, select ContextMenuFonts to bind the contextmenustrip to rich text box.

I Hope you should now have a form that looks something like this:

7. Now Run the Application and you will see a window some and try to type and use the menu items and you should see something like this:

All Rights Reserved To EaglesGroup

675

Now lets add the Program Code Adding the Event handlers
We are now ready to add code to our menus. Well keep the Open, Save, and New methods simple, and well use a fixed file for the demonstration in the next chapter well look at using the common dialogs that allows the user to select a file to open or save. To add a handler for the Click event of a menu item, you simply double click it, as for buttons and other controls. We will add handlers for the New, Open, Save, and Exit menu items. Clicking on a separator is not possible and noting should be done when the user clicks the files menu, so theres not need to add click event handlers to this menu item. Now we are almost entering the coding part by just double clicking the new menu item: private void menuItemNew_Click_1(object sender, EventArgs e) { this.rtfText.Clear(); }

676

All Rights Reserved To EaglesGroup

We said wed keep this simple, and we did. The sender parameter is a reference to the menu item that was clicked. In this case we know that it was the New item, but an event handler can be assigned to many items, in which case this identifies the menu to be used. Now Repeat the steps with the Open, Save, and Exit, and the code as follows: private void menuItemOpen_Click_1(object sender, EventArgs e) { // Now we are Loading the file fomr the computer try { this.rtfText.LoadFile("../../eagles.rtf"); } catch (System.Exception err) { MessageBox.Show("Error While Loading", "EaglesGroup", MessageBoxButtons.OK, MessageBoxIcon.Error); }

private void menuItemSave_Click_1(object sender, EventArgs e) } { // Saving the File try { this.rtfText.SaveFile("../../eagles.rtf"); } catch (System.Exception err) { MessageBox.Show("Error While Saving the File", "EaglesGroup", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void menuItemExit_Click_1(object sender, EventArgs e) { // Exit all the application Application.Exit(); }

All Rights Reserved To EaglesGroup

677

The LoadFile () method of the RichtTextBox class does exactly that it loads the contents of an RTF as can be exported from WordPad or Word, or ASCII file into the rich text box. Note that we have put error handling in here to deal with situations where the text file does not exist. However, there is another way of archiving this check, which we will look at now: The EaglesMenuItemFiles item contains the other items in our main menu. Because of that, every time the menu item is asked to show its members, it dispatches a Popup event. If we subscribe to that event, we can check if the file exists and disable the Open menu item if it doesnt. Well subscribe to the event by selecting the eaglesmenuitemfiles control, and double clicking on the Popup event in the Events list in the Properties window.

678

All Rights Reserved To EaglesGroup

Then we just add the code to the event handler itself: private void EaglesMenuItemFiles_Popup(object sender, System.EventArgs siddhu) { // The follwoing Code will check wether the file exist by setting the Enabled property to the return value of the File.Exist method this.EaglesMenuItemFiles.Enabled = System.IO.File.Exists("../../eagles.rtf"); } The static method Exists of the File class returns a Boolean which is true if the file exists and false otherwise which is exactly what we want the Open menu item to reflect, so we simply set the value of the Enabled property to the return value of this function.

We are now with the main menu and can move on to the context menu. We add the Click events just as we did in the main menu by double clicking the items and adding the following code:
private void menuItemBold_Click(object sender, EventArgs e) { Font newFont = new Font(rtfText.SelectionFont, (rtfText.SelectionFont.Bold ? rtfText.SelectionFont.Style & ~FontStyle.Bold : rtfText.SelectionFont.Style | FontStyle.Bold)); rtfText.SelectionFont = newFont; } private void menuItemItalic_Click(object sender, EventArgs e) { Font newFont = new Font(rtfText.SelectionFont, (rtfText.SelectionFont.Italic ? rtfText.SelectionFont.Style & ~FontStyle.Italic : rtfText.SelectionFont.Style | FontStyle.Italic)); rtfText.SelectionFont = newFont; } private void menuItemUndeline_Click(object sender, EventArgs e) { Font newFont = new Font(rtfText.SelectionFont, (rtfText.SelectionFont.Underline ? rtfText.SelectionFont.Style & ~FontStyle.Underline : rtfText.SelectionFont.Style | FontStyle.Underline)); rtfText.SelectionFont = newFont; }

All Rights Reserved To EaglesGroup

679

Now lets see how the above code works: In each of the three functions we create a new font from the one that is currently being used by the selection in the rich text box. If the style of the font is already set, we remove it form the new font, otherwise we include the style in the font. We then set the font of the selection to the new font. The single line that creates the object can look a bit daunting so well explain it here. To create the objects we make use of the ternary operate we first saw this in earlier chapter. Lets look at the code form the menuItemBold_Click method (): private void menuItemBold_Click(object sender, EventArgs e) { Font newFont = new Font(rtfText.SelectionFont, (rtfText.SelectionFont.Bold ? rtfText.SelectionFont.Style & ~FontStyle.Bold : rtfText.SelectionFont.Style | FontStyle.Bold)); rtfText.SelectionFont = newFont; } On the second line of the first statement, we examine whether the Bold property of the selected font is true. If it is, then we must create a new style for the font we are creating, which retains all the styles that are currently set except for the bold style, which is the code between the ? And the: on the third line. On the fourth line of the statement, after the colon, this code is run if the value of the Bold property is false, whereby we ad in the bold style rather than remove it. Finally the entire sequence of events just discusses is wrapped in parentheses, often used to separate out the ternary operator logic from other code and aid readability.

This concludes the first example of MenuStrip and the Context menu.

16.8 ToolStripMenu
While menus are great for providing access to multitude of functionality in your application, some items benefit being placed in a toolbars/toolstrip as well as on the menu. These items are those that are used frequently by the user, such as Open and Save, and a toolbar provides one click access to such commonly used functionality.

680

All Rights Reserved To EaglesGroup

The following screenshot has been taken from the Microsoft Word.

A button on the toolbar usually contains a picture and no text, though it is possible to have buttons with both. Examples, with no text are those found in Word as see above in the screenshot that includes text can be found in Internet Explorer and as well as in the Visual Studio .NET Environment. If you let the mouse pointer rest above a button in a toolbar, it should display a tooltip that provides some clue as the purpose of the button, especially when only an icon is displayed. Unlike the menu controls weve just discussed the ToolStripMenu control is not merely a container for other objects. You can set several properties on the control itself, such as where it is positioned on the screen. All the buttons on the toolstrip menu object and they hold the information about which image to display, the style of any text displayed with the icon, and tooltips.

In the version 2005 .NET the toolstrip menu has more feature than compare to the version 2003 .NET. Well start describing the properties and event of the ToolStripMenu control and then move on to the ToolBarButton.

16.9 ToolStrip Properties


The properties of the ToolStrip control manage how and where the control is displayed. They also manage some display setting for the buttons of the control, which would be the same for all the buttons contained in the control:

Name Appearance

AutoSize

Description This property controls the appearance of all the buttons contained within the control. You can set this property to Flat or to Normal. The normal setting will draw a 3D border around the button. Setting this property to false allows you to change the size of the control. The default, true, allows the control to size itself to make room for images and text.

All Rights Reserved To EaglesGroup

681

Buttons ButtonSize Divider DropDownArows

ImageList ShowToolTips Wrappable

Returns the collection of buttons contained in the control This property controls the size of the buttons. If the AutoSize property is true this property has no effect. If this property is set to true, the control will draw a border at the top of the ToolBar control If you have toolbar buttons that provide a drop down list, this property determines whether an arrow is drawn to the right of the button. The image list from which the images used on the buttons contained in the control are taken. Setting this property to true will make the control display tooltips for each button contained in the control. If this property is true, and the toolbar is too long to display all the buttons it contains in one line, it will wrap to the next line.

16.20 ToolStrip Event


The two events on the ToolStrip class that are not derived form Control are raised when a button or down arrow on a drop down list is clicked. You could be forgive for thinking that the buttons themselves would more logically raise these events, but Microsoft has choose otherwise. The result is that a single event handler must handle clicks on all the buttons in a toolbar, and this be able to distinguish the buttons. Name Button Click Description This event occurs whenever a button contained in the toolbar is clicked. To determine which button was clicked you should use the Button property of the ToolStripButtonClickEventArgs parameter that is sent to the event handler. By examining this property you can determine which action you should take. This event occurs when a toolstrip button with its Style property set to Dropdown Button or its corresponding arrow is clicked, the ToolStripButtonClickEventArgs can be used to determine which button was clicked and

Button DropDown

682

All Rights Reserved To EaglesGroup

Click DisplayStyleChanged Double Click Drag Drop Drag Enter Drag Leave Drag over Mouse Down Mouse Enter Mouse Hover Mouse Leave Mouse Move Mouse Up Paint QueryAccessibilityHelp QueryContinueDrag

thus which action to take. It occurs when the ToolStripItem is clicked It occurs when the Display Style has changed It occurs when the item is double clicked with the mouse. It occurs when the user drags an item and user releases the mouse button, indicating that the item should be dropped into this item. It occurs when the user drags an item into the client area of this item It occurs when the user drags an item and the mouse pointer is no longer over the client area of this item. It occurs when the user drags an item over the client area of this item. It occurs when the mouse pointer is over the item and a mouse button is pressed It occurs the mouse pointer enter the item. It occurs when the mouse pointer over the item, It occurs when the mouse pointer leaves the item. It occurs when the mouse pointer is moved over the item. It occurs when the mouse pointer is over the item and a mouse button is released. It occurs when the item is redrawn It occurs when a accessibility client application invokes help for the ToolStripItem It occurs during a drag and drop operation and allows the drag source to determine whether the drag and drop operation should be canceled.

16.21 The ToolStrip Button Properties


The ToolStripButton class manages individual settings for each button in a toolbar, including images, style and text and tooltip. One interesting feature of the ToolBarButton is, that if its style is set to DropDownButton, it is able to contain a menu more specifically a MenuItem containing the menu items to display.

Name DropDownMenu

Description By using this property you can assign a

All Rights Reserved To EaglesGroup

683

Enabled

Image Index Partial Push

Pushed

Style

MenuItem to the button. If the Style property of the button is DropDownButton the MenuItem will be displayed when the user clicks the button. By setting this property to false you make the button unavailable to the user. If you are using bitmap images on the button, then the button is only able to draw the image in monochrome. The index of the image to use. The image list is assigned to the ToolStrip control. You can use this property when the style of the toolstrip button is set to ToggleButton. Setting this property to true will make the button appear grayed. Unlike setting the Enable property to false, this setting cause the entire button face to become hazed. If the style of the ToolStrip button is ToggleButton then the setting this property to true will make the button appear pressed. There are four different style that can be used: Push Button: Appears like a normal button Toggle Button: When this style is selected the button can appear to be pressed and will remain in the state until pressed again. An example of such a button is the Bold button on the toolstrip used in Microsoft Word Separator: A button with this style is not drawn which is exactly the point; it creates a small space between buttons. DropDownButton: A button with this style can be assigned a ContextMenu. This menu will be dropped down when the user clicks the button. Combo Box : This will display the Combo box in the ToolStrip Label: This style will help to hold the Information about what the

684

All Rights Reserved To EaglesGroup

Text ToolTipText

user has given in the Label as in Text Property. Progress Bar: The is a new feature Style which can be make available to display in the ToolStrip it self. The text to display in the toolstrip button The tooltip text of the button.

The following table will show you the public properties of the ToolStripItem objects Name Anchor Description It obtains or sets the edges of the container to which a ToolStripItem is bound and determines how a ToolStripItem is resized with its parent. It obtains or sets a value indicating whether to use the Text property or the ToolTipText property for the ToolStripItem ToolTip It obtains or sets a value indicating whether the ToolStripItem should be placed on a ToolStrip It obtains or sets the background color for the item. It obtains or sets the background image layout used for the ToolStripItem. It gets the size and location of the item. It gets a value indicating whether the item can be selected. It gets the area where content, such as text and icons, can be placed within a ToolStripItem without overwriting background borders. It obtains or sets whether text and images are displayed on a ToolStripItem It obtains or sets which ToolStripItem borders are docked to its parent control and determines how a ToolStripItem is resized with its parent. It obtains or sets a value indicating whether the ToolStripItem can be activated by double clicking the mouse It Obtains or sets a value indicating whether the parent control of the

Auto ToolTip

Available Back Color Background Images Layout Bounds Can Select Content Rectangle

Display Style Dock

Double Click Enabled Enabled

All Rights Reserved To EaglesGroup

685

Font Fore Color Height Image Image Align Image Index Image Key Image Scaling Image Transparent Color IsDisposed IsOnDropDown IsOnOverflow Margin Merge Action Merge Index Overflow

ToolStripItem is enabled. It Sets or obtains the font of the text displayed by the item. It obtains or sets the foreground color of the item. It obtains or sets the height, in pixels, of a ToolStripItem. It obtains or sets the image that is displayed on a ToolStripItem. It obtains or sets the alignment of the image on a ToolStripItem. Obtains or sets the index value of the image that is displayed on the item. It obtains or sets the key accessor for the image in the ImageList that is displayed on a ToolStripItem. It obtains or sets a value indicating whether an image on a ToolStripItem is automatically resized to fit in a container. It obtains or sets the color to treat as transparent in a ToolStripItem Image It gets a value indicating whether the object has been disposed of. It gets a value indicating whether the container of the current Control is a ToolStripDropDown. It gets a value indicating whether the Placement property is set to Overflow. It Obtains or sets the space between the item and adjustment items. It obtains or sets how child menus are merged with parent menus. It obtains or sets the position of a merged item within the current ToolStrip It obtains or sets the whether the item is attached to the ToolStrip or ToolStripOverFlowButton or can float between the two. It obtains or sets the owner of this item. It gets the parent ToolStrip of this ToolStripItem. It obtains or sets the internal spacing, in pixel, between the items contents and its edges It gets the current layout of the item.

Owner Owner Item Padding Placement

686

All Rights Reserved To EaglesGroup

RightToLeft

Right To LeftAutoMirrorImage Selected Size Tag Text Text Align Text Direction TextImageRelation ToolTipText Visible Width DoDragDrop Get Current Parent GetPreferredSize Invalidate Perform Click Select Tab Stop Stretch

It obtains or sets a value indicating whether items are to be placed from right to left and text is to be written form right to left. Its a mirrors automatically the ToolStripItem image when the RightToLeft property is set to YES. It gets a value indicating weather the item is selected It obtains or sets the size of the item. It obtains or sets the text that is to be displayed on the item. It obtains or sets the text that is to be displayed on the item. It obtains or sets alignment of the text on a ToolStripLabel. It gets the orientation of text used on a ToolStripItem. It obtains or sets the position of ToolStripItem text and image relative to each other. It obtains or sets the text that appears as a ToolTip for a control It obtains or sets a value indicating whether the item is displayed. It obtains or sets the width in pixel of a ToolStripItem. It begins a drag and drop operation It gets or retrieves the ToolStrip that is the container of the current ToolStripItem. It retrieves the size of a rectangular area into which a control cab be fitted. Invalidates some or all of the surface of the control and causes the control to be redrawn It activates the ToolStripItem when it is clicked with the mouse. It selects the item. It obtains or sets a value indicating whether the user can give the focus to an item in the ToolStrip using the TAB key. It obtains or sets a value indicating whether the ToolStrip stretches from end to end in the ToolStripContainer.

All Rights Reserved To EaglesGroup

687

ShowItemToolTips

It obtains or sets a value indicating whether the ToolTips are to be displayed on the ToolStrip

16.22 Creating Tool Strips Just double click or drag and drop the toolstrip control to the Windows Forms, you can dock it on any edge you like by default, the dock property is set to Top, but you can set it to Bottom, Left, Right, Fill, or whatever you prefer. To actually add the items to a tool strip at design time, click the Items property at the design time, which opens the Items Collection Editor you can see in the following picture. You can add items to the tool strip as with the other editors weve see just select the type of item you want to add from the list before Add button and click the Add button to add a new button to the ToolStrip, and remove the button with a cross mark to removes a button. You can also set the text in an item with the Text property in the Item Collection Editor, an image from application resources or directly from a file to use for an item with the Image property, and the style of the button with the DisplayStyle property and TextImageRelation properties to specify the arrangement of text and image on the items where they are applicable. You can add one of these items to a tool strip from the item editor: ToolStripButton It is normal push button ToolStripLabel It non - selectable ToolStripItem that renders text and images and the display hyperlinks. ToolsStripSeparator It is a small space between other buttons used to space and group buttons. ToolsStripComboBox It is a ToolStripComboBox that is properly, rendered in a ToolStrip ToolStripTextButton It is a combination of a standard button on the left and a drop down button on the right. ToolStripSpitButton It is a combination of a standard button on the left and a drop down button on the right. ToolStripDropDownButton It is a button that can display a drop down menu. We will be adding a few of these types of items to the ToolStrip in the ToolStrip example on the chapter.

688

All Rights Reserved To EaglesGroup

Handling Tool Strip Button Clicks When a button item in a tool strip is clicked, the tool strip items Click event happens. You can simply double click an item to generate an skeleton handler for the event much like you do for standard buttons and then put the code there you want to get executed on the click event. Heres how that works in the ToolStrip example on the Program where we reporting that the text of the clicked button in a message box. private void toolStripButton1_Click(object sender, EventArgs e) { MessageBox.Show("You Have clicked me " + sender.ToString(), "EaglesGroup"); } 16.23 Drop- Down and Split Buttons Drop down and split buttons are one of the most useful styles of ToolStrip buttons, these buttons can display a drop down menu if you click their down arrow. The only difference between a drop down and a split button is that a drop down only displays a drop down menu, whereas a split button can display a drop down menu as well as work as a push as push button if you click the button itself, instead of the down arrow that appears at their end. You can add menus items to these buttons in the form editor much like you would do in a menu strip case. Another way to add a menu to a Drop Down button is to create a context menu strip, and assign that menu to the buttons DropDown property. To see how this works, take a look at the ToolStrip example on the CD which is made available with this book. Weve added three menu items, they are Red, Blue, and Green, to drop down menu and implemented the event handler for these items like this:

All Rights Reserved To EaglesGroup

689

private void redToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("You Have Clicked " + sender.ToString(), "EaglesGroup"); } private void greenToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("You Have Clicked " + sender.ToString(), "EaglesGroup"); } private void blueToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("You Have Clicked" + sender.ToString(), "EaglesGroup"); } DENOTE: You can also add buttons to the drop down or split buttons with the Items Collection Editor, which you open with the DropDownItems Property in the Properties Window. Thats all it takes, you can see the active drop down button in the below picture.

16.24 Connecting ToolStrip Buttons to Menu Items

690

All Rights Reserved To EaglesGroup

Typically, ToolStrip buttons correspond to frequently used menu items. To connect a ToolStrip to a menu item, you can use that menu items Perform Click method to make it seem as though the item itself was clicked. private void toolStripDropDownButton1_Click(object sender, EventArgs e) { pickColorToolStripMenuItem.PerformClick(); }

16.25 Creating ToolStrip Image Buttons To Display images in ToolStrip button, you only need to set the Image property of the button in the Items Collection Editor to the image you want to use. Adding Combo boxes and Other Control to ToolStrip One of the common non button controls you see in ToolStrip is the Combo box control, which lets the user select an item from a list, or type their own entry. In the previous version of the Visual Studio Version 2002 and Version 2003, it was difficult to add the combo box or such controls to Toolbars, but now in the Visual Studio 2005 and 2008 it is very easy to add these controls. You can add combo boxes, text boxes, and progress bars, right from the Items Editor. Thats what the example we are going to see and the example already in the CD also which is made available with this book. Weve added a few item to the combo box, like Times New Roman, Arial, and added this code to its SelectedIndexChanged event handler: private void toolStripComboBox1_Click(object sender, EventArgs e) { MessageBox.Show("Selected item text: " + toolStripComboBox1.SelectedIndex.ToString() ,"EaglesGroup"); }

Adding Buttons to a ToolStrip at Run Time As you might except, you can add buttons to ToolStrip at the run time.