Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
94% found this document useful (16 votes)
23K views143 pages

VTU MCA .NET Notes

Download as pdf
Download as pdf
Download as pdf
You are on page 1/ 143

Enterprise Architecture - II

Bandari Ravikiran

October 28, 2009


2

For this material contact


ravikiran1312@sify.com

Ravikiran
Contents

1 Philosophy of .NET 7
1.1 Life Before .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 .NET Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3 Building blocks of .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.1 Common Lanugage Runtime (CLR) . . . . . . . . . . . . . . . . . . . . . 12
1.3.2 Common Type System(CTS) . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.3 Cross Language Specification (CLS) . . . . . . . . . . . . . . . . . . . . . 12
1.4 Base Class Library[BCL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5 C# Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5.1 C# Language Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.6 Overview of .NET Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7 Common Intermediate Language (CIL) . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.1 Advantages of CIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.2 Compiling CIL to platform specific Instructions . . . . . . . . . . . . . . . 16
1.8 Common Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.8.1 Built - In Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.9 Common Language Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.10 Common Language Runtime(CLR) . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.10.1 Features of CLR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.11 Namespaces in .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.11.1 Accessing a Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.12 Deploying .NET Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2 Building C# Applications 23
2.1 C# Command Line Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.1 Configuring the C# Command-Line Compiler . . . . . . . . . . . . . . . . 23
2.1.2 Configuring Additional .NET Command-Line Tools . . . . . . . . . . . . 23
2.2 Building C# Applications using csc.exe . . . . . . . . . . . . . . . . . . . . . . . 24
2.2.1 Referencing External Assemblies . . . . . . . . . . . . . . . . . . . . . . . 25
2.3 csc.exe Response Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.3.1 The Default Response File(csc.rsp) . . . . . . . . . . . . . . . . . . . . . . 26
2.4 Generating Bug Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.5 Remaining C# Compiler Options . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.6 The Command Line Debugger (cordbg.exe) . . . . . . . . . . . . . . . . . . . . . 29
2.6.1 Debugging at Command Line . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.7 Using Visual Studio - .NET IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.7.1 The VS.NET Start Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3
4 CONTENTS

2.7.2 Creating VS.NET Project Solution . . . . . . . . . . . . . . . . . . . . . . 30


2.8 Building VS.NET Test Application . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.8.1 Examining the solution explorer window . . . . . . . . . . . . . . . . . . . 32
2.8.2 Examining Class View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.9 VS.NET Solution Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.9.1 Properties Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.10 Other Key Aspects of VS.NET IDE . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.10.1 Server Explorer Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.10.2 XML-Related editing tools . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.10.3 Object Browser Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.10.4 Database Manipulation in Visual Studio . . . . . . . . . . . . . . . . . . . 37
2.11 C# language’s preprocessor directives . . . . . . . . . . . . . . . . . . . . . . . . 37
2.12 System Environment Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3 C# Language Fundamentals 43
3.1 Anatomy of C# Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.1 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.2 Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.3 Main Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2 Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.2.1 Types of Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.3 System.Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.3.1 Basic Input and Output with the Console Class . . . . . . . . . . . . . . . 48
3.3.2 Formatting Console output . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.3.3 Formatting Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.3.4 Custom Number Formatting . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.3.5 Date Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.3.6 Custom Date Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.4 Default values for variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.5 Variable Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.6 Member Variable Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.7 Value Types and Reference Types . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.7.1 Value Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.7.2 Reference Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.8 Boxing and Unboxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.8.1 Boxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.8.2 UnBoxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.9 System.Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.10 Constant Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.10.1 const modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.10.2 By using readonly modifer . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.11 Iteration Constructs in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.11.1 while loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.11.2 do-while loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.11.3 for loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.11.4 foreach loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.12 Flow Control statements in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.12.1 Jump Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.12.2 Selection Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

Ravikiran
CONTENTS 5

3.13 C# Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.14 Defining Custom Class Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.15 Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.16 Method Parameter Modifiers in C# . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.16.1 Value parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.16.2 Reference parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.16.3 Output Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.16.4 Parameter arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.17 Arrays in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.17.1 Array Bounds Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.17.2 Multi Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.17.3 System.Array class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.18 String Manipulation in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3.18.1 String Manipulation Methods . . . . . . . . . . . . . . . . . . . . . . . . . 73
3.18.2 System.Text.StringBuilder Class . . . . . . . . . . . . . . . . . . . . . . . 75
3.18.3 Escape Characters and Verbatim Strings . . . . . . . . . . . . . . . . . . . 75
3.19 Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.19.1 System.Enum class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4 Object Oriented Programming using C# 81


4.1 Definition of C# class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.1.1 Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.2 Self Reference in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.2.1 Forwarding Constructor Calls using ”this” . . . . . . . . . . . . . . . . . . 83
4.3 Default Public Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.4 Pillars of OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.4.1 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.5 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.5.1 Classical Inheritance : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
4.5.2 Containment / Delegation model (”Has-A” Relationship) . . . . . . . . . 90
4.5.3 ”base”- keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
4.5.4 Preventing Inheritance : Sealed classes . . . . . . . . . . . . . . . . . . . . 92
4.6 Ploymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
4.7 Abstract Classes & Abstract Methods . . . . . . . . . . . . . . . . . . . . . . . . 95
4.8 Type Casting in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4.8.1 ”is” - Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4.8.2 ”as” - operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

5 Exceptions and Object Lifetime 99


5.1 Introduction to Errors, Bugs, and Exceptions . . . . . . . . . . . . . . . . . . . . 99
5.2 The Role of .NET Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . 99
5.2.1 The Elements of .NET Exception Handling . . . . . . . . . . . . . . . . . 100
5.3 The System.Exception Base Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
5.3.1 Members of System.Exception Class . . . . . . . . . . . . . . . . . . . . . 101
5.4 Throwing a Generic Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
5.5 Catcing Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
5.6 CLR System-Level Exceptions (System.SystemException) . . . . . . . . . . . . . 105
5.7 Custom Application-Level Exceptions . . . . . . . . . . . . . . . . . . . . . . . . 105
5.7.1 Creating Custom Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . 106

Ravikiran
6 CONTENTS

5.8 Handling Multiple Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107


5.9 The Finally Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.10 Last chance of Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
5.11 Identifing Application and System Exceptions . . . . . . . . . . . . . . . . . . . . 109
5.12 Debugging Unhandled Exceptions using Visual Studio . . . . . . . . . . . . . . . 110
5.13 Understanding Object Life Time . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
5.14 The CIL of ”new” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
5.15 Garbage Collection Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
5.16 Finializing a Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
5.17 The Finalization Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
5.18 Building an Ad Hoc Destruction Method . . . . . . . . . . . . . . . . . . . . . . . 115
5.18.1 The IDisposable Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
5.18.2 Reusing the C# ”using” Keyword . . . . . . . . . . . . . . . . . . . . . . 116
5.19 Garbage Collection Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . 116
5.20 The System.GC Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

6 Interfaces and Collections 119


6.1 Implementing Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
6.2 Contrasting Interfaces to Abstract Base Classes . . . . . . . . . . . . . . . . . . . 121
6.3 Invoking Interface Members at Object Level . . . . . . . . . . . . . . . . . . . . . 121
6.4 Explicit Interface Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
6.4.1 The Advantages of Explicit Interface Implementations . . . . . . . . . . . 126
6.5 Building Interface Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
6.6 IConvertible Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
6.6.1 The IConvertible.ToXXXX() Members . . . . . . . . . . . . . . . . . . . . 129
6.7 Building Custom Enumerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.8 Building Cloneable objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
6.9 Building Comparable Objects (IComparable) . . . . . . . . . . . . . . . . . . . . 135
6.9.1 Specifying Multiple Sort Order . . . . . . . . . . . . . . . . . . . . . . . . 136
6.10 Exploring the System.Collections Namespace . . . . . . . . . . . . . . . . . . . . 138
6.10.1 The Interfaces of System.Collections . . . . . . . . . . . . . . . . . . . . . 138
6.10.2 The Role of ICollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
6.10.3 The Role of IDictonary . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
6.10.4 The Role of IDictionaryEnumerator . . . . . . . . . . . . . . . . . . . . . 139
6.10.5 The Role of IHashCodeProvider . . . . . . . . . . . . . . . . . . . . . . . 139
6.10.6 The Role of IList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
6.10.7 The Class Types of System.Collections . . . . . . . . . . . . . . . . . . . . 140

Ravikiran
Chapter 1

Philosophy of .NET

1.1 Life Before .NET

C Language
The main philosophy of C Language is ”Programmers know what to do”, but it does not
help or assist or warn you about anything, unless there is some syntactical error like some type
mismatch, or some macro redefinition, or some array’s index goes out of bound, etc...
Main drawbacks of C Language are

1. Concept of Pointers is the powerful feature of C Language. But, they are highly insecure
and makes it vulnerable.

2. The concept of re usability is achieved only through functions, so it makes it more complex
for coding big projects as we have to write everything from scratch and hence lot of time
is wasted.

3. C developers have to concentrate on memory management as there is no automatic


memory management.

4. Since C is structured language, it lacks all the benefits of object oriented programming
concepts like Abstraction, Encapsulation, Inheritance and Polymorphism

Besides all these, C is a powerful language, thats why, a majority of Operating Systems are built
using C.

C++ Language
C++ was designed at AT & T Bell Labs by Bjarne Stroustrup in the early 80s. The main
features of C++ are

• Stronger typechecking

7
8 CHAPTER 1. PHILOSOPHY OF .NET

• Support for data abstraction

• Support for object-oriented programming

• Support for generic programming

Apart from these advantages, C++ has following drawbacks

• It is not truly object oriented

• It is not suitable for developing web technologies

• It does not support versioning i.e. creation and management of multiple versions of a
software. All versions have the same general function but they are improved, upgraded or
customized. New versions of software modules can work with existing applications

• It is not type-safe. It means the following

– C++ arrays are unbound.


– Compile time errors are not generated when uninitialized arrays are used

• C++ still support pointers which will leads to major errors in programs and also it
makes C++ programs highly insecure

Visual Basic 6.0


Like many things, VB’s greatest strengths are also its greatest weaknesses. The following are
some of the advantages of VB

1. VB was originally designed as a programming language for non-programmers. To that end,


the syntax was designed to read more like natural language sentences than instructions to
a computer.

2. As VB does not support pointers, it does limit what we can do with VB

3. In VB, there is no need to specify the type of a variable, or even declaring the variable
itself. This provide an advantage of using a variable without having to worry about, or
even knowing about the data type or size of the variable.

Drawbacks of VB are

1. VB is not fully object oriented

2. Developing multi-threading applications using VB is a bit complex as we have to call the


low level WIN32 API calls

3. We have to distribute a runtime with all of our applications (or install it to the computer
before you use the application). This adds to a larger download (not all versions of windows
have the VB6 runtime and even less have the .Net framework). The minimum distribution
package is greater than 1 floppy. This is because the VB 6.0 run-time must be included.

Ravikiran
1.1. LIFE BEFORE .NET 9

4. As there is no need to declare the data type of variables prior to its usage, there will be
more chances to get runtime errors

5. Every time you create a new form or code file, you must remember to specify the directory
where you want it stored. There is no default setting to specify that new code for a specific
project should default to a specific directory.

JAVA / J2EE
Java is one of the most popular programming language, because of its following features..

1. It is Platform Independent

2. It contains large number of predefined packages that contain various type definitions.

3. Java programmers can build pure Java applications complete with database connec-
tivity, messaging support, web-enabled front ends, and a richer user interface

4. Java eliminates pointers which is major concern in C and C++

5. Allows Concurrent control in an application

6. Garbage collection is one of the powerful feature of JAVA which automatically cleans the
memory.

Like any programming language, Java is not without drawbacks. Here are some of the drawbacks
of JAVA...

1. Java applets are not supported by all the browsers and they need separate plug-in to be
installed

2. Java developers have less control over on garbage collection to free objects

3. Primary goal of Java is to make Java as a single programming language for every need. So
Java offers a little chance for language integration.

COM
Component Object Model, abbreviated as COM, is Microsofts framework for developing and
supporting component objects. It enables interprocess communication and dynamic object cre-
ation. COM is an architecture that says ”If you build your classes in accordance with the rules
of COM, you end up with a block of reusable binary code”.
The COM model has come into widespread use since its introduction by Microsoft and it is an
integral part of many Microsoft applications and technologies, including Internet Explorer and
the Office suite of applications.
Unlike traditional software development, which required each application to be built from scratch,
COM allows developers to create complex applications using a series of small software objects.

Ravikiran
10 CHAPTER 1. PHILOSOPHY OF .NET

COM lets developers make portions of their applications using components. For example, a
component might be a tax calculation engine or the business rules for a price list.
This approach speeds up the development process by allowing several teams to work on separate
parts at the same time. Developers can also reuse components from one project to the next, and
they can easily swap out or update a particular component without affecting other portions of
the application.

1. The primary advantage of the Component Object Model is that it is founded on the object-
oriented principles

2. It has given rise to the development of popular technologies like COM+ and the .NET
framework. COM+ provides the users with support for distributed transactions. The
.NET framework has taken over the COM platform and is largely being used for software
development

3. COM technology is perhaps the most suitable means of developing and deploying desktop
applications

4. COM can best be described as an infrastructure that allows building speedy, and extensible
component-based software

Drawbacks of COM are

1. Writing COM classes is very complex

2. We cannot create a new COM class with existing COM class

Windows DNA Architecture


DNA stands for Distributed interNet Application Architecture. Windows DNA is essentially a
’blueprint’ that enables corporate developers and independent software vendors (ISVs) to design
and build distributed business applications using technologies that are inherent to the Windows
platform. ”It consists of a conceptual model and a series of guidelines to help developers make
the right choices when creating new software applications.”
Applications based on Windows DNA will be deployed primarily by businesses, from small com-
panies to large enterprise organizations. Consumers are likely to use many of the applications
built to take advantage of Windows DNA, such as electronic commerce Web sites and on-line
banking applications.
Central to Windows DNA is the concept that applications should be logically separated into
partitions, called tiers. The three tiers of Windows DNA are:

1. Presentation or User Interface

2. Business logic

3. Data Storage

Ravikiran
1.2. .NET FEATURES 11

Drawbacks of DNA Architecture

1. DNA is quite complex because of the fact that Windows DNA requires the use of numerous
technologies and languages (ASP, HTML, XML, JavaScript, VBScript, and COM(+), as
well as a data access API such as ADO).

2. Each technology is different from other technology in their syntax and also in semantics.
So when they are combined in DNA, it may results in highly confused mishmash of tech-
nologies.

1.2 .NET Solution


The main features of .NET are

• .NET is multi-lingual With the .NET platform we can use several languages, such as
C++, JScript, VB.NET, C# etc... All these languages are combined via an intermediate
binary code, which is independent of hardware and operating systems. This intermediate
language called Microsoft Intermediate Language (MSIL) is then executed in the
Common Language Runtime(CLR) which is the execution environment of .NET applica-
tions

• .NET Applications are portable Applications compiled as intermediate code are pre-
sented as Portable Executables (PEs). These PEs can be implemented over a vast
range of hardware and software architectures: Intel PCs with windows 9x, Windows NT4,
Windows 2000 or 64 bit windows versions, PocketPC and other operating systems.

• All Languages must agree with a common agreement For a language to be eligi-
ble for the range of languages supported by the .NET platform, it must provide a set of
possibilities and constructions listed in the agreement called Common Language Spec-
ification (CLS). To add a language to .NET, all that is required is for it to meet the
requirements of the CLS, and a compiler to convert that language into MSIL.

• Managed Codes All Code in .NET is managed code because the runtime provides ser-
vices that include automatic memory management, debugging support, enhanced security.
Earlier, the developers had to explicitly manage the memory in languages like C++.

• Complete and total language integration: Unlike COM, .NET supports cross-language
inheritance, cross-language exception handling, and cross-language debugging.

• Base class library: .NET framework provides a class library that offers a consistent
object model used by all .NET-aware languages.

• Interoperability: All languages supported by the .NET framework support a common


set of programming classes as their base class library. This means that the developers
will not have trouble while interoperating between languages since all of them support the

Ravikiran
12 CHAPTER 1. PHILOSOPHY OF .NET

same set of APIs and also have the same data types as specified by the Common Type
Specification (CTS)

1.3 Introducing the Building Blocks of the .NET Platform


(the CLR, CTS, and CLS)
The three building blocks of .NET platform are

• Common Language Runtime(CLR)

• Common Type System (CTS)

• Cross Language Specification (CLS)

1.3.1 Common Lanugage Runtime (CLR)


The .NET framework provides a run-time environment called the Common Language Runtime,
which manages the execution of code and provides services that make the development process
easier. CLR makes it easy to design components and applications whose objects interact across
languages. Objects written in different languages can communicate with each other and their
behaviors can be tightly integrated.

1.3.2 Common Type System(CTS)


With so many languages to run in same runtime environment, it becomes a necessity that they all
follow some guidelines. In .NET framework, CTS describes the types supported by the runtime
and specifies how those types can interact with each other. The types in the runtime’s type
system include classes, interfaces and value types.

1.3.3 Cross Language Specification (CLS)


.NET provides support for language interoperability. However, it doesnt mean every program
written in a language can be used by another language. To enable a program to be used with
other languages, it must be created by following a set of rules called Cross Language Specifications
(CLS). The runtime provides cross language integration through a new Common Type System.
the Common Type System defines a standard set of types that can represent the types supported
by most modern programming languages. It also provides rules for creating new types, if required.

1.4 The Role of the Base Class Libraries


The Base Class Library (BCL) is a standard library available to all languages using the .NET
Framework. .NET includes the BCL in order to encapsulate a large number of common functions,
such as file reading and writing, graphic rendering, database interaction, and XML document

Ravikiran
1.5. C# LANGUAGE 13

manipulation, which makes the programmer’s job easier. The BCL is sometimes incorrectly
referred to as the Framework Class Library (FCL), which is a superset including the Microsoft.*
namespaces

1.5 C# Language
Microsoft has developed a new programming language, C# (pronounced ”see sharp”), specifically
for this new platform. C# is a programming language that looks very similar (but not identical)
to the syntax of Java. C# is primarily derived from the C, C++, and Java programming
languages with some features of Microsoft’s Visual Basic in the mix.

1.5.1 C# Language Features


c# language offers the following features (many of which are shared by other .NET-aware pro-
gramming languages):

• No pointers required c# programs typically have no need for direct pointer manipulation

• Unsafe operations such as direct memory manipulation are not allowed.

• Since it‘s on .NET, it inherits the features of automatic memory management and
garbage collection.

• C# has been based according to the current trend and is very powerful and simple for
building interoperable, scalable, robust applications.

• As of C# 2005, the ability to build generic types and generic members using a
syntax very similar to C++ templates.

• The C++-like ability to overload operators for a custom type, without the complexity

• Arrays are zero base indexed and are bound checked.

• Overflow of types can be checked

As C# comes along with .NET platform, it can only produce code that can execute within the
.NET runtime. Officially speaking, the term used to describe the code targeting the .NET runtime
is managed code. The binary unit that contains the managed code is termed an assembly and
the code that cannot be directly hosted by the .NET runtime is termed as unmanaged code.

1.6 Overview of .NET Assemblies


An assembly is the primary building block of a .NET application and can take the form of a
dynamic link library (DLL) or executable file (EXE). An assembly is a collection of functionality
that is built, versioned, and deployed as a single implementation unit.

Ravikiran
14 CHAPTER 1. PHILOSOPHY OF .NET

In the Microsoft .NET framework, an assembly is a partially compiled code library for use
in deployment, versioning and security. The .NET assembly is the standard for components
developed with the Microsoft.NET. Dot NET assemblies may or may not be executable, i.e.,
they might exist as the executable (.exe) file or dynamic link library (.dll) file. All the .NET
assemblies contain the definition of types, versioning information for the type and meta-data.
.NET assemblies do not contain platform specific instructions.

Figure 1.1: All .NET-aware compilers emit IL instructions and metadata.

When a *.dll or *.exehas been created using a .NET-aware compiler, the resulting module is bun-
dled into an assembly. An assembly contains CIL (Common Intermediate Language) code, which
is conceptually similar to Java bytecode and it is not compiled to platform specific instructions.
In addition to CIL instructions , assemblies also contain metadata that describes the various
characteristics of every ”type” described with in the binary assembly. Finally, in addition to CIL
and type metadata, assemblies themselves are also described using metadata, which is officially
termed as manifest. The manifest contains information about the current version of the assembly,
culture information (used for localizing string and image resources), and a list of all externally
referenced assemblies that are required for proper execution.
A .NET assembly may contain the following elements:

1. Assembly Manifest :An assembly manifest is metadata inside an assembly that describes
everything there is to know about the assembly and its contents. The manifest contains:

(a) Strong Name - The assembly’s name, version, culture, optional processor architec-
ture, and public key (for shared assemblies)
(b) File Contents - Name and hash of all files in the assembly
(c) Type List - Types defined in the assembly, including public types that are exported
from the assembly
(d) Resource List - Icons, images, text strings and other resources contained in the
assembly
(e) Dependencies - Compile-time dependencies on other assemblies

Ravikiran
1.7. COMMON INTERMEDIATE LANGUAGE (CIL) 15

(f) Security - Permissions required for the assembly to run properly

2. Source Code :Compiled into Microsoft intermediate language (MSIL)

3. Type Metadata : Defines all types, their properties and methods, and most importantly,
public types exported from this assembly

4. Resources :Icons, images, text strings and other resources

Single-File and Multi file Assemblies

The .NET platform supports two broad types of assemblies


Single file assemblies:

1. A single *.dll or *.exe file which contains the CIL code, metadata, manifest and optional
resources in one binary package.

2. This is the simplest type of assemblies. It contains the type information and implementation
as well as the assembly’s manifest into a single physical file.

3. Class Libraries, Windows Forms / WPF applications, Console applications and Windows
Services are all examples of single file assemblies.

Multi-file assemblies: An assembly can consist of one or more files called modules. Exactly
one of these modules contains the assembly manifest. Note that the files in a multi-file assembly
can reside in separate locations and are linked together with the assembly manifest.
Multi-file assemblies are rare, and Visual Studio doesn’t directly support their creation. The
most common reason for multi-file assemblies is when a single assembly combines code from
multiple programming languages.

1.7 Common Intermediate Language (CIL)


.NET language compilers do not emit native platform code. Rather, they emit platform-
independent instructions called the Common Intermediate Language (CIL). CIL is an object-
oriented assembly language, and is entirely stack-based. It is executed by a virtual machine.
CIL is a language that sits above any particular platform-specific instruction set. Regardless of
which .NET-aware language we choose, the associated compiler emits CIL instructions.

1.7.1 Advantages of CIL


1. Language Integration :The main benefit of CIL is Language Integration. As all the
.NET aware compilers produce nearly identical CIL Instructions, the program written in
one language can be interact with other language. ( Note that both the languages should
be .NET aware languages)

Ravikiran
16 CHAPTER 1. PHILOSOPHY OF .NET

2. Platform Independence As CIL doesn’t emit any platform specific code, CIL is an plat-
form independent code. Besides, there is an international standard for the C# language,
and a large subset of the .NET platformand implementations already exist for many non-
Windows operating systems

1.7.2 Compiling CIL to platform specific Instructions


As CIL instructions are not platform specific (not machine code), they have to be converted into
machine language. In .NET, this work is carried out by Just - in - time Compiler (JIT
Compiler) The .NET runtime environment leverages a JIT compiler for each CPU targeting
the runtime, each optimized for the underlying platform
CIL is just-in-time compiled to the target platform at runtime. A block of code (method) is
just-in-time complied when it is first called by a client. JIT compilation provides environment-
specific optimization, runtime type safety, and assembly verification. To accomplish this, the
JIT compiler examines the assembly metadata for any illegal accesses and handles violations
appropriately.
Furthermore, as a given Jitter compiles CIL instructions into corresponding machine code, it
will cache the results in memory in a manner suited to the target operating system. In this
way, if a call is made to a method named PrintDocument(), the CIL instructions are compiled
into platform-specific instructions on the first invocation and retained in memory for later use.
Therefore, the next time when the PrintDocument() is called, there is no need to recompile the
CIL.

1.8 Common Type System


A given assembly may contain any number of distinct types. In the world of .NET, ”type” is
simply a generic term used to refer to a member from the set ( A set may be either class or
structure or interface or enumeration or delegate)
As .Net Framework is language independent and support over 20 different programming lan-
guages, many programmers will write data types in their own programming language.
For example, an integer variable in C# is written as int, whereas in Visual Basic it is written
as integer. Therefore in .Net Framework you have single class called System.Int32 to interpret
these variables. Similarly, for the ArrayList data type .Net Framework has a common type called
System.Collections.ArrayList. In .Net Framework, System.Object is the common base type from
where all the other types are derived.
This system is called Common Type System. The types in .NET Framework are the base on
which .NET applications, components, and controls are built. Common Type System in .Net
Framework defines how data types are going to be declared and managed in runtime. The
Common Type System performs the following functions:

1. Automatically adapts itself in a framework that enables integration of multiple languages,


type safety, and high performance code execution.

Ravikiran
1.8. COMMON TYPE SYSTEM 17

2. Provides an object-oriented model that supports the complete implementation of many


programming languages.

3. Defines rules that languages must follow, which helps ensure that objects written in different
languages can interact with each other.

There are two general types of categories in .Net Framework that Common Type System support.
They are value types and reference types. Value types contain data and are user-defined or built-
in. they are placed in a stack or in order in a structure. Reference types store a reference of the
values memory address. They are allocated in a heap structure. You can determine the type
of a reference by the values of self-describing types. Reference types can be categorized into
self-describing types, pointer types, or interface types.
There are five different types defined in .NET framework

1. CTS Class Type : Every .NET-aware language supports, the notion of a class type,
which is the cornerstone of object-oriented programming (OOP). A class may be composed
of any number of members (such as properties, methods, and events) and data points
(fields).

2. CTS Structure Type : The concept of a structure is also formalized under the CTS. A
structure can be thought of as a lightweight class type having value-based semantics

3. CTS Interface Types : Interfaces are nothing more than a named collection of abstract
member definitions, which may be supported (i.e., implemented) by a given class or struc-
ture.

4. CTS Enumeration Types :Enumerations are a handy programming construct that al-
lows us to group name/value pairs.

5. CTS Delegate Types Delegates are equivalent to function pointers in C Language. The
key difference is that a .NET delegate is a class that derives from System.MulticastDelegate,
rather than a simple pointer to a raw memory address.

6. CTS Member Types : A type member can be either constructor or finalizer or static
constructor or nested type or operator or method or property or indexer or field or read
only field or constant or event.

1.8.1 Built - In Data Types


.NET framework supports a well defined set of core data types. We know that there are different
languages which are supported by .NET framework and each language is having its own syntax
to declare an data type. But ultimately all those key words resolve to the same type defined in
an assembly named mscorlib.dll.
The following are the some of the data types defined in .NET Frame work

Ravikiran
18 CHAPTER 1. PHILOSOPHY OF .NET

CTS Data Type C# Keyword


System.Byte byte
System.SByte sbyte
System.Int16 short
System.Int32 int
System.Int64 long
System.UInt16 ushort
System.UInt32 uint
System.UInt64 ulong
System.Single float
System.Double double
System.Object object
System.Char char
System.String string
System.Decimal decimal
System.Boolean bool

Table 1.1: The Built-in CTS Data Types

1.9 Common Language Specification


The Common Language Specification (CLS) is a set of rules that a given .NET-aware compiler
must support to produce code that can be hosted by the CLR, while at the same time be accessed
in a uniform manner by all languages that target the .NET platform. In many ways, the CLS
can be viewed as a subset of the full functionality defined by the CTS.
The CLS helps enhance and ensure language interoperability by defining a set of features that
developers can rely on to be available in a wide variety of languages. The classes that follow the
rules specified by CLS are termed as CLS-complaint classes. The classes defined in the .NET
Framework class library are CLS-Compliant. The CLS describes a set of features that different
languages have in common. CLS Compliance is especially important when creating software
components that will be used by other languages.

The most important rules, and which apply to public and protected members are

1. All types appearing in a method prototype must be CLS-compliant

2. Array elements must have a CLS-compliant element type. Arrays must also be 0-indexed

3. A CLS compliant class must inherit from a CLS-compliant class only

1.10 Common Language Runtime(CLR)


Common Language Runtime (CLR) is the execution environment for the .NET framework appli-
cations. CLR provides a unified environment for execution of programs written across different
programming languages. While an application is running, the runtime environment is responsible

Ravikiran
1.10. COMMON LANGUAGE RUNTIME(CLR) 19

for managing memory allocation, starting up and killing processes, and enforcing security policy,
as well as satisfying any dependencies that the component might have on other components.
Programmatically speaking, the term runtime can be understood as a collection of external ser-
vices that are required to execute a given compiled unit of code

The CLR makes it easy to design components and applications whose objects interact across
languages. Objects written in different languages can communicate with each other, and their
behaviors can be tightly integrated.

1.10.1 Features of CLR


The following are some of the unique features of CLR

1. Cross Language Integration

2. Self Describing Components

3. Simple Deployment and Versioning

4. Integrated Security Services

5. Garbage Collection

6. High Performance

7. Reusability

Figure 1.2: Common Language Runtime Architecture

Ravikiran
20 CHAPTER 1. PHILOSOPHY OF .NET

1.11 Namespaces in .NET


A Namespace in Microsoft .Net is like containers of objects. They may contain unions, classes,
structures, interfaces, enumerators and delegates. Main goal of using namespace in .Net is for
creating a hierarchical organization of program. In this case a developer does not need to worry
about the naming conflicts of classes, functions, variables etc., inside a project.
In Microsoft .Net, every program is created with a default namespace. This default namespace is
called as global namespace. But the program itself can declare any number of namespaces, each
of them with a unique name. The advantage is that every namespace can contain any number
of classes, functions, variables and also namespaces etc., whose names are unique only inside the
namespace. The members with the same name can be created in some other namespace without
any compiler complaints from Microsoft .Net.
To declare namespace in C# .Net has a reserved keyword ”namespace”. If a new project is
created in Visual Studio .NET it automatically adds some global namespaces. These names-
paces can be different in different projects. But each of them should be placed under the base
namespace System. The names space must be added and used through the using operator, if
used in a different project.
Example
using System;
namespace OutNamespace
{
namespace WorkNamespace
{
// Here we can be placed some classes, structures etc.
class WorkItem
{
public WorkItem(){ }
}
}
}

In this example we create two namespaces. These namespaces have hierarchical structure - outer
one named OutNamespace and the inner one called WorkNamespace. The inner namespace is
declared with a C# .Net class WorkItem.

1.11.1 Accessing a Namespace


In C#, the ”using” keyword is used to refer any type declared in the namespace.
They are two forms of using directive. The firsh is shown here

1. using name

Ravikiran
1.12. DEPLOYING .NET FRAMEWORK 21

Here, name specifies the name of the namespace we want to access. All of the members
defined in the specified namespace will now become the part of the current namespace.
Using directive should be specified at the top of the file, prior to any other declarations.

2. using alias = name


Here, alias becomes another name for the class or namespace specified by name

1.12 Deploying .NET Framework


NET assemblies can be executed only on a machine that has the .NET Framework installed.
As an individual who builds .NET software, this should never be an issue, as your development
machine will be properly configured at the time you install the freely available .NET Framework
2.0 SDK.

However, if you deploy an assembly to a computer that does not have .NET installed, it will fail
to run. For this reason, Microsoft provides a setup package named dotnetfx.exethat can be freely
shipped and installed along with your custom software. This installation program is included
with the .NET Framework 2.0 SDK, and it is also freely downloadable from Microsoft. Once
dotnetfx.exeis installed, the target machine will now contain the .NET base class libraries, .NET
runtime ( mscoree.dll), and additional .NET infrastructure (such as the GAC).

Ravikiran
22 CHAPTER 1. PHILOSOPHY OF .NET

.NET Namespace Contents of Namespace


System Within System we can find numerous useful types
dealing with built in data, mathematical computations,
random number generation, environment ariables,
and garbage collection, as well as a number of commonly used
exceptions and attributes.
System.Collections These namespaces define a number of stock container
System.Collections.Generic objects (ArrayList, Queue, and so forth), as well as base types
and interfaces that allow you to build customized collections.
As of .NET 2.0, the collection types have been extended
with generic capabilities .
System.Windows.Forms This namespace contains types that facilitate the construction of
traditional desktop GUI applications.
System.Data These namespaces are used for interacting with databases using
System.Data.Odbc ADO .NET.
System.Data.OracleClient
System.Data.OleDb
System.Data.SqlClient
System.Diagnostics Here, you find numerous types that can be used to
programmatically debug and trace your source code.
System.Drawing Here, you find numerous types wrapping graphical primitives
System.Drawing.Drawing2D such as bitmaps , fonts , and icons , as w ell as printing capabilities.
System.Drawing.Printing
System.IO These namespaces include file I/O, buffering, and so forth. As of
System.IO.Compression .NET 2.0, the IOnamespaces now include support compression
System.IO.Ports and port manipulation.
System.Net This namespace (as well as other related namespaces) contains types
related to network programming (requests/responses, sockets, end points,
and so on).
System.Reflection These namespaces define types that support runtime type
System.Reflection.Emit discovery as well as dynamic creation of types.
System.Runtime. This namespace provides facilities to allow .NET types to interact
InteropServices with ”unmanaged code” (e.g., C-based DLLs and COM servers)
and vice versa.
System.Runtime.Remoting This namespace (among others) defines types used to build
solutions that incorporate the .NET remoting layer.
System.Security Security is an integr ated aspect of the .NET universe.
In the security-centric namespaces y ou find numerous types
dealing with permissions, cryptography, and so on.
System.Threading This namespace defines types used to build multithreaded applications.

Table 1.2: Built-in Namespaces in .NET Framework

Ravikiran
Chapter 2

Building C# Applications

2.1 C# Command Line Compiler

There are a number of techniques to compile C# source code. Most of the .NET programmers
use Visual Studio in order to create .NET assemblies. Apart from visual studio, we can also use
C# command-line compiler - csc.exe tool (where csc stands for C-Sharp Compiler). This tool is
included with the .NET Framework 2.0 SDK. But using csc.exe alone is very difficult to build a
large-scale application however it is important to understand the basics of how to compile *.cs
files.

2.1.1 Configuring the C# Command-Line Compiler


Before using the csc.exe tool, we need to ensure that your development machine recognizes the
existence of csc.exe. If our machine is not configured correctly, we are forced to specify the full
path to the directory containing csc.exe.
In order to specify the full of csc.exe, follow the following steps

1. Right-click the My Computer icon and select Properties from the pop-up menu.

2. Select the Advanced tab and click the Environment Variables button.

3. Double-click the Path variable from the System Variables list box.

4. Add the following line to the end of the current Path value (note each value in the Path
variable is separated by a semicolon):
C:/Windows/Microsoft.NET/Framework/v2.0.50215

2.1.2 Configuring Additional .NET Command-Line Tools


The other command line tools that are commonly used during .NET development are located in
the following directory

23
24 CHAPTER 2. BUILDING C# APPLICATIONS

C:/Program Files/Microsoft Visual Studio 8/SDK/v2.0/Bin


With these two paths established, we should now be able to run any .NET utility from any
command window.

2.2 Building C# Applications using csc.exe


Once the path of csc.exe is set, the next goal is to write a simple C# application. Open any text
editor and enter the following

using System;
class TestApp
{
public static void Main() {
Console.WriteLine(”Testing! 1, 2, 3”); }
}

Save the above program in a convenient location (e.g, C:/CscExample) as TestApp.cs. Before
compiling the above program, we have to know the different options of C# compiler. The
following are the some of the options of C# Compiler. To compile TestApp.csinto a console

Option Purpose
/out This option is used to specify the name of the assembly to be
created. By default, the assembly name is the same as the name of the initial
input *.cs file (in the case of a *.dll) or the name of the type containing the
programs Main()method (in the case of an *.exe).
/target:exe This option builds an executable console application. This is the
default file output type, and thus may be omitted when building
this application type.
/target:library This option builds a single-file *.dllassembly.
/target:module This option builds a module. Modules are elements of multifile assemblies
/target:winexe Although you ar e free to build Windows-based applications
using the /target:exe flag, the /target:winexeflag
prevents a console window from appearing in the background.

Table 2.1: Output-centric Options of the C# Compiler

application named TestApp.exe, change to the dir ectory containing your source code file and
enter the following command

csc /target:exe TestApp.cs

Ravikiran
2.3. CSC.EXE RESPONSE FILES 25

When we compile the C# program, we can get the exe file of the compiled program having the
same name of the file that is compiled.
After compiling the TestApp.cs file, we will get TestApp.exe file and it can be executed by typing
its file name

C:/i TestApp.exe
Testing! 1,2,3

2.2.1 Referencing External Assemblies


If our C# application refers to the external assemblies, then our application should be compiled
with csc.exe by specifying the ”/r:” option.
For example...

using System;
using System.Windows.Forms;
class ExternalAssemblyDemo
{
public static void Main(string[] args)
{
MessageBox.Show(”Hello...”);
}
}

Notice the reference to the System.Windows.Formsnamespace via the C# ’using’ keyword. So


at the command prompt while compiling the above program we have to specify the ”/r:” option.

C:/i csc /r: ExternalAssemblyDemo.cs

if you need to reference numerous external assemblies using c sc.exe, then we have to simply list
each assembly using a semicolon-delimited list.
For example
csc /r:System.Windows.Forms.dll;System.Drawing.dll *.cs

2.3 csc.exe Response Files


If we are refering so many external assemblies, then we have to specify a lengthy options for the
csc.exe tool. So to reduce he burden of typing long command line options, the C# command
line compiler supports response files. Response files are nothing but text files which contain
command line arguments to be feed to the compiler. Response files can save time and avoid
typing errors. Response files end with the .rsp file extension.

Ravikiran
26 CHAPTER 2. BUILDING C# APPLICATIONS

For example, create the following text file named commandLine01.rsp:


/r: MainAsm.dll
/r: SecondAsm.dll
/t: winexe
/out: MainAppl.exe *.cs
# Response file comment.

Then, replace the lengthy command line switches with the name of the relevent response file for
the current compilation using the @ symbol:

csc @commandLine01.rsp

2.3.1 The Default Response File(csc.rsp)


The C# compiler is defaultly associated with one response file having the name csc.rsp, which
is located in the same directory where csc.exe is located. In this default response file contains
numerous .NET assemblies are specified using the /r: flag.
When we are building C# program using csc.exe, this file will be automatically referenced even
when we supply our own response file. So even though if we are referring built in assemblies,
there is no need to specify them explicitly by /r: flag.
But, if we want to disable the automatic reading of csc.rsp we can specify the /noconfig option
during the compile time.
For example...

csc @commandLine01.rsp /noconfig

2.4 Generating Bug Reports


The raw C# compiler provides a helpful flag named /bugreport. This flag will allows you to
specify a file that will be populated (by csc.exe) with various statistics regarding our current
build including any errors encountered during the compilation process.

csc /bugreport:bugs.txt *.cs

When we specify /bugreport, we will be prompted to enter correct information for the pos-
sible error(s) at hand, which will be saved (along with other details) into the file you specify.
For Example...

using System;
class DebugClass
{ static void Main(string[] args)

Ravikiran
2.4. GENERATING BUG REPORTS 27

{
Console.WriteLine(”Hai”);
Console.Readey(); //Compile Time Error
}
}

In the above example, we have one error in the line 7. I have written Console.Readey() insetead
of Console.ReadKey(). So, when we compile the above program as ...

csc /bugreport:BugFile.txt DebugClass.cs

then will be prompted to enter corrective action for the error at hand. All This information is
stored in file that is specified with the /bugreport flag (here it is BugFile.txt)

Ravikiran
28 CHAPTER 2. BUILDING C# APPLICATIONS

2.5 Remaining C# Compiler Options


C# compiler has many other flags that can be used to control how the resulting .NET assembly
is to be generated. Some of those flags are listed below...

Command Line Purpose


Flag of csc.exe
@ Allows you to specify a response file used during compilation
/help or /? Prints out the list of all command line flags of csc.exe
/addmodule Used to specify the modules to add to a multifile assembly
/baseaddress Used to specify the preferred base address at which to load a *.dll
/bugreport Used to build text-based bug reports for the current compilation
/checked Used to specify whether integer arithmetic that overflows the bounds
of the data type will cause an exception at run time
/codepage Used to specify the codepage to use for all
source code files in the compilation
/debug Forces csc.exe to emit debugging information
/define Used to Define pre processor symbols
/doc Used to construct an XML Documentation
/filealign Specifies the size of sections in the output file
/fullpaths Specifies the absolute path to the file in the Compiler output
/lib Specifies the location of assemblies referenced
/ Specifies which Main() method to use as the program’s entry point,
if multiple Main() methods have been defined
in the current *.cs file set
/nolog Suppresses compiler banner information when compiling the file
/noconfig Prevents the use of *.rsp files during the current compilation
/nowarn Suppress the compiler’s ability to generate specified warnings
/out Specifies the output file
/recurse Searches the subdirectories for source files to compile
/target Specifies the format of the output file
/warnaserror Used to automatically promote warnings to errors
/unsafe Compiles code that uses the C# ”unsafe” keyword

Table 2.2: C# Command Line Compiler Options

Ravikiran
2.6. THE COMMAND LINE DEBUGGER (CORDBG.EXE) 29

2.6 The Command Line Debugger (cordbg.exe)


Cordbg.exe is a tool that provides many options that allow us to run our .NET assemblies under
debug mode. We can view all these options by typing
cordbg -?

Command Line Flag Purpose


of cordbg.exe
b[reak] set or display current break points
del[ete] Removes one or more break points
ex[i] Exit the debugger
g[0] Contiune the process of debugging until the next breakpoint
si Step into the next line
o[ut] Step out of the current function
so Step over the next line
p[rint] Print all loaded variables.

Table 2.3: cordbg.exe flags

2.6.1 Debugging at Command Line


For example when we compile the DebugClass.cs

csc DebugClass.cs /debug

and if there are no any compilation errors, the csc.exe tool will generates the DebugClass.pdb
(pdb stands for Program Debug Database), DebugClass.exe files
Once you have a valid *.pdb file, we can open a session with cordbg.exe by specifying your
.NET assembly(here DebugClass.exe) as a command line argument (the *.pdb file will be loaded
automatically): cordbg.exe testapp.exe

cordbg DebugClass.exe

At this point, you are in debugging mode, and may apply any number of cordbg.exe flags at the
”(cordbg)” command prompt
When we finished debugging our application we can exit debugging mode by simply typing exit
or just ex

2.7 Using Visual Studio - .NET IDE


Visual Studio allows you to build applications using any number of .NET-aware (and unaware)
languages. Thus, you are able to use VS .NET when building C#, J#, VB.NET, MFC etc...
The following are the some of the Key Elements of VS.NET

Ravikiran
30 CHAPTER 2. BUILDING C# APPLICATIONS

2.7.1 The VS.NET Start Page


By default, the first thing you see when you launch Visual Studio .NET is the Start Page. In
this start page we will be having different options like

1. Links to open recent projects

2. Tips to get how to start (Getting Started)

3. Visual Studio Head lines

4. Visual Studio Developer News (requires internet connection)

Figure 2.1: Visual Studio.NET 2005 Start page

2.7.2 Creating VS.NET Project Solution


Once Visual studio is opened, our next step is to either open recent project by clicking the
required link shown on the start up page or to create a new project solution. Steps involved
while creating new project

1. Click create project link from the start page or by choosing File — New — Project
Menu selection

2. Next, New project Dialog will be appeared which allows us to choose different Project
Types and Templates under the selected Project type.

Ravikiran
2.7. USING VISUAL STUDIO - .NET IDE 31

3. After selecting the appropriate project type and template, specify the name of the project,
location of project and also name of the solution in the corresponding texfields located at
the bottom of New Project Dialog and then click ok button

Figure 2.2: New Project Dialog of VS.NET

Ravikiran
32 CHAPTER 2. BUILDING C# APPLICATIONS

Project Type Purpose


Windows This project type represents a Windows Forms application.
Application
Class Library This option allows you to build a single file assembly (*.dll). Windows
Windows Control This type of project allows you to build a single file assembly (*.dll)
Library that contains custom Windows Forms Controls
ASP.NET Web Select this option when you want to build an ASP.NET Web application.
Application
ASP.NET Web This option allows us to build .NET web service
service web service is block of code, reachable using HTTP requests
Web Control VS .NET also allows you to build customized Web controls. These GUI
Library widgets are responsible for emitting HTML to a requesting browser.
Console Used to develop Console Application i.e. to create command window
Application
Window .NET allows you to build NT/2000 services. As you may know, these are
Services background worker applications that are launched during the OS boot process.

Table 2.4: Different Project Types available in VS.NET

2.8 Building VS.NET Test Application


Once we have given all the details like project name, project location and after pressing the ok
button, a new folder will be created that contains number of starter files and project subdirec-
tories.
Generated Item Purpose
/bin /Debug This folder contains the debug version of our compiled
.NET assembly. If we configure a release build, a new folder (/bin /Release )
will be generated that contains a copy of our assembly.
/obj /* Under this folder there are numerous sub folders used by the VS.NET
during compilation process.
App.ico An *.ico file used to specify the icon for the current program
AssemblyInfo.cs This file allows us to establish assembly-level attributes for
for our current project.
Class1.cs This is our initial class file
*.csproj This file represents a C# project that is loaded into a given solution
*.sln This file represents the current VS.NET solution

2.8.1 Examining the solution explorer window


Solution Explorer allows you to view items and perform item management tasks in a solution or
a project. It also allows you to use the Visual Studio editors to work on files outside the context
of a solution or project.
The management of items displayed in Solution Explorer is based on an item’s relationship with
project and solution containers. Items can be related in the following ways:

Ravikiran
2.8. BUILDING VS.NET TEST APPLICATION 33

1. As project items, which appear under a project folder in Solution Explorer, for example,
forms, source files, and classes.

2. As solution items, which appear in the Solution Items folder of Solution Explorer.

3. As miscellaneous files, which are files that are not associated with either a project or a
solution and are displayed in the Miscellaneous Files folder.

Figure 2.3: VS.NET Solution explorer

2.8.2 Examining Class View


Class View displays the symbols defined, referenced, or called in the application we are devel-
oping. We can use Class View to open files and navigate directly to the lines where symbols
appear. Class view tab shows object oriented view of our project.

Figure 2.4: VS.NET Class View

Ravikiran
34 CHAPTER 2. BUILDING C# APPLICATIONS

2.9 VS.NET Solution Properties


In the solution explorer window, right click on the name of the project and select properties.
This launches the all-important Project Property Page.

Figure 2.5: Project Properties

The box provides a number of settings, which map to various flags of the command line compiler.
To begin, when we select the Application tab, we are able to configure the type of output file
that should be produced by csc.exe.
You are also able to configure which item in your application should be marked as the ”Startup
object” (meaning, the class in the application that contains the Main() method). Finally, we can
also allows you to configure the ’default’ namespace for this particular project.

Ravikiran
2.10. OTHER KEY ASPECTS OF VS.NET IDE 35

2.9.1 Properties Window

Figure 2.6: Project Properties

Another important aspect of the IDE is the Properties window. This window allows you to
interact with a number of characteristics for the item that has the current focus. This item may
be an open source code file, a GUI widget, or the project itself.

2.10 Other Key Aspects of VS.NET IDE


2.10.1 Server Explorer Window

Figure 2.7: Sever Explorer Window

The Server Explorer is a new development tool in Visual Studio .NET or in Visual Studio 2005
that is shared across development languages and projects. With the Server Explorer, you can
connect to servers, as well as view and access their resources. For example, you can connect to,
view and access the following resources:

1. Database Connections

Ravikiran
36 CHAPTER 2. BUILDING C# APPLICATIONS

2. Servers

3. Crystal Reports

4. Event logs

5. Message Queues

6. Performance Counters

7. Window Services

2.10.2 XML-Related editing tools


XML is everywhere from XML Web Services to databases to config files to Office documents.
Visual Studio .NET also provides numerous XML-related editors. When you open a file with an
XML extension in Visual Studio, you will invoke its XML Editor. XML Editor comes with a full
range of features you would expect from a Visual Studio editor, which includes IntelliSense, color-
coding, brace matching, outlining, and formatting. It provides full XML 1.0 syntax checking,
end-tag completion, as well as DTD and XML schema support with real-time validation.

2.10.3 Object Browser Utility


The Object Browser allows you to select and examine the symbols available for use in projects.
You can open the Object Browser from the View menu, or by clicking the Object Browser button
on the main toolbar. There are three panes: an Objects pane on the left, a Members pane on
the upper right, and a Description pane on the lower right.
In the Objects pane, icons identify hierarchical structures such as .NET Framework and COM
components, namespaces, type libraries, interfaces, enums, and classes. You can expand these
structures to reveal ordered lists of their members. Properties, methods, events, variables, con-
stants, and other contained items are listed in the Members pane. Details on the item selected
in the Objects or Members pane appear in the Description pane.

Ravikiran
2.11. C# LANGUAGE’S PREPROCESSOR DIRECTIVES 37

Figure 2.8: Sever Explorer Window

2.10.4 Database Manipulation in Visual Studio


Integrated database support is also part of the VS .NET IDE. Using the Server Explorer window,
you can open and examine any database object from IDE.

2.11 C# language’s preprocessor directives


C# preprocessor is fundamentally very similar to C preprocessor and the whole concept in C#
has been taken from C language specification.
C# preprocessor is fundamentally very similar to C preprocessor and the whole concept in C#
has been taken from C language specification.
A preprocessor directive must be the only instruction on a line. Preprocessing directives are lines
in your program that start with ’#’. Whitespace is allowed before and after the ’#’. The ’#’ is
followed by an identifier that is the directive name. For example, ’#define’ is the directive The
C# language’s preprocessor directives are as follows

1. #if : #if lets us begin a conditional directive, testing a symbol or symbols to see if they
evaluate to true. If they do evaluate to true, the compiler evaluates all the code between
the #if and the next directive.
#if symbol (operator symbol)
where:

Ravikiran
38 CHAPTER 2. BUILDING C# APPLICATIONS

symbol
The name of the symbol we want to test. we can also use true and false. symbol can be
prefaced with the negation operator. For example, !true will evaluate to false.
operator (optional) You can use the following operators to evaluate multiple symbols:

== (equality)
!= (inequality)
&& (and)
—— (or)
You can group symbols and operators with parentheses. #if, along with the #else, #elif,
#endif, #define, and #undef directives, lets us to include or exclude code based on the
condition of one or more symbols. This can be most useful when compiling code for a
debug build or when compiling for a specific configuration.

A conditional directive beginning with a #if directive must explicitly be terminated with
a #endif directive.

2. #else : #else lets you create a compound conditional directive, such that, if none of the
expressions in the preceding #if or (optional) #elif directives did not evaluate to true, the
compiler will evaluate all code between #else and the subsequent #endif.

3. #elif

4. #endif

5. #define : #define lets you define a symbol, such that, by using the symbol as the expres-
sion passed to the #if directive, the expression will evaluate to true.

6. #undef : #undef lets you undefine a symbol, such that, by using the symbol as the
expression in a #if directive, the expression will evaluate to false.

7. #warning : #warning lets you generate warning from a specific location in your code
where text is the text of the warning that should appear in the compiler’s output.

8. #error : #error lets you generate an error from a specific location in your code where
text is the text of the warning that should appear in the compiler’s output.

9. #line : #line lets you modify the compiler’s line number and (optionally) the file name
output for errors and warnings
#line [ number [”filename”] — hidden — default ]
where number is the number we want to specify for the following line in a source code file.
”filename” (optional) The file name we want to appear in the compiler output. By default,
the actual name of the source code file is used. The file name must be in double quotation

Ravikiran
2.11. C# LANGUAGE’S PREPROCESSOR DIRECTIVES 39

marks (” ”).
hidden - Hides the successive lines from the debugger until another #line directive is en-
countered.
default - Resets the line numbering in a file.

10. #region #region lets you specify a block of code that we can expand or collapse when
using the outlining feature of the Visual Studio Code Editor.

11. #endregion A #region block must be terminated with a #endregion directive.

Main use of directives are

• Conditional compilation - Using special preprocessing directives, we can include or


exclude parts of the program according to various conditions.

• Line control - If we use a program to combine or rearrange source files into an interme-
diate file, which is then compiled, you can use line control to inform the compiler of where
each source line originally came from.

• Error and Warning reporting - The directive ’#error’ causes the preprocessor to
report a fatal error and the directive ’#warning’ is like the directive ’#error’, but causes
the preprocessor to issue a warning and continue preprocessing.

There are two method to define directive

• Define in your C# program.

• Define them at command line on compile time.

Here is example for first way

#define TEST
using System;
public class MyClass
{
public static void Main()
{
#if (TEST)
Console.WriteLine(”TEST is defined”);
#else
Console.WriteLine(”TEST is not defined”);
#endif
}
}

Ravikiran
40 CHAPTER 2. BUILDING C# APPLICATIONS

output
TEST is defined In other way you can define it at command line. So program will be like this
Example

using System;
public class MyClass
{
public static void Main()
{
#if (TEST)
Console.WriteLine(”TEST is defined”);
#else
Console.WriteLine(”TEST is not defined”);
#endif
}
}

At compile time user can define as below

csc /define:TEST MyClass.cs

Output

TEST is defined

2.12 System Environment Class


System.Environment class provides information about, and means to manipulate, the current
environment and platform. This class cannot be inherited. ome of the static members of this
class are as follows:

• Environment.OSVersion - Gets the version of the operating system

• Environment.GetLogicalDrives() - method that returns the drives

• Environment.Version - returns the .NET version running the application

• Environment.MachineName - Gets name of the current machine

• Environment.Newline - Gets the newline symbol for the environment

• Environment.ProcessorCount - returns number of processors on current machine

• Environment.SystemDirectory - returns complete path to the System Directory

Ravikiran
2.12. SYSTEM ENVIRONMENT CLASS 41

• Environment.UserName - returns name of the entity that invoked the application

• Environment.HasShutdownStarted -Ture if system is going to shut down

Ravikiran
42 CHAPTER 2. BUILDING C# APPLICATIONS

Ravikiran
Chapter 3

C# Language Fundamentals

3.1 Anatomy of C# Class


A class declaration in C# is composed of attributes, modifiers, the class name, base class and
interfaces, and a body. Attributes, modifiers, and bases are all optional.
The body of the class contains class members that can include constants, fields (or variables),
methods, properties, indexers, events, operators, and nested types. Nested types are defined by
class, interface, delegate, struct, or enum declarations within the class body.

3.1.1 Attributes
Attributes allows us to add custom information to the metadata for a class. It contains informa-
tion about a class such as its name, its fields, and its methods, including their parameters and
types. Metadata is essential to enable the .NET run time to load and use a class. The .NET run
time reads the metadata through a process known as reflection. We can use reflection to access
your own custom class metadata.

3.1.2 Modifiers
Modifiers allow us to control access to the class and to restrict the ability of the class to be
instantiated or to serve as the base of another class. The class modifiers are public, protected,
internal, private, abstract, sealed, and new. Using these modifiers, the following access levels
can be specified:

• public Access is unrestricted

• protected Access is restricted to the containing class or to classes derived from it.

• internal Access is restricted to the containing assembly (program).

43
44 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

• protected internal Allow protected or internal access. You can also specify this access
level as internal protected

• private Access is restricted to the containing class

• abstract The abstract modifier indicates that a class is incomplete and must be extended
by a derived class in order to be instantiated.

• sealed A sealed class can not be extended i.e. it cannot serve as a base class for another
class.

• new The new modifier may be applied only to a nested class or other class member, to
indicate that it hides an inherited member of the same name. Hiding isnt necessarily an
error, but the compiler will issue a warning. You can attach the new modifier to the nested
class to tell the compiler that we are aware of the situation and that everything is okay

Example

using system;
public class ClassAnatomy
{
int i;
ClassAnatomy()
{
i=10;
}
static void Main(string[] args)
{
ClassAnatomy ca=new ClassAnatomy();
Console.WritLine(ca.i);
}
}

3.1.3 Main Method


Like in C or C++, the execution of C# program begins with Main method. In C#, we are
having four overloaded forms of Main method.
When a program starts, it looks for an entry point. This is the role of the Main() method. In
fact, a program, that is an executable program, starts by, and stops with, the Main() method
They are...

• public static void Main(){} //No Return Type and No Arguments

• public static void Main(string[] args){}//No Return Type and String argument

• public static int Main(){} //Integer Return type and No Arguments

Ravikiran
3.2. CONSTRUCTORS 45

• public static int Main(string[] args){} Integer Return type and string argument

Processing Command Line Arguments

There are two common ways to read command line arguments in C#. First, you can override
the Main method with an array of strings, which are command line arguments. For example,
the following code loops through the command line arguments and print them on the console.

static void Main(string[] args)


{ foreach(string arg in args)
{
Console.WriteLine(arg);
}
Console.ReadLine();
}

However, this is not only the way to read command line arguments. For example, if you do
not want to override the Main method? Or access the command line arguments from non-Main
method of your application, we have to use Environment Class, which has a static method
called GetCommandLineArgs, which returns an array of strings containing the arguments. The
following code reads the command line arguments using Environment.GetCommandLineArgs
method.

foreach (string arg in Environment.GetCommandLineArgs())


{
Console.WriteLine(arg);
}

Specifying Command-Line Arguments in Visual Studio

In Visual Studio, double-click the Properties icon from Solution Explorer and select the Debug
tab on the left side. From here, specify values using the ”Command line arguments” text box

3.2 Constructors
A constructor is a member that implements the actions required to initialize an instance of a
class. Broadly speaking, it is a method in the class which gets executed when its object is created
i.e. a constructor is invoked when you use the ”new” operator.
Constructors are used for initializing the members of a class whenever an object is created with
the default values for initialization. If a class is not defined with the constructor then the CLR
(Common Language Runtime) will provide an implicit constructor which is called as Default
Constructor. A class can have any number of constructors provided they vary with the number
of arguments that are passed, which is they should have different signatures.

Ravikiran
46 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

Figure 3.1: Passing Command line arguments in Visual Studio

• Constructors do not return a value

• Constructors can be overloaded except static constructors

• Constructors will be having the same name as that of its containing class

• Constructor cant be get inherited

• A class has atleast one constructor also known as default constructor [a constructor without
parameter]

3.2.1 Types of Constructors


In C#, we are having the following different types of constructors...

• Default Constructor A constructor that takes no parameters is called a default con-


structor. Default constructors are invoked whenever an object is instantiated by using the
new operator and no arguments are provided to new.

• Parameterized Constructors At times, we will require initializing class members during


instantiation and this is the time where parameterized constructor will come into picture.
It follows the same rules as default constructor and will have parameters.
Note A default constructor should be explicitly declared while declaring parameterized
constructor.

Ravikiran
3.2. CONSTRUCTORS 47

• Static Constructors A static constructor is used to initialize any static data, or to


perform a particular action that needs performed once only. It is called automatically
before the first instance is created or any static members are referenced. Static constructors
will have following properties...

1. A static constructor does not take access modifiers or have parameters


2. A static constructor is called automatically to initialize the class before the first in-
stance is created or any static members are referenced.
3. A static constructor cannot be called directly
4. The user has no control on when the static constructor is executed in the program.

• Private Constructors A private constructor is a special instance constructor. It is com-


monly used in classes that contain static members only. If a class has one or more private
constructors and no public constructors, then other classes (except nested classes) are not
allowed to create instances of this class. Private constructors are used to prevent the cre-
ation of instances of a class when there are no instance fields or methods, such as the Math
class.
Example

public class CounterClass


{
private CounterClass() { }
public static int i;
public static int IncrementCount()
{
return ++i;
}
}
class CounterClass
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error

CounterClass.i = 100;
CounterClass.IncrementCount();
System.Console.WriteLine(”Current Value: {0 }”, CounterClass.i);
}
}

Ravikiran
48 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

3.3 System.Console
Represents the standard input, output, and error streams for console applications. This class
cannot be inherited. As its name implies, the Console class encapsulates input, output, and
error stream manipulations for console-based applications. The console is an operating system
window where users interact with the operating system or a text-based console application by
entering text input through the computer keyboard, and reading text output from the computer
terminal. Some of the properties of Console are...

Console Member Purpose


BackgroundColor These properties set the background/foreground colors for the
ForegroundColor current output. They can be assigned any member of the
ConsoleColor enumeration
BufferWidth These properties control the height/width of the consoles buffer area.
BufferHeight
Clear() This method clears the buffer and console display area
WindowHeight These properties control the dimensions of the console in
relation to WindowWidth the established buffer.
WindowTop
WindowLeft
Title Gets or sets the title to display in the console title bar.
CursorVisible Gets or sets a value indicating whether the cursor is visible.

3.3.1 Basic Input and Output with the Console Class


When a console application starts, the operating system automatically associates three I/O
streams with the console. Our application can read user input from the standard input stream;
write normal data to the standard output stream; and write error data to the standard error
output stream. These streams are presented to our application as the values of the In, Out, and
Error properties Console class defines a set of methods to capture input and output. All these
methods are static methods and hence we can directly call these methods at class level.

Console Member Purpose


Read Reads the next character from the standard input stream.
ReadKey Obtains the next character or function key pressed by the user.
ReadLine Reads the next line of characters from the standard input stream.
Write Writes the text representation of the specified value or values to
the standard output stream
WriteLine Writes the specified data, followed by the current line terminator,
to the standard output stream

Table 3.1: Console Class Properties that support Read and write operations

Ravikiran
3.3. SYSTEM.CONSOLE 49

using System;
using System.Collections.Generic;
using System.Text;
namespace Environment
{
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WindowWidth = 50;
Console.Title = ”Ravi kiran Console”;
Console.WriteLine(”Ravi kiran”);
Console.BackgroundColor = ConsoleColor.DarkGray;
Console.WriteLine(”Press any key to get beep sound”);
Console.ReadKey();
Console.Beep();
Console.BufferWidth = 100;
Console.WriteLine(”Press any key to clear the screen”);
Console.ReadKey();
Console.Clear();
Console.WriteLine(”Press any key to reset the screen color”);
Console.ReadKey();
Console.ResetColor();

}
}
}

3.3.2 Formatting Console output


.NET introduces a new style of string formatting which is similar to the ’C’ language printf
statement. For example...

static void Main(string[] args)


{
int age=28;
string name=”Ravi kiran”;
Console.WriteLine(”I am {0}, having age {1}”,name,age);
}

The first parameter to WriteLine() represents a string literal that contains optional placeholders
designated by {0}, {1}, {2}, and so forth (curly bracket numbering always begins with zero).

Ravikiran
50 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

The remaining parameters to WriteLine() are simply the values to be inserted into the respective
placeholders. It is also permissible for a given placeholder to repeat within a given string. For
example,

Console.WriteLine(”{0} is simple. {0} is like C++ ”,”.NET”);

The above statement prints ” .NET is simple. .NET is like C++ If we require more elaborate
formatting, each placeholder can optionally contain various format characters either in upper
case or lower case.

3.3.3 Formatting Numbers

Specifier type format output output


(double 1.2345) (int -12345)
C or c Currency {0:c} $ 1.23 $ 12,345.00
D or d decimal {0:d} System.FormatException -12345
(whole number)
E or e exponent /scientific {0:e} 1.234500e+000 -1.234500e+004
F or f fixed point {0:f} 1.23 -12345.00
G or g general {0:g} 1.2345 -12345
N or n number {0:n} 1.23 -12,345.00
R or r round trippable {0:r} 1.23 System.FormatException
X or x hexadecimal {0:x4} System.FormatException ffffcfc7

3.3.4 Custom Number Formatting

Specifier type format output


(double 1234.56)
0 zero placeholder {0:00.000} 1234.560
# digit placeholder {0:#.##} 1234.56
. decimal point placeholder {0:0.0} 1234.6
, thousand separator {0:0,0} 1,235
% percentage {0:0%} 123456%

Ravikiran
3.3. SYSTEM.CONSOLE 51

3.3.5 Date Formatting

Specifier type output


(June 8, 1970 12:30:59)
d Short Date 08/06 /1970
D Long Date 08 June 1970
t Short Time 12:30
T Long Time 12:30:59
f Full date and time 08 June 1970 12:30
F Full date and time (long) 08 June 1970 12:30:59
g Default date and time 08 /06 /1970 12:30
G Default date and time (long) 08 /06 /1970 12:30:59
M Day /Month 8 June
Y Month /Year June 1970

3.3.6 Custom Date Formatting

Specifier type output


(June 8, 1970 12:30:59)
dd Day 08
ddd Short Day Name Mon
dddd Full Day Name Monday
hh 2 digit hour 12
HH 2 digit hour (24 hour) 12
mm 2 digit minute 30
MM Month 06
MMM Short Month name Jun
MMMM Month name June
ss seconds 59
tt AM /PM PM
yy 2 digit year 70
yyyy 4 digit year 1970
: seperator, e.g. 0:hh:mm:ss 12:30:59
/ seperator, e.g. 0:dd /MM /yyyy 08 /06 /1970

Ravikiran
52 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

3.4 Default values for variables


The following table shows the default values of value types returned by the default constructors.
Default constructors are invoked by using the new operator. All the value types that are declared

Value Type Default Value


bool false
byte 0
char ’\0’
decimal 0.0M
double 0.0D
float 0.0F
int 0
long 0L
sbyte 0
short 0
ulong 0
ushort 0

in the class are initialized to their default values, whereas all other reference types are initialized
to null.

3.5 Variable Scope


The scope of a variable determines its visibility to the rest of a program.
When we declare a variable in any method, this means that the variable is available to use within
the method but when control passes to another method the variable becomes unavailable.
There are other possibilities for a variable’s scope. For example, a variable can be declared within
a loop or other code structure and then be only visible to the code within the structure. A wider
scoped variable could be declared at class-level so that it can be used by any method within the
class. In fact, a variable’s scope is always the full extent of the code block, delimited by braces
{}, that it is declared within.

1. Class-Level Scope Variables that are defined at the class level become available to any
non-static method within the class.

2. Method-Level Scope Variables declared within the main code block of a method are
available for use by any other part of the method, including nested code blocks

3. Nested Scope Variables declared within a nested scope are not available to those outside
of their code block

Ravikiran
3.6. MEMBER VARIABLE INITIALIZATION 53

3.6 Member Variable Initialization


Class tends to have member variables. Normally in order to initialize these variables, we will use
constructors. A class can contain more than one one constructor (overloaded constructors), and
in each constructor we have to write same initialization code. This is particularly necessary if we
do not wish to accept the default values assigned to class members. For example, if an integer
variable in our class should always begins with default value of ”13” then we could write

class MemberInitializationDemo
{
int i;
string name;
MemberInitializationDemo()
{
i=9;
}
MemberInitializationDemo(string val)
{
i=9;
name=””;
}
static void Main(string[] args)
{
MemberInitializationDemo m1,m2;
m1=new MemberInitializationDemo();
m2=new MemberInitializationDemo(”Ravi kiran”);
}
}

The main method in the above example contains two objects (m1 and m2) for the class ”Mem-
berInitializationDemo”. When memory is alloted for the object m1, m1.i will be having value
of 9 and m1.name will be having value of empty string where as for m2, m2.i will also hold the
value of 9 but m2.name contains ”Ravi kiran”.

3.7 Value Types and Reference Types


3.7.1 Value Types
C# provides a set of different data types. The data types in C# are divided into two categories
Value Types and Reference Types. A variable that is a value type, stores the data, while a
variable of a reference type stores a reference to the data. Variable that are based on value types
directly contain a values. Assigning one value type variable to another copies the contained

Ravikiran
54 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

value. All value types are derived implicitly from the System.ValueType.
The value types consist of two main categories:

1. Structs Structs fall into these categories

• Numeric types
– Integral Types
– Floating-Point types
– Decimal
• bool
• User defined structs

2. Enumerations

3.7.2 Reference Types


Variables of reference types, referred to as objects, store references to the actual data. When
an assignment occurs between reference variables, only the reference is copied i.e actual value
remains the same in memory and there are now two references to the same memory location
Reference Type variables are allocated on the Managed Heap. CLR manages the Heap memory
for reference type. Memory allocation for an object should be done by using the ”new” keyword.
Objects are allocated onto the managed heap, where they are automatically deallocated by the
runtime at ”Some time in the future”. Garbage collection is automated in C#. If the Managed
heap does not have sufficient memory to allocate a requested object, a garbage collection will
occur.
All class objects, interface objects and delegates are reference type variables.
The following program demonstrates the Value and Refernce Types

using System;
class ValueAndRefernceTypes
{
int i;
static void Main(string[] args)
{
int temp=10;
ValueAndRefernceTypes v=new ValueAndRefernceTypes();

//Assigning Value Type to a value type i.e. value is copied


//from one variable to another variable

int temp1=temp;

Ravikiran
3.8. BOXING AND UNBOXING 55

//Assigning Reference Type to a Reference type. Here, only


//reference is copied from one variable to another variable
//i.e Variables (v1 and v2) will be pointing to same memory location

ValueAndRefernceTypes v1=v;

temp1=50;
v1.i=100;
Console.WriteLine(”Temp value is {0}”,temp);
Console.WriteLine(”Temp1 value is {0}”,temp1);

Console.WriteLine(”Temp value is {0}”,v.i);


Console.WriteLine(”Temp value is {0}”,v1.i);

}
}

3.8 Boxing and Unboxing


Boxing and unboxing is a essential concept in .NET. With Boxing and unboxing one can link
between value-types and reference-types by allowing any value of a value-type to be converted
to and from type object

3.8.1 Boxing
Converting a value type to reference type is called Boxing. When the CLR boxes a value type,
it wraps the value inside a System.Object and stores it on the managed heap.In the following
example, the integer variable i is boxed and assigned to object o.

int i=10;
object o = (object) i; //boxing

Boxing is used to store value types in the garbage-collected heap. Boxing is an implicit conversion
of a value type to the type object or to any interface type implemented by this value type. Boxing
a value type allocates an object instance on the heap and copies the value into the new object.
The following statement implicitly applies boxing operation on variable i

int i=10;
object o = i; //implicit boxing

Ravikiran
56 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

3.8.2 UnBoxing
Unboxing is the opposite operation to boxing. An unboxing conversion permits an explicit
conversion from reference type to any value-type. An unboxing operation consists of
1. Checking the object instance to make sure it is a boxed value of the given value type

2. Copying the value from the instance into the value-type variable
When an object box is cast back to its original value type, the value is copied out of the box and
into the appropriate storage location

Example for Boxing and Unboxing


using System;
class Program
{
struct Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
static void Main(string[] args)
{
Point p = new Point(10, 20);
object o = p;
Console.WriteLine(((Point)o).x);
Point p1 = (Point)o;
Console.WriteLine(p1.x);
}
}

3.9 System.Object
In C# the Object class is the ultimate base class of every type that all other other types directly
or indirectly derive from it. the object classThe Object class provides a number of methods that
can be called on all objects
1. Equals The Equals method of the object class provides a default implementation that
compares two reference type objects for reference equality. Reference equality occurs when
two reference type objects refer to the same object.

Ravikiran
3.9. SYSTEM.OBJECT 57

using System;
class Program
{
int i;
Program(int j)
{
j = i;
}
void display()
{
Console.WriteLine(”Value of I is ” + i);
}

static void Main(string[] args)


{
Program p = new Program(10);
Program p1 = new Program(10);
Console.WriteLine(p.Equals(p1));
Program p2=p;
Console.WriteLine(p.Equals(p2));
}
}

In above example p and p1 are two different objects (i.e. both of these objects ae pointing
to different memory location), so p.Equals(p1) will returns false. But, the objects p2 and
p are pointing to the same memory location and hence p.Equals(p2) will returns true.
Some times it is necessary to check whether the two objects have same values for their fields
instead of checking for their memory address. So for this purpose, we have to override the
Equals method. For example, if we include the following code in the above example, the
Equlas method will return true if both objects will have the same value for i. (Even though
both objects refer to different memory locations, if the value of i is same it will returns
true or else false)

override public bool Equals(Program p)


{
if(i==p.i)
return true;
return false;
}

2. ReferenceEquals In the object class, the Equals and ReferenceEquals methods are se-
mantically equivalent, except that the ReferenceEquals works only on object instances.

Ravikiran
58 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

The ReferenceEquals method is static. For example,

Object.ReferenceEquals(p,p1)

If both p and p1 refer to same memory location, then it will returns true else it will return
false.

3. GetType GetType is the basis for using reflection in .NET. It returns a Type object,
describing the object it was called on. The GetType method is also useful if we get an
object at runtime and we don’t know what it’s type is. For example

Console.WriteLine(p.GetType())

The above statement will prints the name of the Type (Here it is ”Program”).

4. GetHashCode The GetHashCode method makes any object usable in a Hashtable or any
hashing algorithm. Since the default algorithm supplied by the GetHashCode method of
the object class is not guaranteed to be unique, you should override GetHashCode in your
custom types. For example

Console.WriteLine(p.GetHashCode())

The above line will prints the hash code of object ”p”

5. ToString The purpose of the ToString method is to return a human readable represen-
tation of a type. The default implementation in the object class returns a string with the
name of the runtime type of the object. For example

Console.WriteLine(p)

The above line will prints the name of Type. Here it is ”Program”. The ToString method
is a virtual method, and so we can override this method to return our own string. For
example

override public string ToString()


{
return ”The value of I is ”+i;
}

Now Console.WriteLine(p) method will prints ”The value of I is 10”

6. MemberwiseClone Whenever we need to create a shallow copy of our type, we use the
MemberwiseClone method. A shallow copy is a bitwise copy of our type. As such, if we
perform a MemberwiseClone on our class, it will make a copy of the type and all contained
value types and references types. Since the MemberwiseClone method is not virtual, we
can not override it in derived classes. For example..

Ravikiran
3.10. CONSTANT DATA 59

Program p3=(Program)p.MemberWiseClose();

The above statement will creates a new object p3 exactly of type p. But p and p3 will
point to different memory locations (It is not similar to Program p3=p where p3 and p will
refer to same memory location). As MemberwiseClone returns object, we have to convert
explicitly to the type of object we are going to convert.

3.10 Constant Data


In C# constant data can be specided in two ways

• by using ’const’ modifier

• by using ’readonly modifier

3.10.1 const modifier


Constants are fields whose values are set at compile time and can never be changed. A C#
constant is similar to a variable in that it gives a defined name to a value. However, a constant
differs from a standard variable because once defined, the value assigned to the constant can
never be changed. A constant is declared using similar syntax to any other variable. However,
to indicate that the value is fixed and may not be changed at run-time, the const keyword is
used as a prefix to the data type for example

const int PI=3.14;

Constants are declared with the const modifier. Only the C# built-in types (excluding Sys-
tem.Object) may be declared as const. C# does not support const methods, properties, or
events. Constants can be marked as public, private, protected, internal, or protected internal.
These access modifiers define how users of the class can access the constant. Constants are ac-
cessed as if they were static fields because the value of the constant is the same for all instances
of the type. we do not use the static keyword to declare them.

using System;
class Program
{
const int PI=3.14; //By default const variables are static
static void Main(string[] args)
{
Console.WriteLine(Program.PI);
}
}

Ravikiran
60 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

3.10.2 By using readonly modifer


A readonly member is like a constant in that it represents an unchanging value. The difference
is that a readonly member can be initialized at runtime, in a constructor as well being able to
be initialized as they are declared. for example

using System;
class ConstantDemo
{
readonly int A=10;
readonly int B;
readonly int C;
ConstantDemo()
{
B=20;
C=Console.ReadLine();
}
}

• Like constant members, readonly members are not implicitly static, and therefore the static
keyword can be applied to a readonly field explicitly if required.

• A readonly member can hold a complex object by using the new keyword at initialization.

• readonly members cannot hold enumerations.

3.11 Iteration Constructs in C#


C# provides a number of the common loop statements:

• while

• do-while

• for

• foreach

3.11.1 while loop


A ’while’ loop executes a statement, or a block of statements wrapped in curly braces, repeatedly
until the condition specified by the boolean expression returns false. For instance, the following
code

Ravikiran
3.11. ITERATION CONSTRUCTS IN C# 61

int a=1;
while(a <4)
{
Console.WriteLine(a);
a++;
}

produces the follwing output


1
2
3

3.11.2 do-while loops


A ’do-while’ loop is just like a ’while’ loop except that the condition is evaluated after the block
of code specified in the ’do’ clause has been run. So even where the condition is initially false,
the block runs once. For instance, the following code outputs ’4’:

int a=4;
do
{
Console.WriteLine(a);

}while(a <3);

3.11.3 for loops


The statements in the for loop repeat continuously for a specific number of times. The while
and do-while loops repeat until a certain condition is met. The for loop repeats until a specific
count is met. Use a for loop when the number of repetition is know, or can be supplied by the
user. The coding format is:
for(startExpression; testExpression; countExpression)
{
block of code;
}
The startExpression is evaluated before the loop begins. It is acceptable to declare and assign
in the startExpression (such as int x = 1;). This startExpression is evaluated only once at the
beginning of the loop.
The testExpression will evaluate to true or false. While TRUE, the body of the loop repeats.
When the testExpression becomes FALSE, the looping stops and the program continues with
the statement immediately following the for loop body in the program code.
The countExpression executes after each trip through the loop. The count may increase /decrease
by an increment of 1 or of some other value.

Ravikiran
62 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

3.11.4 foreach loop


syntax:
foreach(variable1 in variable2)
{
//Statements }
The ’foreach’ loop is used to iterate through the values contained in a collection. When a ’fore-
ach’ loop runs, the given variable1 is set in turn to each value exposed by the object named by
variable2. for example

int[] a=1,2,3;
foreach(int b in a)
{
Console.WriteLine(b);
}

The main drawback of ’foreach’ loops is that each value extracted (held in the given example by
the variable ’b’) is read-only.

3.12 Flow Control statements in C#


C# provides two types of statements that control the flow of control in a program

• Jump Statements

• Selection Statements

3.12.1 Jump Statements


The jump statements include

• break

• continue

• goto

• return

• throw

break

The ’break’ statement breaks out of the ’while’ and ’for’ loops and the ’switch’ statements. The
output of the following loop is the numbers from 0 to 4.

Ravikiran
3.12. FLOW CONTROL STATEMENTS IN C# 63

int i=0;
while(true)
{
Console.WriteLine(i);
if(i==5)
break;
i++;
}

continue

The ’continue’ statement can be placed in any loop structure. When it executes, it moves the
program counter immediately to the next iteration of the loop. The following code example uses
the ’continue’ statement to count the number of values between 1 and 100 inclusive that are not
multiples of seven. At the end of the loop the variable y holds the required value.

int y=0;
for(int x=1;x <101;x++)
{
if((x%7)==0)
continue;
y++;
}

goto

The ’goto’ statement is used to make a jump to a particular labelled part of the program code.
We can use a ’goto’ statement to construct a loop, as in the following example (but again, this
usage is not recommended):

int a=0;
start:
Console.WriteLine(a);
a++;
if(a <5 )
goto start;

Return Statement

The ’return’ statement is used in the method to return some value to the calling part of the
program. When the return statement is encountered in the method, method will stop and return
a value. The control will be transfered to the calling part of the program and starts executes the
statements thereafter.

Ravikiran
64 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

throw statement

Throw statement is used for handling exceptions. Throw statement is used in the try block. When
throw statement is encountered in the middle of try block, then the control will be transferred
to the appropriate catch block.

3.12.2 Selection Statements


In C#, there are two types of selection statements.
1. if-else statements
’If-else’ statements are used to run blocks of code conditionally upon a boolean expression
evaluating to true. The ’else’ clause, present in the following example, is optional.

if(a==10)
Console.WriteLine(” A is equal to 10”);
else
Console.WriteLine(”A is not equal to 10”);

Different types of if statements are...

• simple if
• if-else statements
• Nested if statements
• Ladder if-else statements(if-else-if....)

2. Switch statements The switch statements help to control complex conditional and branch-
ing operations. The switch statement transfers control to a statement within its body.
Syntax

switch(expression)
{
case (constantExpression):
//Statements
break;
.
.
.
case (constantExpression):
//Statements
break;
default:
//statements
break
}

Ravikiran
3.13. C# OPERATORS 65

In order to come out of a particular case, we have to use break statement and program
will comes out of the switch body. Without break, the program continues to the next case,
executing the statements until a break or the end of the statement is reached. In some
situations, this continuation may be desirable.
The default statement is executed if no case constant-expression is equal to the value of
switch ( expression ). If the default statement is omitted, and no case match is found,
none of the statements in the switch body are executed. There can be at most one default
statement. The default statement need not come at the end; it can appear anywhere in
the body of the switch statement. A case or default label can only appear inside a switch
statement.
The type of switch expression and case constant-expression must be integral. The value
of each case constant-expression must be unique within the statement body. The case
and default labels of the switch statement body are significant only in the initial test that
determines where execution starts in the statement body. Switch statements can be nested.

3.13 C# Operators
C# provides a large set of operators, which are symbols that specify which operations to perform
in an expression. The following are the C# operators.

• Unary Operators Unary operators are those which will take only one operand. The
various unary operators in C# are

+, -, !, , ++x, –x, true, false, & , sizeof

• Binary Operators Binary operators are those which will take two operands.

* , /, % , + , -

• Shift Operators Shift operators are those used to shift bits of a number (in binary
number) towards are right or left

<<, >>

• Relational Operators These operators are used to test the relation of two operands.

<, >, >= , <= , == , != , is , as

• Conditional And This operator returns true if both the expressions on either side of this
operator evaluates to true else it will returns false

& & - Logical AND operator

Ravikiran
66 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

• Conditional Or This operator returns true if either on of the expressions on either side
of this operator evaluates to true. If both expressions evaluates to false, it will also returns
false.

|| - Logica OR operator

• Conditional operatoar This operator is similar to if-else statement.

?: - Conditional operator (or) terenary operator

• Assignment operatoars These operators are used to assign values to a variable. The
following are the assignment operators available in C#

= , += , -= , *= , /= , % = , & = , |=, ˆ= , <<= , >>=

3.14 Defining Custom Class Methods


Custom classes are those classes which we define i.e. those are not part of .NET library. We can
define our own methods in our own classes. These custom methods may or may not have return
type ( if no return type, then void is used as return type ). Custom methods also may or may
not take parameters, may be declared as static or non static.
We can also specify the following various access modifiers to the custom methods

1. private : Method that is declared as private can be accessed only by the type in which
the method is defined. (It is the default visiblity level)

2. public : Method that is declared as public can be accessed by any class or object i.e. there
is no restriction in accessing the public method

3. internal : Methods that are declared as internal can be accessed as public by all types
in a containing assembly.

4. protected : Here the access is limited to the containing class or types derived from the
containing class.

5. protected internal : Access is limited to the current assembly or types derived from the
containing class.

3.15 Static Methods


A C# class can contain both static and non-static methods. When we declare a method with
the help of the keyword static, it becomes a static method. A static method belongs to the class
rather than to the objects of the class. Hence static method are also known as class method and
non-static method are known as instance methods.

Ravikiran
3.16. METHOD PARAMETER MODIFIERS IN C# 67

A static method is callable on a class even when no instance of the class has been created. If
any instances of the class are created, they cannot be used to access the static member. Static
members are often used to represent data or calculations that do not change in response to object
state; for instance, a math library might contain static methods for calculating sine and cosine.
Static class members are declared using the static keyword before the return type of the member,
for example:
static int Sum(int a, int b) return a+b;
Static members are initialized before the static member is accessed for the first time, and before
the static constructor, if any is called. To access a static class member, use the name of the class
instead of a variable name to specify the location of the member.
Static Fields
Static fields can be declared as follows by using the keyword static.

class MyClass
{
public static int x;
public static int y = 20;
}

When we declare a static field inside a class, it can be initialized with a value as shown above.
All un-initialized static fields automatically get initialized to their default values when the class
is loaded first time.
Inside a C# class, member functions can also be declared as static. But a static member function
can access only other static members. They can access non-static members only through an
instance of the class.
We can invoke a static member only through the name of the class. In C#, static members can’t
invoked through an object of the class as like in C++ or JAVA.

3.16 Method Parameter Modifiers in C#


There are four different kinds of parameters in C#:

• value parameters (the default)

• reference parameters (which use the ref modifier)

• output parameters (which use the out modifier)

• parameter arrays (which use the params modifier)

we can use any of them with both value and reference types.

Ravikiran
68 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

3.16.1 Value parameters


; By default, parameters are value parameters. This means that a new storage location is created
for the variable in the function member declaration, and it starts off with the value that you
specify in the function member invocation. If you change that value, that doesn’t alter any
variables involved in the invocation. For instance, if we have:

public class ValueReferenceType


{
static void change (int x)
{
x += 10;
}
public static void Main (string[] args)
{
int x=10;
change(x);
Console.WriteLine (”value of x is {0}”,x);
}
}

In the above example, the value of x is not changed in main method even when we call the function
change(). This is because, a new memory is created for the parameter when the function is called
and all the changes will occur in that new memory location and that change is not reflected in
the main method.
So the output of above program will be 10 but not 20.

3.16.2 Reference parameters


Reference parameters don’t pass the values of the variables used in the function member invo-
cation - they use the variables themselves. Rather than creating a new storage location for the
variable in the function member declaration, the same storage location is used, so the value of
the variable in the function member and the value of the reference parameter will always be
the same. Reference parameters need the ref modifier as part of both the declaration and the
invocation - that means it’s always clear when you’re passing something by reference.
Reference parameters are passed using the keyword ref

Ravikiran
3.16. METHOD PARAMETER MODIFIERS IN C# 69

Let’s look at our previous examples, just changing the parameter to be a reference parameter...

public class ValueReferenceType


{
static void change (ref int x)
{
x += 10;
}
public static void Main (string[] args)
{
int x=10;
change(x);
Console.WriteLine (”value of x is {0}”,x);
}
}

Now the above program will produces output 20.

3.16.3 Output Parameters


Like reference parameters, output parameters don’t create a new storage location, but use the
storage location of the variable specified on the invocation. Output parameters need the out
modifier as part of both the declaration and the invocation - that means it’s always clear when
you’re passing something as an output parameter. Output parameters are very similar to refer-
ence parameters. The only differences are..

• The parameter is considered initially unassigned

• The parameter must be assigned a value before the function member completes normally.

public class ValueReferenceType


{
static void change (ref int x,out int y) {
x += 10;
y=10;
}
public static void Main (string[] args) {
int x=10;
int y;
change(x,y);
Console.WriteLine (”value of x is {0} and y is {1} ”,x,y);
}
}

Ravikiran
70 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

The above program will produces 10 and 20 as output. Notice that even though we didnt initialize
the y variable, it will get initiailized in the method. Genrally out parameters are used to return
multiple values from the method.

3.16.4 Parameter arrays

Parameter arrays allow a variable number of arguments to be passed into a function member.
The definition of the parameter has to include the params modifier, but the use of the parameter
has no such keyword. A parameter array has to come at the end of the list of parameters, and
must be a single-dimensional array. When using the function member, any number of parameters
(including none) may appear in the invocation, so long as the parameters are each compatible
with the type of the parameter array. Alternatively, a single array may be passed, in which case
the parameter acts just as a normal value parameter. For example:

public class ValueReferenceType


{
void ShowNumbers (params int[] numbers)
{
foreach (int x in numbers)
Console.WriteLine (x+” ”);
}
public static void Main (string[] args)
{
change(10,11,12,13,14,15,16);
change(34,45,2);
}
}

3.17 Arrays in C#

An array is a collection of similar data types stored in adjacent memory locations. Though the
syntax of declaring and using a C# array is more or less similar to that of C/C++, they are
actually created as objects of the System.Array class. Hence arrays in C# fall in the category of
reference types. Like any other reference type, an array object refers to a memory space allocated
on the heap. Following code fragment shows how to declare and initialise an array.
int[] a, b ;
a = new int [10] ;
b = new int [] { 0, 1, 2, 3, 4 } ;

Ravikiran
3.17. ARRAYS IN C# 71

3.17.1 Array Bounds Checking


In C# checking the array bounds is not the programmer’s responsibility. If the array bounds
are exceeded, the .NET runtime informs the application about it by throwing an exception. An
exception is a runtime error caused by fatal errors like array bounds out of range, using an invalid
reference, etc. Thus, following code would never work in C#.
int[ ] a = { 1,2, 3, 4 } ;
a [ 4 ] = 10 ;
Although compiler would not report any error .NET runtime would throw an exception.

3.17.2 Multi Dimensional Arrays


Apart from single dimension array, C# provides multidimensional arrays, also called rectangular
arrays and jagged arrays. This is how we can declare a 2D array.
int [ , ] arr1 = new int [ 4, 4 ] ;
arr1 = new int [ 4, 4 ] ;
int [ , ] arr2 = { { 3, 5, 7, 9 }, { 11, 13, 15, 17 } } ;

3.17.3 System.Array class


The difference between C and C++ arrays is the fact that every array we create is automatically
derived from System.Array. This class defines a number of helpful methods that make working
with arrays much more palatable.

1. BinarySearch This is a static method of System.Array class. It takes two arguments one
is an array type and one is object type. It will searches the array for the given object and
if the object is found it will return the index of that object else it will return the value less
than 0 (negative index). For example

static void Main()


{
int[] a=10,20,30,40,15;
Console.WriteLine(Array.BinarySearch(a,30));
}

The above example prints the value 2 as 30 is at 2nd position.

2. Clear : Clear is a static method of Array class. Sets a range of elements in the Array
to zero, to false, or to a null reference depending on the element type. It will take three
parameters -

• Array type - whose elements has to be cleared


• index - specifying the start index of the range of elements to be cleared
• length - specifies the number of elements to be cleared

Ravikiran
72 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

static void Main()


{
int[] a=10,20,30,40,15;
Array.Clear()
}

3. Clone : Creates a shallow copy of the Array. The return type of this method is an object.
So we have to use explicitly type cast into the required type. For example..

static void Main()


{
int[] a=10,20,30,40,15;
int[] b;
b=(int[]) a.Clone();
}

4. CopyTo : Copies all the elements of the current one-dimensional Array to the specified
one-dimensional Array. It takes two parameters

• Array Type - It is the destination array to which we have to copy elements


• intex - Specifies the index from which copy has to begin

static void Main()


{
int[] a=10,20,30,40,15;
int[] b=new int[4];
a.CopyTo(b,0);
}

In the above example, all the elements in a will be copied into b starting at 0th index of b.

5. GetLength Gets a 32-bit integer that represents the number of elements in the specified
dimension of the Array.

6. GetValue :Returns the element at the specified position in an array. For example the
following statement prints element at second index
Console.WriteLine(a.GetValue(2));

7. SetValue :Sets the specified value at the specified position. for example the following
statement sets the value 30 at the position 3.
a.SetValue(30,3);

8. Reverse : Reverses the order of the elements in a one-dimensional. This is static method
and takes one parameter of Array type which has to be reversed.

Ravikiran
3.18. STRING MANIPULATION IN C# 73

9. Sort : Sorts the elements in one-dimensional Array objects. This is static method and
takes one parameter of Array type which has to be sorted.

3.18 String Manipulation in C#


A string is a sequential collection of Unicode characters, typically used to represent text, while
a String is a sequential collection of System.Char objects that represents a string. The value of
the String is the content of the sequential collection, and the value is immutable.

1. It is a reference type.

2. It’s immutable because its value cannot be modified once it has been created. Methods
that appear to modify a String actually return a new String containing the modification.

3.18.1 String Manipulation Methods


String class provides various methods to manipulate the string. Some of those are..

1. Trim :It strips all white spaces from both the start and end of the string. string Name =”
String Manipulation ”; string NewName = Name.Trim();

2. Copy : This method simple creates a copy of an existing string. It provides the same
functionality as assigning to a string directly. This is a static method. string sample =
”Ravi kiran.”
string result = string.Copy(sample); //result = ”Ravi kiran.”

3. Compare : It is a static method. Compares two specified String objects and returns an
integer that indicates their relationship to one another in the sort order i.e. if both strings
are equal it will returns 0, else if first string is greater it will returns 1 else it will returns
-1. Example
string s=”ravi”;
string s1=”kiran”;
Console.WriteLine(string.Compare(s,s1)); //Prints 1

4. Concat : Concatenates one or more instances of String, or the String representations of


the values of one or more instances of Object. Example
string s=string.Concat(”ravi”,”kiran”,”kumar”);

5. Contains : Returns a boolean indicating whether the specified String object occurs
within this string. Example
string s=”ravi kiran”;
Console.WriteLine(s.Contains(”avi”)); //Prints true;

Ravikiran
74 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

6. EndsWith : Determines whether the end of a String matches a specified string. Example
string s=”ravi kiran”;
Console.WriteLine(s.EndsWith(”an”)); //Prints true;

7. Format :Replaces each format item in a specified string with the text equivalent of a
corresponding object’s value. Example
Console.WriteLine(string.Format(”{0:c}”,1000)); //Prints$1,000.00;

8. IndexOf :Reports the index of the first occurrence of a String within this string. Example
string s=”Ravi”;
Console.WriteLine(s.IndexOf(”av”)); //Prints 1;

9. Insert :Inserts a specified instance of String at a specified index position in this instance.
Example
string s=”Ravi kiran”;
Console.WriteLine(s.Insert(0,”Bandari ”)); //Prints Bandari Ravi kiran;

10. LastIndexOf : Reports the index position of the last occurrence of a specified Unicode
character or String within this instance.

11. PadLeft :Right-aligns the characters in this instance, padding on the left with spaces or
a specified Unicode character for a specified total length. Example
string s=”Ravi”;
Console.WriteLine(s.padLeft(20,’*’)); //Prints ****************Ravi ;

12. PadRight :Left-aligns the characters in this string, padding on the right with spaces or a
specified Unicode character, for a specified total length. Example
string s=”Ravi”;
Console.WriteLine(s.padRight(20,’*’)); //Prints Ravi**************** ;

13. Replace :Replaces all occurrences of a specified Unicode character or String in this in-
stance, with another specified Unicode character or String. Example
string s=”Ravi kiran”;
Console.WriteLine(s.Replace(”a”,’aa”)); //Prints Raavi kiraan ;

14. ToUpper : Returns a copy of this String in uppercase.

15. ToLower : Returns a copy of this String in lowercase.

16. ToCharArray : Copies the characters in this instance to a Unicode character array.
Example
string s=”Ravi kiran”;
char[] c=s.ToCharArray();

Ravikiran
3.18. STRING MANIPULATION IN C# 75

3.18.2 System.Text.StringBuilder Class


This class represents a string-like object whose value is a mutable sequence of characters. The
value is said to be mutable because it can be modified once it has been created by appending,
removing, replacing, or inserting characters. The following are the some of the methods defined
in the StringBuilder class

1. Append : Appends the string representation of a specified object to the end of this
instance. Example
StringBuilder sb=new StringBuilder(”Ravi”);
sb.Append(”Kiran”);
Console.WriteLine(sb); //Prints Ravi Kiran

2. Insert : Inserts the string representation of a specified object into this instance at a
specified character position. Example
StringBuilder sb=new StringBuilder(”Kiran”);
sb.Insert(0,”Ravi”);
Console.WriteLine(sb); //Prints Ravi Kiran

3. Remove : Removes the specified range of characters from this instance. Example
StringBuilder sb=new StringBuilder(”Ravi Kiran”);
sb.Remove(0,4);
Console.WriteLine(sb); //Prints Kiran

4. Replace : Replaces all occurrences of a specified character or string in this instance with
another specified character or string.

3.18.3 Escape Characters and Verbatim Strings


Certain characters in C# cant be reprsented in strings in usual way for various reasons C#
supports two different solutions to this problem.
The first approach is to use ’escape sequences’. For example, suppose that we want to set variable
a to the value: ”Hello, How are you?”
We could declare this using the following command, which contains escape sequences for the
quotation marks and the line break
string a = ”\”Hello World\n How are you\””;
The following table gives a list of the escape sequences for the characters that can be escaped in
this way:

Ravikiran
76 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

Character Escape Sequence


’ \’
” \”
\ \\
Alert \a
Backspace \b
Form feed \f
New Line \n
Carriage Return \r
Horizontal Tab \t
Vertical Tab \v
null \0 (zero)

Table 3.2: Various Escape characters in C#

The second approach is to use ’verbatim string’ literals. These are defined by enclosing the
required string in the characters @” and ”. To illustrate this, to set the variable ’path’ to the
following value:
C:\My Documents\
we could either escape the back-slash characters string path = ”C:\\My Documents\\”
or use a verbatim string thus:
string path = @”C:\MyDocuments\” Usefully, strings written using the verbatim string syntax
can span multiple lines, and whitespace is preserved. The only character that needs escaping is
the double-quote character, the escape sequence for which is two double-quotes together. For
instance, suppose that you want to set the variable ’text’ to the following value:
the word ”big” contains three letters.

Using the verbatim string syntax, the command would look like this:
string text = @”the word ””big”” contains three letters.”

3.19 Enumerations
An enumeration is a special kind of value type limited to a restricted and unchangeable set of
numerical values. By default, these numerical values are integers, but they can also be longs,
bytes, etc. (any numerical value except char) as will be illustrated below.
When you define an enumeration you provide literals which are then used as constants for their
corresponding values. The following code shows an example of such a definition:
public enum Days
{
Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
}
Note, however, that there are no numerical values specified in the above. Instead, the numerical
values are set up according to the following two rules:

Ravikiran
3.19. ENUMERATIONS 77

1. For the first literal: if it is unassigned, set its value to 0.

2. For any other literal: if it is unassigned, then set its value to one greater than the value of
the preceding literal.

From these two rules, it can be seen that DAYS.Monday will be set to 0, and the values increased
until DAYS.Sunday is set to 6. Note also how we are referring to these values - the values spec-
ified in an enumeration are static, so we have to refer to them in code using the name of the
enumeration: ”DAYS.Monday” rather than just ”Monday”. Furthermore, these values are final
- we can’t change their runtime value.

The following code demonstrates how you can override the default setting which makes the
default values integers. In this example, the enumeration values are set to bytes.
public enum Days:byte
{
Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
}

You can also override the default numerical values of any and all of the enumeration elements.
In the following example, the first literal is set to value 1. The other literals are then set up
according to the second rule given above, so DAYS.Sunday will end up equal to 7.
public enum Days:byte
{
Sunday=1,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
}

3.19.1 System.Enum class


System.Enum class will provide the following static methods

1. Format :Converts the specified value of a specified enumerated type to its equivalent string
representation according to the specified format It takes three paramters

• enumType :The enumeration type of the value to convert.


• value : The value to convert.
• format : The output format to use. The valid formats are

(a) ”G” or ”g” : If value is equal to a named enumerated constant, the name of
that constant is returned; otherwise, the decimal equivalent of value is returned.
For example, suppose the only enumerated constant is named, Red, and its value
is 1. If value is specified as 1, then this format returns ”Red”. However, if value
is specified as 2, this format returns ”2”.

Ravikiran
78 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

(b) ”X” or ”x” Represents value in hexadecimal


(c) ”D” or ”d” Represents value in decimal form.

Example

class EnumDemo
{
public enum Days
{
sunday, monday, tuesday
}

static void Main(string[] args)


{
Days d = Days.monday;
Console.WriteLine(Enum.Format(typeof(Days),d,”D”));
Console.WriteLine(Enum.Format(typeof(Days),d,”G”));
Console.WriteLine(Enum.Format(typeof(Days),d,”X”));
}
}

2. GetName :Retrieves the name of the constant of the specified enumeration type that has
the specified value. It takes two parameters
enumType : A Type that specifies the type of the enumeration.
value : A Object that contains the integral value or the name of an enumeration constant.
Example
Console.WriteLine(Enum.GetName(typeof(Days),d)); //Prints monday

3. GetNames :Returns a zero-based, one-dimensional String array that contains the names
of the constants of the specified enumeration type. Example

string str[]=Enum.GetNames(typeof(Days));

4. GetUnderlyingType : Returns the underlying type of the specified enumeration type.

5. GetUnderlyingType : Returns the underlying type of the specified enumeration type.


It takes one paratmeter of Enum Type
Example
Console.WriteLine(Enum.GetUnderlyingType(typeof(Days)));

6. GetValues :Returns a zero-based, one-dimensional array of the values of the constants of


the specified enumeration type.
Example
Array a=Enum.GetValues(typeof(Days));

Ravikiran
3.19. ENUMERATIONS 79

7. IsDefined :Returns a Boolean indicating whether a constant with the specified value exists
in the specified enumeration type. It takes two parameters
enumType - A Type that describes an enumeration.
value - The constant or value being searched for in enumType.
Example
Console.WriteLine(Enum.IsDefined(typeof(Days),1)); //Prints true

Ravikiran
80 CHAPTER 3. C# LANGUAGE FUNDAMENTALS

Ravikiran
Chapter 4

Object Oriented Programming


using C#

4.1 Definition of C# class


A class is the core of any modern Object Oriented Programming language such as C#. A class
is nothing but a user defined data type (UDT) that is composed of data (fields or attributes)
and functions (methods) that act upon this data.
We use Classes as a template to put the properties and functionalities or behaviors in one building
block for some group of objects and after that we use that template to create the objects we
need. For example, if we want to have Student object in our program, the first thing we have
to do is to create a Class called Person that contains all the functionalities or behaviors and
properties of any student. After creating Student class, we can use this class as a template to
create as many as student objects we need. Creating object of a specific class type called
”instance of the class”.
The Class : Is a building block that contains the properties and functionalities that describe
some group of objects, We can create a class Student that contains:

• The properties of normal student like Student ID, Student N ame, Date Of Birth, F ather N ame
etc...

• The functionalities or behaviors of any normal student like Get M arks, Calculate Average
etc...

When we declare a variable in a class we call it member variables or instance variables. The
name instance come from the fact that when we create an object we instance a class to create
that object so instance of a class means object of that class and instance variable means variable
that exists in that class.

81
82 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

4.1.1 Constructors
A class will also contains Constructors which will be automatically executed when an object of a
class is created. Constructors can be considered as a special class member functions that provide
a simple way to create an instance of a class with inital look and feel (.i.e. all the variables in
a class will be initialized to their default values when object is created). If we didnt declare
any constructor in a class, the compiler will provide one default constructor(Constructor with
no parameters). The role of default constructor is to ensure that all the data in a class is set to
an initial safe (default) value.
For Example

using System;
class Student
{
string name,sid;
int markstotal;
Student(string na,string id,int marks)
{
name=na;
sid=id;
markstotal=marks;
}
void setStudent(string na,string id,int marks)
{
name=na;
sid=id;
markstotal=marks;
}
void displayData(string na,string id,int marks)
{
name=na;
sid=id;
markstotal=marks;
}
}

In the above example there is no default constructor. So, if we want to create an object for the
above class, it is cumpolsory that we have to pass arguments the arguments to an object. Example

Student s=new Student(”Ravi”,”std01”,100); //Calling Parameterized Constructor

Student s1=new Student(); //Error - As there is no Default Constructor

Ravikiran
4.2. SELF REFERENCE IN C# 83

As there is parameterized constructor, the compiler will not include any default constructor.
So in order to make above statement correct we have to explicitly include the follwoing default
constructor.

Student()
{
}

4.2 Self Reference in C#


The this keyword refers to the current instance of the class. The following are common uses of
this:

1. To qualify members hidden by similar names, for example:


public Employee(string name, string alias)
{
this.name = name;
this.alias = alias;
}

2. To pass an object as a parameter to other methods, for example:


void display(this);

It is an error to refer to this in a static method because they exist at the class level and not as
part of an object.

4.2.1 Forwarding Constructor Calls using ”this”


Another use of C# ”this” keyword is to force one constructor to call another during the time of
object initialization.

class Student
{
string sid;
int marks;
Student(string s, int i)
{
sid = s;
¿ marks = i;
}
Student():this(”Ravi kiran”, 100)
{
}
void display()

Ravikiran
84 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

{
Console.WriteLine(”Student ID {0 } /Marks {1 }”, sid, marks);
}
static void Main(string[] args)
{
Student s = new Student();
s.display();
}
} Output
Student ID Ravi kiran
Marks 100

4.3 Default Public Interface


Once the variables and methods (including constructor) are defined in a class, the next step is
define which of these memebers are directly accessible from an object variable. And these class
members which are accessible from an object variable are called Public Interfaces of a class.
The public interface is any item declared in a class using ”public” keyword. In C#, the default
interface of a class may be populated by any of the following members.

1. Methods : These are member functions that provide some behavior to a class in which
they are declared.

2. Properties : These are Accessor and Mutator Functions which are used to access or set
the values to the class fields.

3. Public fields or Public Variables :These are the fields declared in a class as public.
(Declaring public variables in a class is not recommended)

By default, if we do not explicitly mark the visibility level of a class, it is implicitly set to
”internal”. Internal classes can only be created by types which are present within the same
assembly, and are not accessible from outside the assembly.

4.4 Pillars of OOP


C# is an Object oriented Programming language. So like all Object oriented languages, C# will
also supports following Object Oriented Principles..

1. Encapsulation

2. Inheritance

3. Polymorphism

Ravikiran
4.4. PILLARS OF OOP 85

4.4.1 Encapsulation
Encapsulation is the procedure of covering up of data and functions into a single unit (called
class). An encapsulated object is often called an abstract data type.

1. Encapsulation is one of the fundamental principles of object-oriented programming.

2. Encapsulation is a process of hiding all the internal details of an object from the outside
world

3. Encapsulation is the ability to hide its data and methods from outside the world and only
expose data and methods that are required

4. Encapsulation provides a way to protect data from accidental corruption

5. Encapsulation gives you the ability to validate the values before the object user change or
obtain the value

6. Encapsulation makes implementation inaccessible to other parts of the program and protect
from whatever actions might be taken outside the function or class.

Need for Encapsulation

The need of encapsulation is to protect or prevent the code (data) from accidental corruption. In
Object oriented programming data is treated as a critical element in the program development
and data is packed closely to the functions that operate on it and protects it from accidental
modification from outside functions.
Rather than defining the data in the form of public, we can declare those fields as private.
The Private data are manipulated indirectly by two ways. The first method is using a pair of
conventional accessor and mutator methods. Another method is using a named property.

Ravikiran
86 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

ENCAPSULATION USING ACCESSORS AND MUTATORS :

Figure 4.1: Example for Accessors and Mutators

In this example employeeid and salary is private fields and providing access to the fields using
public methods (SetEmployeeID,GetEmployeeID,SetSalary,GetSalary)

ENCAPSULATION USING PROPERTIES :

Properties are a new language feature introduced with C#. Properties in C# helps in protect a
field in a class by reading and writing to it. The first method itself is good but Encapsulation
can be accomplished much smoother with properties. Now let’s see an example.

public class Department


{
private string departname;
public string Departname
{
get { return departname; }
set
{
departname=value;
}
}
}

Ravikiran
4.4. PILLARS OF OOP 87

public class Departmentmain


{
public static int Main(string[] args)
{
Department d= new Department();
d.departname=”Master of Computer Application”;
Console.WriteLine(”The Department is : {0 }”,d.Departname);
return 0;
}
}
From the above example we see the usage of Encapsulation by using properties. The property
has two accessor get and set. The get accessor returns the value of the some property field.
The set accessor sets the value of the some property field with the contents of ”value”. The C#
”value” keyword represents the right hand side of the assignment. Like all the things in C#
”value” is also object. However, the underlying type of the object depends on which sort of data
it represents.

Internal Reprsentation of C# Properties

Many programmers tend to design traditional accessor and mutator methods using ”get ” and
”set ” prefixes (e.g., get Name() and set Name()). This naming convention itself is not problem-
atic. However, it is important to understand that C# property is internally represented using
these same prefixes. For example Assume that class Employee type has a private member vari-
able named empSSn to represent an individual’s Social Security Number, which is manipulated
by a property named SSN.
public class Department
{
private string empSSN;
public string SSN
{
get { return empSSN; }
set
{
empSSN=value;
}
}
public string get SSN() { return empSSN;} //ERROR
public void set SSN(string val) { empSSN = val;} //ERROR
}
In the above example there is one property by name SSN. This property internally represented
as get SSN() and set SSN() methods. So, the compiler will generates an error if we explicitly

Ravikiran
88 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

include those methods in a class.

Read-Only and Write-Only Properties

Properties can be made read-only. This is accomplished by having only a get accessor in the
property implementation. For Example...

public class Department


{
private string empSSN;
public string SSN
{
get { return empSSN; }

}
}

In the above example, the property ”SSN” is having only get accessor but not set mutator. So
we can call SSN as a ”read-only property

Creating a Write-Only Property

You can assign values to, but not read from, a write-only property. A write-only property only
has a set accessor.

public class Department


{
private string empSSN;
public string SSN
{
set { empSSN=value; }

}
}

4.5 Inheritance
Inheritance is one of the primary concepts of object-oriented programming. It allows you to
reuse existing code. The relationship between two or more classes is termed as Inheritance in
an Object Oriented Programming language. Normally there will be one class, from which the
other classes may derive. The former class is called as Base class or super class and latter class
is called as derived class. All variables and methods in the base class can be called in the derived
classes, provided they are declared public or protected.

Ravikiran
4.5. INHERITANCE 89

The subclass can add methods and properties or modify the functionality that it has inherited
to provide a more specialised version of the base class. Inheritance comes in two flavors

• classical inheritance (the ”is-a” relationship)

• containment/delegation model (the ”has-a” relationship).

4.5.1 Classical Inheritance :


When we establish ”is-a” relationships between classes, we are building a dependency between
types. The basic idea behind classical inheritance is that new classes may extend the functionality
of other classes. To illustrate, assume that we wish to define two additional classes to model
sales people and managers. The hierarchy looks like this From the above figure we notice that

Figure 4.2: Employee Hierarchy

sales-person ”is-a” Employee.


In classical Inheritance model, base classes are used to define general characteristics that are
common to all subclasses.
In C#, classes are extended by means of ”:” operator. Example

using System;
public class ParentClass
{
public ParentClass()
{
Console.WriteLine(”Parent Constructor.”);
}
public void print()
{
Console.WriteLine(”I’m a Parent Class.”);
}
}
public class ChildClass : ParentClass
{
public ChildClass()
{

Ravikiran
90 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

Console.WriteLine(”Child Constructor.”);
}
public static void Main()
{
ChildClass child = new ChildClass();
child.print();
}
}
Output :
Parent Constructor.
Child Constructor.
I’m a Parent Class.

4.5.2 Containment / Delegation model (”Has-A” Relationship)


The composition (HAS-A) relationship specifies how one class (the whole) is made up of other
classes (the parts). For Example...

public class Engine


{
public void Start()
{
System.Console.WriteLine(”Engine started”);
}
}
public class Car
{
public string make;
public Engine engine; //Car has an Engine
public void Start()
{
engine.Start();
}
}

4.5.3 ”base”- keyword


The base keyword is used to access members of the base class from within a derived class:

1. Call a method on the base class that has been overridden by another method.

2. Specify which base-class constructor should be called when creating instances of the derived
class.

Ravikiran
4.5. INHERITANCE 91

It is an error to use the base keyword from within a static method.

using System;
class BaseClass
{
public int i;
public BaseClass(int i)
{
this.i = i;
}
}
class DerivedClass:BaseClass
{
new int i = 0;
DerivedClass(int i):base(i)
{
this.i = 100;
}
void display()
{
Console.WriteLine(”Value of Base Class I is {0 }”,base.i);
Console.WriteLine(”Value of Derived Class I is {0 }”,i);
}
static void Main(string[] args)
{
DerivedClass dc = new DerivedClass(10);
dc.display();
}
}
Output
Value of Base Class I is 10
Value of Derived Class I is 100

Because classes cannot inherit constructors, a derived class must implement its own constructor
and can only make use of the constructor of its base class by calling it explicitly.
If the base class has an accessible default constructor, the derived constructor is not required
to invoke the base constructor explicitly; instead, the default constructor is called implicitly as
the object is constructed. However, if the base class does not have a default constructor, every
derived constructor must explicitly invoke one of the base class constructors using the ”base”
keyword. The keyword - ”base” identifies the base class for the current object.

Ravikiran
92 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

4.5.4 Preventing Inheritance : Sealed classes


When a base class is declared with sealed keyword, then that class cannot be extended. The
sealed modifier is used to prevent derivation from a class. An error occurs if a sealed class is
specified as the base class of another class. In C# structs are implicitly sealed; therefore, they
cannot be inherited.

Example for Sealed Classes

using System;
sealed class MyClass
{
public int x;
}
class MainClass
{
public static void Main()
{
MyClass mC = new MyClass();
mC.x = 110;
Console.WriteLine(”x = {0} ”, mC.x,);
}}
In the preceding example, if we attempt to inherit from the sealed class by using a statement like this:
class MainClass: MyClass {} //Error
You will get the error message:
’MainClass’ cannot inherit from sealed class ’MyClass’.

Sealed Methods in C#

In C# a method can’t be declared as sealed. However when we override a method in a derived


class, we can declare the overrided method as sealed as shown below. By declaring it as sealed,
we can avoid further overriding of this method.

Example for Sealed Method

using System;
sealed class MyClass
{
public void virtual Display()
{
Console.WriteLine(”Virtual Method”);
}
}

Ravikiran
4.6. PLOYMORPHISM 93

class MainClass : MyClass


{
public override sealed void Display()
{
Console.WriteLine(”sealed method”);
}
public static void Main()
{
MainClass mC = new MainClass();
mc.Display();
}
}

4.6 Ploymorphism
Through inheritance, a class can be used as more than one type; it can be used as its own type,
any base types, or any interface type if it implements interfaces. This is called polymorphism.
In C#, every type is polymorphic. Types can be used as their own type or as a Object instance,
because any type automatically treats Object as a base type.
When a derived class inherits from a base class, it gains all the methods, fields, properties and
events of the base class. To change the data and behavior of a base class, we have two choices:
we can replace the base member with a new derived member, or we can override a virtual base
member.
Replacing a member of a base class with a new derived member requires the new keyword. If a
base class defines a method, field, or property, the new keyword is used to create a new definition
of that method, field, or property on a derived class. The new keyword is placed before the return
type of a class member that is being replaced. For example

public class BaseClass


{
public void display()
{
Console.WriteLine(”Base Class”);
}
}
public class DerivedClass : BaseClass
{
public new void display()
{
Console.WriteLine(”Derived Class”);
}

Ravikiran
94 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

static void Main(String[] args)


{
BaseClass b=new DerivedClass();
b.display(); //Prints Base Class
DerivedClas d=new DerivedClasb();
d.display(); //Prints Derived Class
}
}

When the new keyword is used, the new class members are called instead of the base class
members that have been replaced. Those base class members are called hidden members. Hidden
class members can still be called if an instance of the derived class is cast to an instance of the
base class.

static void Main(String[] args)


{
DerivedClas d=new DerivedClasb();
d.display(); //Prints Derived Class
BaseClass b=(BaseClass)d;
b.display();
}

In order for an instance of a derived class to completely take over a class member from a base
class, the base class has to declare that member as virtual. This is accomplished by adding the
virtual keyword before the return type of the member. A derived class then has the option of
using the override keyword, instead of new, to replace the base class implementation with its
own.

public class BaseClass


{
public virtual void display()
{
Console.WriteLine(”Base Class”);
}
}
public class DerivedClass : BaseClass
{
public override void display()
{
Console.WriteLine(”Derived Class”);
}
static void Main(String[] args)

Ravikiran
4.7. ABSTRACT CLASSES & ABSTRACT METHODS 95

{
DerivedClas d=new DerivedClasb();
d.display(); //Prints Derived Class
BaseClass b=(BaseClass)d; //Prints Derived Class
b.display();
}
}

Fields cannot be virtual; only methods, properties, events and indexers can be virtual. When a
derived class overrides a virtual member, that member is called even when an instance of that
class is being accessed as an instance of the base class.

4.7 Abstract Classes & Abstract Methods


The abstract keyword enables us to create classes and class members that are incomplete and
must be implemented in a derived class.
Classes can be declared as abstract by putting the keyword abstract before the class definition.
For example:

public abstract class Shape


{
//Class Definition
}

An abstract class cannot be instantiated. The purpose of an abstract class is to provide a com-
mon definition of a base class that multiple derived classes can share.
Abstract classes normally contain one or more abstract methods or abstract properties, such
methods or properties do not provide implementations, but derived classes must override inher-
ited abstract methods or properties.
Abstract classes may also define abstract methods. This is accomplished by adding the keyword
abstract before the return type of the method. For example:

public abstract class Shape


{
public abstract void Draw();
}

Abstract methods have no implementation, so the method definition is followed by a semicolon


instead of a normal method block. Derived classes of the abstract class must implement all
abstract methods.

Ravikiran
96 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

4.8 Type Casting in C#


The first law of casting between class types is that when two classes are related by an ”is-
a” relationship, it is always safe to reference a derived class using a base class reference. For
example a base class named Employee and a derived class named Manager, the following code
works because there’s always an implied upcast from a derived class to its base class:

public class Employee


{
}
public class Manager : Employee
{
static void Main(String[] args)
{
Employee e=new Manager();
}
}

However, the following is illegal, because the compiler cannot provide an implicit downcast:

Manager m=new Employee() //ERROR


However, we cannot cast an object of base class down to an object of type derived class because
there’s no guarantee that the object supports the interface defined by the derived class. There-
fore, in the case of a downcast, an explicit cast is used as follows:
Manager m=(Manager)new Employee()

4.8.1 ”is” - Operator


The is operator is used to check whether the run-time type of an object is compatible with a
given type. he is operator cannot be overloaded. The ”is” operator is used in an expression of
the form
expression is type
where

1. expression :An expression of a reference type. An is expression evaluates to true if both


of the following conditions are met. Expressions should not be null

2. type : A type.

The ”is” operator checks whether an object is compatible with a given type, and the result of
the evaluation is a Boolean: true or false. The is operator will never throw an exception. The
follwoing code demonstrates

Ravikiran
4.8. TYPE CASTING IN C# 97

System.Object o = new System.Object();


bool b1 = (o is System.Object); //b1 is true.
bool b2 = (o is Employee); //b2 is false.

If the object reference is null, the is operator always returns false because there is no object
available to check its type.

4.8.2 ”as” - operator


Objects can be converted from one type to another, assuming that the types are compatible. Of-
ten this is achieved using implicit conversion or explicitly with the cast operator. An alternative
to this is the use of the ”as” operator

Implicit casting occurs if the target variable is of a compatible type that is higher in the inher-
itance hierarchy (a superclass), or is of an interface that is implemented by the object’s class,
either directly or indirectly. In these cases, no additional work is required of the developer; the
conversion happens automatically.
Explicit casting must be used when the conversion is in the opposite direction to that required
by implicit casting. For example, when casting an object to one of its subclasses or casting from
an interface to a class. To perform explicit casting, the cast operator is used.
In the following example code, we can see a variable being cast from a subclass to its superclass
using implicit casting. It is then returned to the subclass using explicit casting.

public class Employee


{
}
public class Manager : Employee
{
static void Main(String[] args)
{
Manager m=new Manager();
Employee e=m; //Implicit Cast
Manager m1= (Manager) e; //Explict Cast
}
}

Explicit casting is useful but can be problematic when the variable being cast is not compatible
with the target type. In this situation an exception is thrown.
C# includes another method of performing explicit conversions. Using the ”as” operator, an
object can be converted from one type to another. Unlike with explicit casting, if the conversion
is not possible because the types are incompatible the operation does not throw an exception.

Ravikiran
98 CHAPTER 4. OBJECT ORIENTED PROGRAMMING USING C#

Instead, the resultant variable simply contains null.


Example

class Student
{
void display()
{
Console.WriteLine(”This is Student Class”);
}
static void Main(string[] args)
{
Object o=new Object();
Student s=(Student) o; //ERROR - Invalid Cast, generates Compile Error
Student s1=o as Student; //VALID statement but here s1 will be assigned to null
}
}

Ravikiran
Chapter 5

Exceptions and Object Lifetime

5.1 Introduction to Errors, Bugs, and Exceptions


Writing a software is a complex process, so it is quite common for even the best software to
ship with various problems. These problems may be caused either due to ”bad code”(such as
overflowing the bounds of an array) or due to invalid input given by the end-user. When such
an error occurs, our software may not work as expected.
In software terminology, we will frequently come across these following terms

• Bugs : A software bug is the common term used to describe an error, flaw, mistake, failure,
or fault in a computer program or system that produces an incorrect or unexpected result,
or causes it to behave in unintended ways.

• Errors : Unlike bugs, errors are typically caused by the end user of the application, rather
than those who created the appliation. For example, User may enter character data where
numeric data is expected

• Exceptions : Exception is a strange behavior of software during runtime. It is very


difficult to prevent exceptions. For example Exceptions my arise either if we try to connect
to a database which is not there, or if we try to open a corrupted file etc... The programmer
has little control over these ”exceptional” circumstances.

5.2 The Role of .NET Exception Handling


Before .NET, many programmers used to code their own error handling logic within the context
of a given application. For example, they may define a set of numerical constants that represent
known error conditions and make use of them as method return values. For example

99
100 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

#define DIVIDE BY ZERO -3


int SomeFunction(int a, int b)
{
if (b == 0) // can’t divide by 0
return DIVIDE BY ZERO;
return a / b;
}

This way of error handling is called as a classic C approach and it doesn’t provide any helpful
information regarding how to deal with the problem.
So there must be some way to wrap the name, message, and other helpful information regarding
this error condition into single well defined package. This technique of bundling all information
regarding the error is called as structured exception handling.
Exception handling is an in built mechanism in .NET framework to detect and handle run time
errors which can be caused due to logic or system errors. If a user (programmer) do not provide
a mechanism to handle these anomalies, the .NET run time environment provide a default
mechanism, which terminates the program execution.
Another important feature of Exceptions in .NET is that rather than using of numeric constants
for identifying the problem, we are using the exceptions as objects that contain human readable
description of the problem as well as the detailed infromration of the call stack that triggered
the exception in the first place.

5.2.1 The Elements of .NET Exception Handling


Programming with structured exception handling involves the following elements

• A class type that represents the details of the exception that occurred

• A member that throws an instance of the exception class to the caller

• A block of code(try block) on the callers side that invokes the exception-prone
member

• A block of code on the callers side that will process (or catch) the exception
should it occur

Ravikiran
5.3. THE SYSTEM.EXCEPTION BASE CLASS 101

5.3 The System.Exception Base Class


System.Exception class represents an error that occurs during runtime of an application. This
class is the base class for all exceptions. When an error occurs, either the system or the currently
executing application reports it by throwing an exception containing information about the error.
Once thrown, an exception is handled by the application or by the default exception handler.

5.3.1 Members of System.Exception Class


1. Properties

• HelpLink : Gets or sets a link to the help file associated with this exception. This
property returns a URL to a help file describing the error in full detail. For example,
the HelpLink value could be:
”file:///C:/Ravi/help.html”
• Innter Exception : This read-only property can be used to obtain information about
the previous exception(s) that caused the current exception to occur. The previous
exception(s) are recorded by passing them into the constructor of the most current
exception. For Example
try
{
throw new ApplicationException(”This is Application Error”);
}
catch (Exception e)
{
throw new DivideByZeroException(”This is Divide By Zero”,e);
}
• Message :This read-only property returns the textual description of a given error.
The value of the Message property is included in the information returned by ToString.
The Message property is set only when creating an Exception. If no message was
supplied to the constructor for the current instance, the system supplies a default
message that is formatted using the current system culture. For Example
catch (Exception e)
{
Console.WriteLine(e.Message);
}
• Source :This property returns the name of the assembly that threw the exception.
• StackTrace :This read-only property contains a string that identifies the sequence
of calls that triggered the exception. This property is very helpful at the time of
debugging.
The execution stack keeps track of all the methods that are in execution at a given

Ravikiran
102 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

instant. A trace of the method calls is called a stack trace. The stack trace listing
provides a means to follow the call sequence to the line number in the method where
the exception occurs.

• TargetSite :This read-only property returns a MethodBase type, which describes


numerous details about the method that threw the exception

5.4 Throwing a Generic Exception


When developing a software for .NET framework, it is important that exceptions are thrown
only when an unexpected or invalid activity occurs that prevents a method from completing its
normal function. Before throwing an exception, it is always up to us to decide excatly what
constitutes the error and also when it has be thrown. When an error condition is encountered,
the throw command is used to raise an exception. The throw command’s syntax is as follows:
throw exceptionObj
The exceptionObj is an exception object containing the details of the exception to be raised.
This can be declared as an object and initialised before the throw command. However, it is more
usual to create a new exception object within the throw statement, using the new keyword and
one of the exception’s constructors to set the object’s properties.
The following example uses a console application that requires at least one command line argu-
ment in order to execute. If no command-line argument is provided, an Exception is thrown.
The constructor of System.Exception class used in the example requires a single string parameter
containing the error message for the exception.

class ExceptionDemo
{
static void Main(string[] args)
{
// Check that a parameter was provided
if (args.Length == 0)
{
throw new Exception(”Invalid Arguments”);
}
Console.WriteLine(”{0} argument(s) provided”, args.Length);
}
}

When executed correctly with a parameter, the above program runs without error and outputs
the number of parameters detected. However, if the number of arguments used is zero, this is
identified by the if statement and an exception is thrown. This avoids unexpected exceptions
occurring later due to the parameters being invalid.

Ravikiran
5.5. CATCING EXCEPTIONS 103

5.5 Catcing Exceptions


When we suspect that a block of code will generate an errors or throws an Exceptions, that
block of code has to be included in the try-catch block. The idea behind the try and catch
command is that if any anomalies happen within the try block, the catch block will be executed.
For example

public class ExceptionDemo


{
static double Divide(int a, int b)
{
return a / b;
}
static void Main(String[] args)
{
Console.WriteLine(ExceptionDemo.Divide(10, 2));
}
}

The above example works well as long as we dont pass zero as second parameter to Excep-
tion.Divide method. But if we pass zero the program will abnormally terminate as we can’t
divide by zero. The calling the ExceptionDemo.Divide method should be included in a try block
as follows.

try
{
Console.WriteLine(ExceptionDemo.Divide(10, 0));
}
catch(Exception)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.Source);
Console.WriteLine(e.TargetSite);
}

Output
Attempted to divide by zero.
ConsoleApplication1
Double Divide(Int32, Int32)

Even though we passed zero as second argument for ExceptionDemo.Divide Method, the program
will not abnormally terminate. Instead, it will Prints the above output.

Ravikiran
104 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

In some situations, Exceptions may also occur when we call the method that explicitly throws
an Exception. For Example
public class ExceptionDemo
{
private int age;
private string yourName, childName;
string YourName
{
set
{
yourName = value;
}
}
string ChildName
{
set
{
childName = value;
}
}
int Age
{
set
{
if (value <18)
throw new Exception(”Invalid Age”);
else
age = value;
}
}
public void GetData()
{
Console.WriteLine(”Enter Name : ”);
YourName = Console.ReadLine();
try
{
Console.WriteLine(”Enter Name : ”);
YourName = Console.ReadLine();
Console.WriteLine(”Enter Age: ”);
Age = Int32.Parse(Console.ReadLine());
Console.WriteLine(”Enter {0 } Child Name”, yourName);

Ravikiran
5.6. CLR SYSTEM-LEVEL EXCEPTIONS (SYSTEM.SYSTEMEXCEPTION)105

ChildName = Console.ReadLine();
}
catch (Exception)
{
Console.WriteLine(” {0 } is not having Child”, yourName);
}
}
static void Main(String[] args)
{
ExceptionDemo ed = new ExceptionDemo();
ed.GetData();
}
}

In the above example, the Property Age is accepting the values only if we provide value greater
than 18 or else Exception will be thrown. So, when ever we are accessing the Age Property, that
statement should be included in the try-catch block. So, in the GetData method, if we provide
value 18 then only it ask us to enter our ChildName, or else it will print Exception Message.

5.6 CLR System-Level Exceptions (System.SystemException)


Defines the base class for predefined exceptions in the System namespace.
Exceptions that are thrown by methods in the base class libraries are called system exceptions.
System exceptions generally derive directly from a base class named System.SystemException,
which in turn derives from System.Exception.
SystemException does not provide information as to the cause of the Exception. In most sce-
narios, instances of this class should not be thrown. In cases where this class is instantiated, a
human-readable message describing the error should be passed to the constructor
SystemException type does not add any additional functionality beyond that of System.Exception,
The idea is that when an exception type derives from System.SystemException, we are able to
determine that the .NET runtime is the entity that has thrown the exception, rather than the
custom code base of the executing application.

5.7 Custom Application-Level Exceptions


ApplicationException is thrown by a user program, not by the common language runtime. If
you are designing an application that needs to create its own exceptions, derive from the Appli-
cationException class. ApplicationException extends Exception, but does not add new function-
ality. When we handle an exception deriving from System.ApplicationException, we can assume
that exception is raised by the code base of the executing application, rather than by the .NET

Ravikiran
106 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

base class libraries.

5.7.1 Creating Custom Exceptions


Although the .NET framework contains all kinds of exception types which are sufficient in most
cases, it can make sense to define custom exceptions in your own applications. They can greatly
simplify and improve the error handling and thus increase the overall code quality.
Any custom exception we create needs to derive from the System.Exception class. You can either
derive directly from it or use an intermediate exception like SystemException or ApplicationEx-
ception as base class. According to the .NET framework documentation, SystemException is
meant only for those exceptions defined by the common language runtime whereas Applica-
tionException is intended to be used by user code.

The absolute minimum a new custom exception class needs to have is a name. Lets say we are
designing the login mechanism for a database application and as part of this job we need to
create a custom exception which is thrown if a login attempt fails. A good name for such an
exception would be LoginFailedException. An absolute minimum implementation in C# then
looks like:

public class LoginFailedException: System.Exception


{
}
All we need to do is to create a basic custom exception which is derived from the Exception class.
Theres only one problem with this definition. Since C# unfortunately doesnt inherit construc-
tors of base classes, this new type only has the standard constructor with no parameters and is
therefore relatively useless. So, we need to add at least one constructor which does something
useful...

public class LoginFailedException: System.Exception


{
// The default constructor needs to be defined
// explicitly now since it would be gone otherwise.
public LoginFailedException()
{
}
public LoginFailedException(string message): base(message)
{
}
}

Now we can use our custom exception like most other exceptions. We can throw an instance of
LoginFailedException and pass a message which describes the occurred error.

Ravikiran
5.8. HANDLING MULTIPLE EXCEPTIONS 107

But .NET exceptions can do more. we can normally pass a so called inner exception to one of
the constructors which indicates that the created exception is a direct result of a previous one.
This inner exception can then be retrieved via the InnerException property. This way we can
build entire exceptions chains. Since this can be quite useful sometimes, we extend our existing
implementation with this additional constructor.

public class LoginFailedException: System.Exception


{
// The default constructor needs to be defined
// explicitly now since it would be gone otherwise.
public LoginFailedException()
{
}
public LoginFailedException(string message): base(message)
{
}
public LoginFailedException(string message,
Exception innerException): base(message, innerException)
{
}
}

5.8 Handling Multiple Exceptions


A catch block can specify an exception type which it has to catch. This type is called an exception
filter, and must either be the Exception type, or derived from this type
While using multiple catch blocks, each catch block is checked in turn to see if the exception
thrown is the same type as, or derives from, that declared in the catch statement. When a
match is found, the code within the catch block is executed. Only one catch block’s code is ever
executed. Exceptions thrown that do not match any of the declared types remain unhandled.
For Example

public class ExceptionDemo


{
static void Main(String[] args)
{
try
{
Console.WriteLine(”Enter A Value”);
int a = Int32.Parse(Console.ReadLine());
Console.WriteLine(”Enter B Value”);
int b = Int32.Parse(Console.ReadLine());

Ravikiran
108 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

float c = (float)a / b;
Console.WriteLine(” {0} Divided By {1} is {2}”, a, b, c);
}
catch (DivideByZeroException )
{
Console.WriteLine(”You cant Divide a number with Zero”);
}
catch (FormatException)
{
Console.WriteLine(”You have Entered an Invalid Number”);
}
catch (Exception )
{
Console.WriteLine(”Unknown Error”);
}
}
}

Above example includes three catch blocks. The first handles any division by zero error. The
second responds when we enter non numeric string instead on numeric characters. The final
catch block does not specify the type of exception to catch and therefore is executed when any
other type of exception occurs.

5.9 The Finally Block


C# defines an addition block that may be added to the end of the try-catch block. This is known
as the finally block. The code within this section is guaranteed to be executed after the try-catch
block, even if any of the statements in the try / catch block caused the current method to exit
normally or by throwing a further exception.

static void Main(string[] args)


{
int value = 50;
int divisor = 0;
int calculated;
try
{
calculated = value / divisor;
}
catch
{
Console.WriteLine(”An error occurred during division.”);

Ravikiran
5.10. LAST CHANCE OF EXCEPTION 109

calculated = int.MaxValue;
}
finally
{
Console.WriteLine(”Clearing up any resources.”);
}
}

OUTPUT

An error occurred during division.


Clearing up any resources.
Result = 2147483647

5.10 Last chance of Exception

Some times it is possible that, we may leave certain runtime anamolies with out handling them.
The result of ignoring an exception would be highly obstructive to the end user of our application,
as an ”unhandled exception” is displayed.

5.11 Identifing Application and System Exceptions

We can generalize our catch blocks in such a way that all our application level exceptions are
handled separately from possible system-level exceptions.

try
{
}
catch(ApplicationException)
{
// All Custom Applications will be caught here
}
catch(SystemException)
{
// All the exceptions thrown by CLR will be caught here
}

Ravikiran
110 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

5.12 Debugging Unhandled Exceptions using Visual Stu-


dio
Visual Studio 2005 provides us number of tools that help to debug unhandled exceptions. When
we start debugging our program in visual studio, Visual studio will automatically breaks at the
time the uncaught exception is thrown.

Figure 5.1: Debugging unhandled exceptions with visual studio

if we click the ViewDetail link, we will find the details regarding the state of the object

Ravikiran
5.13. UNDERSTANDING OBJECT LIFE TIME 111

5.13 Understanding Object Life Time


In .NET, objects are allocated onto a region of memory termed as the ”manged heap”, where
they will be automatically deallocated by the runtime whenever an object is no longer needed.
Once the object is allocated onto the managed heap, entire care will be taken by the CLR about
that object. Runtime will removes an object from the heap when it is unreachable by the current
application. For example

public class ObjectDemo


{
public void display()
{
Console.WriteLine(”This is ObjectDemo Class”);
}
}
public class ObjectLifeTime
{
void Display()
{
ObjectDemo od = new ObjectDemo();
od.display();
}
public static void main(string[] args)
{
{
ObjectLifeTime o = new ObjectLifeTime();
o.Display();
}
o.Display(); // ERROR - Object o has gone out of scope, so
// it is subjected for Garbage Collection.

ObjectLifeTime o1 = new ObjectLifeTime();


o1.Display();
}
// HERE object o1 also gone for out of scope, object o1 can be now removed
// from heap memory
}

Ravikiran
112 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

5.14 The CIL of ”new”


When a C# compiler encounters a ’new’ keyword, it will emit CIL ”newobj” instruction to the
code module. Managed heap is more than just a raw chunk of memory accessed by the CLR. The
.NET garbage collector is quite a tidy housekeeper, given that i will compact empty blocks of
memory(when necessary) for purpose of optimization. In this optimization process, the managed
heap maintains a pointer (commonly referred to as the new object pointer) that identifies exactly
where the next object will be placed on the heap itself.The newobj instruction informs the CLR
to perform the following sequence of events.

1. Calculate the total amount of memory required for the object about to be allocated. If the
object contains other internal objects (i.e. the ”has-a” relationship as well as nested type
members), memory for those objects should also be calculated. Also the memory required
for each base class is also taken into account.

2. The CLR then examines the managed heap to ensure that there is enough memory to allo-
cate for the object to be newly created. If there is enough memory, the type’s constructor is
called, and the caller is returned a reference to the type in the memory, which just happens
to be identical to the last position of the new object pointer.

3. Finally, before returning the reference to the caller, the CLR will advance the new object
pointer to point to the next available slot on the managed heap.

If we goes on creating objects, at some point of time the managed heap will become full. When
newobj instruction is encountered, and if CLR determines that managed heap does not have
sufficient memory to allocate the requested type, it will perform a garbage collection in an
attempt to free up memory.
Garbage Collector in .Net is in deterministic which means that we can never be sure when the
garbage collector be invoked. When garbage collection occurs, the runtime will checks for objects
in the managed heap that are no longer being used by the application and performs the necessary
operations to reclaim their memory.

5.15 Garbage Collection Algorithm


Application Roots

Every application has a set of roots. Roots identify storage locations, which refer to objects on
the managed heap or to objects that are set to null.
For example

1. References to global objects

2. Reference to any static objects / static fields

3. Reference to local objects within an applications code base

Ravikiran
5.15. GARBAGE COLLECTION ALGORITHM 113

4. Reference to object parameters passed into a method

5. Any CPU register that references an object

Implementation

Garbage collection in .NET is done using tracing collection and specifically the CLR implements
the Mark/Compact collector. This method consists of two phases as described below.

• Phase:1 Mark
Find memory that can be reclaimed.
When the garbage collector starts running, it makes the assumption that all objects in the
heap are garbage. In other words, it assumes that none of the application’s roots refer to
any objects in the heap.
The following steps are included in Phase 1:

1. The GC identifies live object references or application roots.


2. It starts walking the roots and building a graph of all objects reachable from the roots
3. If the GC attempts to add an object already present in the graph, then it stops walking
down that path. This serves two purposes. First, it helps performance significantly
since it doesn’t walk through a set of objects more than once. Second, it prevents
infinite loops should you have any circular linked lists of objects.

Once all the roots have been checked, the garbage collector’s graph contains the set of all
objects that are somehow reachable from the application’s roots; any objects that are not
in the graph are not accessible by the application, and are therefore considered garbage.

• Phase II: Compact Move all the live objects to the bottom of the heap, leaving free
space at the top. Phase II includes the following steps:

1. The garbage collector now walks through the heap linearly, looking for contiguous
blocks of garbage objects
2. The garbage collector then shifts the non-garbage objects down in memory, removing
all of the gaps in the heap
3. Moving the objects in memory invalidates all pointers to the objects. So the garbage
collector modifies the application’s roots so that the pointers point to the objects’ new
locations
4. In addition, if any object contains a pointer to another object, the garbage collector
is responsible for correcting these pointers as well.
5. After all the garbage has been identified, all the non-garbage has been compacted, and
all the non-garbage pointers have been fixed-up, a pointer is positioned just after the
last non-garbage object to indicate the position where the next object can be added.

Ravikiran
114 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

5.16 Finializing a Type


.NET garbage collection scheme is non-deterministic in nature, i.e. it is difficult to determine ex-
catly when an object will be deallocated from the memory..NET automatic memory management
is quite helpful to us if we do not included any unmanaged code into our application. But some
times there may be a need to include unmanged objects for which automatic memory manage-
ment is not done i.e. we have to explicitly remove those unmanaged objects from the memory. To
account for such situations, one choice we have is to override the virtual System.Object.Finalize()
method (the default implementation does nothing). But the odd thing is C# language does not
allow us to directly override the finalize method using the following standard syntax

public class Student


{
protected override void Finailize() // ERROR - Overriding Finialize is not allowed
{
}
}

Instead of overrding the Finalize method, we have to make use of (C++ like) destructor to syntax
to achieve the same effect.

public class Student


{
∼ Student()
{
}
}

5.17 The Finalization Process


The role of a finalizer is to ensure that a .NET object can clean up unmanaged resources. Thus,
if we are building a type that does not make use of unmanaged entities, finalization is of little
use.
When we place an object onto the managed heap using the new operator, the runtime automat-
ically determines if our object supports a custom Finalize() method. If so, the object is marked
as finalizable, and a pointer to this object is stored on an internal queue called finalization queue.
The finalization queue is a table maintained by the CLR that points to each and every object
that must be finalized before it is removed from the heap.
When the garbage collector determines it is time to free an object from memory, it examines each
entry cataloged on the finalization queue, and copies the object off the heap to yet another CLR-
managed structure termed the finalization reachable table (often abbreviated as freachable, and
pronounced ”Freachable”). At this point, a separate thread is spawned to invoke the Finalize()
method for each object on the freachable table at the next garbage collection.

Ravikiran
5.18. BUILDING AN AD HOC DESTRUCTION METHOD 115

5.18 Building an Ad Hoc Destruction Method


When our type manipulates unmanaged resources, we do need to ensure they are released in a
timely and predictable manner. Even though we can do this by using destructors, still there are
better ways.
One alternative is to define a custom method that we can assume all objects in our system
implement. Let’s call this method as Dispose(). The assumption is that when the object user
is finished using our type, it manually calls Dispose() before allowing the object reference to
drop out of scope. In this way, our objects can perform any amount of cleanup necessary of
unmanaged resources without incurring the hit of being placed on the finalization queue and
without waiting for the garbage collector to trigger the class finalization logic

public class Student


{
public void Dispose()
{
/* Clean up your internal unmanaged resources. */
}
}

5.18.1 The IDisposable Interface


In order to provide symmentry among all the objects that support an explicit destruction routine,
the .NET class libraries define an interface named IDisposable that supports a single member
named Dispose().

public Interface IDisposable


{
public void Dispose();
}

Its a better way to follow to implement the IDisposable interface for all types that wish to support
an explicit form of resource deallocation. For example

public class Student:IDisposable


{
public void Dispose()
{
/* Clean up your internal unmanaged resources. */
}
static void Main(string[] args)
{
Student s=new Student();
s.Dispose();

Ravikiran
116 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

}
}

5.18.2 Reusing the C# ”using” Keyword


The ”using” keyword has a double meaning (specifying namespaces and triggering a Dispose()
method). When we are working with .NET types that support IDisposable interface, this syntac-
tically construct will ensure that object being used will automatically have its Dispose() Method
called once the block has exited. On the other hand, if we specify a type that does not implement
IDisposable within the using declaration, we will get a compile time error.

public class Student:IDisposable


{
public void Dispose()
{
/* Clean up your internal unmanaged resources. */
}
static void Main(string[] args)
{
using(Sudent s=new Student())
{
/* Dispose() method is automatically when the using block exits */
}
}
}

5.19 Garbage Collection Optimizations


When the CLR is attempting to locate unreachable objects, is does not literally walk over each
and every object placed on the managed heap looking for orphaned roots. Doing so would involve
considerable time, especially in larger (i.e., real-world) applications.
To help optimize the collection process, each object on the heap is assigned to a given ”gener-
ation.” The idea behind generations is simple: The longer an object has existed on the heap,
the more likely it is to stay there (for example, the object implementing an application’s Main()
method). Conversely, objects that have been recently placed on the heap are more likely to
be dereferenced by the application rather quickly (such as an object created within a method
scope). Given these assumptions, each object belongs to one of the following generations

1. Generation 0 Identifies a newly allocated object that has never been marked for collection

2. Generation 1 Identifies an object that has survied a garbage collection sweep (i.e. it was
marked for collection, but was not removed due to the fact that the heap had enough free
space)

Ravikiran
5.20. THE SYSTEM.GC TYPE 117

3. Generation 2 Identifies an object that has survied more than one sweep of the garbage
collector.

Now, when the collection occurs, the Garbage Collector marks and sweeps all generation-0 objects
first. If this results in the required amount of memory, the remaining objects are promted to the
next available generation. If all generation-0 objects have been removed from the heap, but more
memory is still necessary, generation-1 objects are marked and swept, followed (if necessary) by
generation-2 objects. In this way the newer objects (i.e. local variables) are removed quickly
while an older object is assumed to be in use.

5.20 The System.GC Type


System.GC type allows us to interact with the Garbage Collector using a small set of static
members.

• Collect() : Forces the GC to call the Finalize() method for every object on the managed
heap.

• GetGeneration() : Returns the generation to which an object currently belongs.

• MaxGeneration : This property returns the maximum of generations supported on the


target system.

• SuppressFinalize() : Sets a flag indicating that a given object should not have its Final-
ize() method called

• ReRegisterForFinalize() : Sets a flag indicating that a suppressed object should be


reregistered as finalizable. This (of course) assumes the object was marked as nonfinalizable
using SuppressFinalize().

• GetTotalMemory() : Returns the estimated amount of memory (in bytes) currently


being used by all the objects in the heap including the objects that are soon to be destroyed.
This method takes one boolean parameter that is used to specify if a garbage collection
should occur during the method invocation.

Example

public class Student:IDisposable


{
∼ Student()
{
}
public void Dispose()
{

Ravikiran
118 CHAPTER 5. EXCEPTIONS AND OBJECT LIFETIME

/* Clean up your internal unmanaged resources. */


GC.SuppressFinalize(this);
}
static void Main(string[] args)
{
Student s= new Student();
s.Dispose();
}
}

In the above example, the student class is having both C++ style destructor as well as the
IDisposable interface. Here, our Dispose() method has been altered to call GC.SuppressFinalize()
which informs the system that it should no longer call the destructor for the specified object, as
the end user has called Dispose() method.

Ravikiran
Chapter 6

Interfaces and Collections

Interfaces describe a group of related functionalities that can belong to any class or struct.
Interfaces can consist of methods, properties, events, indexers, or any combination of those four
member types.
When a class or struct is said to inherit an interface, it means that the class or struct provides
an implementation for all of the members defined by the interface. The interface itself provides
no functionality that a class or struct can inherit in the way that base class functionality can
be inherited. However, if a base class implements an interface, the derived class inherits that
implementation.
Interfaces allow you to truly separate the what from the how. The interface tells you only what the
name, return type, and parameters of the method are. Exactly how the method is implemented
is not a concern of the interface. The interface represents how you want an object to be used,
rather than how it happens to be implemented at a particular moment in time.

Interface Syntax

To declare an interface, we use the interface keyword instead of the class or struct keyword.
Inside the interface, we declare methods exactly as in a class or a struct, except that we never
specify an access modifier (no public, private, or protected access), and we replace the method
body with a semicolon. Here is an example:

interface IEmployee
{
string Name();
}

Interface Restrictions

The interface never contains any implementation. The following restrictions are natural conse-
quences of this

119
120 CHAPTER 6. INTERFACES AND COLLECTIONS

1. we are not allowed any fields in an interface, not even static ones.

2. Interfaces do not contain any constructors or even destructors.

3. We cannot supply any access modifier in interfaces. All the methods in an interface are
implicitly public.

4. We cannot inherit any interface from a struct or class.

6.1 Implementing Interfaces


To implement an interface, we declare a class that inherits from the interface and implements
all the interface methods. For example, suppose you are defining the Employee hierarchy shown
earlier, but need to specify that all classes in the hierarchy provide a method called Name that
returns the name of the current token as a string. we could define the IEmployee interface that
contains this method:

interface IEmployee
{
string Name();
}
interface IEmployer
{
int Count();
}
We could the implement these interfaces in the Manager class:

class Manager : IEmployee,IEmployer


{
string name;
int i;
Manager(string s,int temp)
{
name=s;
i=temp;
}
public string Name()
{
return name;
}
public int Count()
{
return i;

Ravikiran
6.2. CONTRASTING INTERFACES TO ABSTRACT BASE CLASSES 121

}
}

When we implement an interface, we must ensure that each method matches its corresponding
interface method exactly, according to the following guidelines:

1. The method names and return types match exactly.

2. Any parameters (including ref and out keyword modifiers, although not the params keyword
modifier) match exactly.

3. If there is any difference between the interface definition and its declared implementation,
the class will not compile.

6.2 Contrasting Interfaces to Abstract Base Classes


Like Interfaces, Abstract classes not only contain a group of abstract methods, but they also
contain non abstract methods which have default implementation. Abstract methods are free to
define public, private, and protected state data as well as any number of concrete methods that
can be accessed by the subclasses.
Interfaces on the other hand, never define state data and never provide an implementation of
the methods.
In C# a class can be derived only from single base class. But, the interfaces will provide us to
derive a class from multiple interfaces.

6.3 Invoking Interface Members at Object Level


The most straight forward way to interact with functionality supplied by a given interface is to
invoke the methods directly from the object level. For example

static void Main(string[] args)


{
Manager m=new Manager(”Ravi”,20);
Console.WriteLine(”Name 0 Age : 1 ”,m.Name(),m.Count());
}

In this approach we can come to know at the comopile time only about the interfaces that the
given class is implemented. But sometimes, we will not able to determine at compile time which
interfaces are supported by a given type. For example, assume that we have an array containg
50 Employe - compatable types only some of them are Employers. So if we attempt to to invoke
the Count method on a type that has not implemented Employer, we will receive a compile time
error. For example

Ravikiran
122 CHAPTER 6. INTERFACES AND COLLECTIONS

class Manager : IEmployee,IEmployer


{
string name;
int i;
Manager(string s,int temp)
{
name=s;
i=temp;
}
public string Name()
{
return name;
}
public int Count()
{
return i;
}
}

class Worker : IEmployee


{
string name;
Worker(string s)
{
name=s;
}
public string Name()
{
return name;
}
}
class Company
{
static void Main(string[] args)
{
IEmployee[] e=new IEmployee[2];
e[0]=new Manager(”Ravi”,30);
e[1]=new Worker(”Kumar”);
Console.WriteLine(e[0].Count());
Console.WriteLine(e[1].Count());// ERROR since e[1] is not of Manager Type

Ravikiran
6.3. INVOKING INTERFACE MEMBERS AT OBJECT LEVEL 123

}
}

In the above example, if we try to call e[1].Count() method, we will get an error as e[1] is an
object of type Worker where it will not contain the Count() method. So, in order to avoid such
errors, we have to explicitly convert an object to the interface reference. For example

Manager m=new Manager(”Ravi kiran”,30);

IEmployer e=(IEmployer)m; // Explicit Casting

Console.WriteLine(”Name : {0} \n Count : {1}”,e.Name(),e.Count());

In the above example, we are explicitly trying to convert manager class to IEmployee interface.
If the object does support this interface, we are then able to access the behavior accordingly.
However if we try to convert an object of type Worker into IEmployer interface reference, we will
get a runtime error when invoke Count() method. When we attempt to access an interface not
supported by a given class using a direct cast, the runtime throws an InvalidCastException. To
recover safely from this excption, we have to catch it. For Example..

try
{
Worker w=new Woker();
IEmployer e=(IEmployer)w;
} catch(InvalidCastException e)
{
Console.WriteLine(”Unable to process your request - Invalid Cast”);
}

Obtaining Interface References: The ”as” Keyword

The second way we can test for interface support (as well as obtain an interface from an object
reference) is to make use of the ”as” keyword. For example:

Workder w=new Worker();


IEmployer e=w as Worker;
if(e!=null)
e.Count();

There is no need of try/catch block when we are making use of the as keyword, given that if the
reference is not null, we know that we are calling on a valid interface reference.

Ravikiran
124 CHAPTER 6. INTERFACES AND COLLECTIONS

Obtaining Interface References: The ”is” Keyword

The another way to check the implemented interface for a given type is -”is” keyword. If the
object is not compatiable with the specified interface, we are returned false. On the other hand,
if the type is compatible with the interface, then we can safely call the members without needing
to make use of try/catch logic. For example...

IEmployee[] e=new Manager(),new Worker(),new Worker(),new Worker(),new Manager();


foreach (IEmployee e in IEmployee)
{
if(e is IEmployer)
e.Count();
}

Interfaces as Parameters

As Interfaces are strongly typed entities, we can use them as parameters for constructing the
methods as well as we can return as values from the methods. For example

interface Animal
{
void Move();
}
class Dog : Animal
{
public void Move()
{
Console.Write(”Dog Can Move from one place to another”);
}
static Animal GetAnimal()
{
Animal a=new Dog();
return a;
}
}
class MainClass
{
static void IsMoving( Animal listener )
{
listener.Move();
}
static void Main()
{

Ravikiran
6.4. EXPLICIT INTERFACE IMPLEMENTATION 125

Dog dog = new Dog();


ListenToMe( dog );
Animal anim=Dog.GetAnimal();
anim.Move();
}
}

6.4 Explicit Interface Implementation


A class that implements an interface can explicitly implement a member of that interface. When
a member is explicitly implemented, it cannot be accessed through a class instance, but only
through an instance of the interface.

using System;
interface InterfaceOne
{
void Execute();
}
interface InterfaceTwo
{
void Execute();
}
class MyImplementation: InterfaceOne, InterfaceTwo
{
void InterfaceOne.Execute()
{
Console.WriteLine(”InterfaceOne.Execute implementation”);
}
void InterfaceTwo.Execute()
{
Console.WriteLine(”InterfaceTwo.Execute implementation”);
}
}
class MainClass
{
public static void Main()
{
MyImplementation myImplementation = new MyImplementation();
InterfaceOne interfaceOne = (InterfaceOne) MyImplementation;
interfaceOne.Execute();

Ravikiran
126 CHAPTER 6. INTERFACES AND COLLECTIONS

InterfaceTwo interfaceTwo = (InterfaceTwo) MyImplementation;


interfaceTwo.Execute();
}
}

6.4.1 The Advantages of Explicit Interface Implementations


Implementing an interface explicitly offer a number of advantages that help us to write clearer,
more maintainable, and more predictable code.
We can implement a method without explicitly specifying the interface name, but this can lead
to some differences in the way the implementation behaves. Some of these differences can cause
confusion. For example, a method defined by using explicit interface implementation cannot be
declared as virtual, whereas omitting the interface name allows this behavior.
Explicit interface implementation disambiguates methods from different interfaces that have the
same name, return type, and parameters. The methods that implement the interface are publicly
accessible, but only through the interface. Without using explicit interface implementation it
would not be possible to distinguish which method implements part of which interface if multiple
interfaces contain methods with the same names, return types, and parameters.

6.5 Building Interface Hierarchies


Just as a class can serve as a base class to other classes (which can in turn function as base
classes to yet another class), it is also possible to build derived relationships among interfaces.
For Example

interface IPerson
{
void GetDetails();
}
interface IStudent:Person
{
void CalculateGrade();
}

Now, if a class wished to support each behavior expressed in this interface hierarchy, it would
derive from the nth-most interface (IStudent). Any methods defined by the base interface(s) are
automatically carried into the definition. For example:

class Student:IStudent
{
void GetDetails()
{
}

Ravikiran
6.5. BUILDING INTERFACE HIERARCHIES 127

void CalculateGrade()
{
}
}

Interfaces With Multiple Base References

interface Getter
{
int GetData();
}
interface Setter
{
void SetData(int x);
}
interface GetterAndSetter : Getter, Setter
{
}
class MyData : GetterAndSetter
{
int data;
public int GetData()
{
return data;
}
public void SetData(int x)
{
data = x;
}
}
class MainClass
{
static void Main()
{
MyData data = new MyData();
data.SetData(5);
Console.WriteLine(”0”, data.GetData());
}
}

We can build interface hierarchies, that derives from Other Interfaces as above

Ravikiran
128 CHAPTER 6. INTERFACES AND COLLECTIONS

6.6 IConvertible Interface

Defines methods that convert the value of the implementing reference or value type to a common
language runtime type that has an equivalent value.
This interface provides methods to convert the value of an instance of an implementing type to
a common language runtime type that has an equivalent value. The common language runtime
types are Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double,
Decimal, DateTime, Char, and String.
If there is no meaningful conversion to a common language runtime type, then a particular in-
terface method implementation throws InvalidCastException. For example, if this interface is
implemented on a Boolean type, the implementation of the ToDateTime method throws an ex-
ception because there is no meaningful DateTime equivalent to a Boolean type. For example...

bool myBool = true;


IConvertible itfConv = (IConvertible)myBool;

The following are the members of IConvertible Interface

public interface IConvertible


{
TypeCode GetTypeCode();
bool ToBoolean(IFormatProvider provider);
byte ToByte(IFormatProvider provider);
char ToChar(IFormatProvider provider);
DateTime ToDateTime(IFormatProvider provider);
Decimal ToDecimal(IFormatProvider provider);
double ToDouble(IFormatProvider provider);
short ToInt16(IFormatProvider provider);
int ToInt32(IFormatProvider provider);
long ToInt64(IFormatProvider provider);
SByte ToSByte(IFormatProvider provider);
float ToSingle(IFormatProvider provider);
string ToString(IFormatProvider provider);
object ToType(Type conversionType, IFormatProvider provider);
UInt16 ToUInt16(IFormatProvider provider);
UInt32 ToUInt32(IFormatProvider provider);
UInt64 ToUInt64(IFormatProvider provider);
}

Ravikiran
6.6. ICONVERTIBLE INTERFACE 129

6.6.1 The IConvertible.ToXXXX() Members


The IConvertible interface defines number of methods of the form ToXXXX(), which will
provide a way to convert from one type to another. For example

bool myBool =true;


IConvertible convert= (IConvertible)myBool;
try
{
DateTime d=convert.ToDateTime();
}catch(InvalidCastException){ }

IFormatProvider

All the IConvertible.ToXXXX() methods takes a parameter of type IFormatProvider. Objects


that implement this interface are able to format their contents based on the culture-specific infor-
mation (for example, returning a floating point number that is formated in various currencies).

public interface IFormatProvider


{
object GetFormat(Type formatType);
}

If we are building custom type that should be formatted using various locals, we have to imple-
ment IFormatProvider

static void Main(string[] args)


{
Console.WriteLine(System.Environment.CommandLine);
int theInt = 13;
IConvertible convert = (IConvertible)theInt;
byte theByte = convert.ToByte(CultureInfo.CurrentCulture);
Console.WriteLine(”Type code int converted to byte is: 0”,
theByte.GetTypeCode());
Console.WriteLine(”Value of converted int: 0”, theByte);
}

IConvertible.GetTypeCode()

This method allows us to programmatically determine a value that represents the typecode of
the type which is represented by the following enumeration.

public enum TypeCode

Ravikiran
130 CHAPTER 6. INTERFACES AND COLLECTIONS

{
Boolean, Byte, Char, DateTime, DBNull, Decimal, Double, Empty, Int16,
Int32, Int64, Object, SByte, Single, String, UInt16,UInt32, UInt64
}
Example
public TypeCode IConvertible.GetTypeCode()
{
return TypeCode.Object;
}

6.7 Building Custom Enumerator


IEnumerator is the base class for all nongeneric enumerators. Enumerators can be used to
read the data in the collection, but they cannot be used to modify the underlying collection.
For example if we want to represent collection of individual Person objects, we can use Standard
System.ArrayType. And it would be convenient to iterate over the Person type using the C#
foreach construct in order to obtain each individual Person.

class Person
{
string name;
public Person(string name)
{
this.name = name;
}
public void Display()
{
Console.WriteLine(”Person Name : {0 }”,name);
}
}
class People
{
Person[] p;
People()
{
p = new Person[4];
p[0] = new Person(”Bandari”);
p[1] = new Person(”Ravi”);
p[2] = new Person(”Kiran”);
p[3] = new Person(”Kumar”);
}

Ravikiran
6.7. BUILDING CUSTOM ENUMERATOR 131

static void Main()


{
People p = new People();
foreach (Person temp in p)
temp.Display();
}
}

If we attempt to execute the above code, the compiler would complain that the People class
does not implement the GetEnumerator() method. This method is defined by the IEnumerable
interface.

public interface IEnumerable


{
IEnumerator GetEnumerator();
}

Thus, to rectify the problem, you may begin by updating the People definition as follows:

public class People : IEnumerable


{
// IEnumerable defines a single method.
public IEnumerator GetEnumerator()
{
...
}
}

GetEnumerator() method returns yet another interface named IEnumerator. IEnumerator can
be obtained from an object to traverse over an internal collection of types. IEnumerator is also
defined in the System.Collections namespace and defines the following three methods

// IEnumerable.GetEnumerator returns an object implementing IEnumerator


public interface IEnumerator
{
bool MoveNext(); // Advance the internal position of the cursor
object Current{get;} // Gets the Current Item (Read only Property);
void Reset(); // Reset the cursor to the begining of the cursor
}

Now given that IEnumerable.GetEnumerator() returns an IEnumerator, we have to update the


Persons type as follows

public class People : IEnumerable,IEnumerator


{

Ravikiran
132 CHAPTER 6. INTERFACES AND COLLECTIONS

// IEnumerable defines a single method.


public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
}

Finally, we have to implement MoveNext(), Current, and Reset() for the People type. Here is
one possible implementation of these members:

class Person
{
string name;
public Person(string name)
{
this.name = name;
}
public override string ToString()
{
return string.Format(”Person Name : {0 }”, name);
}
}
class People:IEnumerable,IEnumerator
{
Person[] p;
private int pos = -1;
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
People()
{
p = new Person[4];
p[0] = new Person(”Bandari”);
p[1] = new Person(”Ravi”);
p[2] = new Person(”Kiran”);
p[3] = new Person(”Kumar”);
}
object IEnumerator.Current
{
get { return p[pos]; }
}

Ravikiran
6.8. BUILDING CLONEABLE OBJECTS 133

bool IEnumerator.MoveNext()
{
if (pos <p.Length-1)
{
pos++;
return true;
}
return false;
}
void IEnumerator.Reset()
{
pos = 0;
}
static void Main()
{
People p = new People();
IEnumerator ie = p.GetEnumerator();
while (ie.MoveNext())
{
Person per = (Person)ie.Current;
Console.WriteLine(per);
}
}
}

6.8 Building Cloneable objects


Supports cloning, which creates a new instance of a class with the same value as an existing
instance. The ICloneable interface contains one member, Clone, which is intended to support
cloning. To illustrate, assume you have a simple class named Person:

class Person
{
public string name;
public int age;
Person(string name, int age)
{
this.name = name;
this.age = age;
}
public override string ToString()

Ravikiran
134 CHAPTER 6. INTERFACES AND COLLECTIONS

{
return String.Format(”Name:{0 }\nAge:{1 }”, this.name, this.age);
}
static void Main()
{
Person p1 = new Person(”Ravi”, 28);
Person p2 = p1;
p1.name = ”Kiran”;
Console.WriteLine(p2);
}
}

If we assign one object to another object, only reference will be copied. So if we change the
values of p1 the same will be affected on object p2. When we wish our custom types to return
identical copy of itself to the caller, we have to implement the standard ICloneable interface.
This type defines a single method named Clone().

public interface ICloneable


{
object Clone();
}

The basic functionality of Clone() method is to copy the value of our member variables into a
new object instance and return it to the user.

class Person
{
public string name;
public int age;
Person(string name, int age)
{
this.name = name;
this.age = age;
}
public override string ToString()
{
return String.Format(”Name: {0 }\nAge: {1 }”, this.name, this.age);
}
public object Clone()
{
return new Person(this.name,this.age);
}
static void Main()

Ravikiran
6.9. BUILDING COMPARABLE OBJECTS (ICOMPARABLE) 135

{
Person p1 = new Person(”Ravi”, 28);
Person p2 = (Person)p1.Clone();
p1.name = ”Kiran”;
Console.WriteLine(p2);
}
}

In this way, we can create exact copies of the Person type, as illustrated in the above code.
If our type (here Person) did not contain any internal reference types, then we can modify the
Clone() Method as follows

public object Clone()


{
return this.MemberWiseClone();
}

MemberWiseClone() method of object class, will perfom only shallow copy i.e. it will also copy
references of any Internal reference types. If we want to perfom deep copy we need to create a
new instance type and manually assign the inner object reference to new (identical) objects.

6.9 Building Comparable Objects (IComparable)


The IComparable interface specifies a behavior that allows an object to be sorted based on
some internal key. If we have an array of types (such as the string or the integer types) that
already support IComparer, we can sort that array without providing any explicit reference to
IComparer. In this case, the elements of the array are cast to the default implementation of
IComparer (Comparer.Default) for us. However, if we want to sort and to compare our custom
objects, we must implement either IComprable or IComprer or both of these interfaces.
The IComparable interface provides a method to compare two objects of a particular type. This
interface is used if we want to order our object. For example, if we have an array of objects of
our type, and if you call the Sort method on that array, you can use the IComparable interface
to compare the objects during the sort. When we implement the IComparable interface, you
must define the CompareTo method. For example...

using System;
using System.Collections; class Person:IComparable
{
public string name;
public int age;
public int[] arry;
Person(string name, int age)

Ravikiran
136 CHAPTER 6. INTERFACES AND COLLECTIONS

{
this.name = name;
this.age = age;
}
public override string ToString()
{
return String.Format(”Name: {0 }\n Age: {1 }”, this.name, this.age);
}
static void Main()
{
Person[] person = new Person[3];
person[0] = new Person(”Ravi”, 29);
person[1] = new Person(”Bandari”, 28);
person[2] = new Person(”Kiran”,30);
foreach (Person temp in person)
Console.WriteLine(temp);
Array.Sort(person);
Console.WriteLine(”After Sorting...”);
foreach (Person temp in person)
Console.WriteLine(temp);
}
public int CompareTo(object obj)
{
Person temp = (Person)obj;
if (this.age <temp.age)
return -1;
if (this.age >temp.age)
return 1;
return 0;
}
}

Now, in the above program Array.Sort(person) statement sorts the person array based on the
age data member of the person.

6.9.1 Specifying Multiple Sort Order


In the above example, we are sorting based on the age of the person. But if we want to sort
based on the name of the person. For this, we have to use another standard interface named
IComparer which is defined in the System.Collections namespace. This interface contains only
one method

interface IComparer

Ravikiran
6.9. BUILDING COMPARABLE OBJECTS (ICOMPARABLE) 137

{
int Compare(object obj1,object obj2);
}

Unlike IComparable interface, IComparer is not implemented on the type we are trying to sort
(here Person). Rather, we implement this interface on any of the helper objects one for each
sort order. Currently, the Person type already knows how to compare itself against other Person
type based on the age type. Therefore to allow the object Person object to sort an an array of
Person types by their name will require an additional helper class that implements the IComparer
interface. Here’s the code

class SortByName: IComparer


{
public int Compare(object obj1,object obj2)
{
Person p1=(Person)obj1;
Person p2=(Person)obj2;
return String.Compare(p1.name,p2.name);
}
}

System.Array has a number of overloaded Sort() methods, one that just happens to take an
object implementing IComparer

static void Main()


{
Person[] person = new Person[3];
person[0] = new Person(”Ravi”, 29);
person[1] = new Person(”Bandari”, 28);
person[2] = new Person(”Kiran”,30);
foreach (Person temp in person)
Console.WriteLine(temp);
// sorting is done based on the name
Array.Sort(person, new SortByName() );
Console.WriteLine(”After Sorting...”);
foreach (Person temp in person)
Console.WriteLine(temp);
}

Ravikiran
138 CHAPTER 6. INTERFACES AND COLLECTIONS

6.10 Exploring the System.Collections Namespace


6.10.1 The Interfaces of System.Collections
First of all, System.Collections defines a number of standard interfaces. Most of the classes
defined within the System.Collections namespace implement these interfaces to provide access
to their contents. The following are the some of the interfaces available in System.Collections
namespace.

1. ICollection : Defines generic characteristics (eg- read-only, thread safe ) for a collection
class.

2. IComparer : Allows two objects to be compared.

3. IDictonary : Allows an object to represent its content using name/value pairs

4. IDictonary Enumerator : Used to enumerate the contents of an object supporting


IDictonary.

5. IEnumerable : Returns the IEnumerator interface for a given object

6. IEnumerator : Generally used to support foreach-style iteration of the sub types.

7. IHashCodeProvider : Returns the hash code for the Implementing type using a cus-
tomized hash alogrithm

8. IList : Provides a behavior to add, remove, and index items in a list of objects.

6.10.2 The Role of ICollection


The ICollection interface is the most primitive interface of the System.Collections namespace.
In that it defines a behavior supported by a collection type. This interface provides a small set
of properties that allow us to determine

• the number of items in the container

• the thread-safety of the container

• the ability to copy the contents into a System.Array type

ICollection is defined as follows (again note that ICollection extends IEnumerable):

public interface ICollection : IEnumrable


{
int Count{get;}
bool IsSynchronized{ get; }
object SyncRoot{get;}
void CopyTo(Array array, int index);
}

Ravikiran
6.10. EXPLORING THE SYSTEM.COLLECTIONS NAMESPACE 139

6.10.3 The Role of IDictonary


The functionality of IDictonary is obtained by its base interfaces - ICollection and IEnumerable.
Here is the defintion of IDictonary

public interface IDictonary : IEnumrable, ICollection


{
bool IsFixedSize{get;}
bool IsReadOnly{get;}
object this[object key]{get; set; }
ICollection Keys{get;}
ICollection Values{get;}
void Add(object key, object value);
void Clear();
bool Contains(object key);
IDictonaryEnumerator GetEnumerator();
void Remove(object key);
}

6.10.4 The Role of IDictionaryEnumerator


The method IDictionary.GetEnumerator() returns an instance of the IDictionaryEnumerator
type. As we may be expecting, IDictionaryEnumerator is simply a strongly typed enumerator,
given that it extends IEnumerator by adding the following functionality:

public interface IDictionaryEnumerator : IEnumerator


{
DictonaryEntry Entry{get;}
object Key{ get; }
object Value{get;}
void CopyTo(Array array, int index);
}

IDictonaryEnumerator allows us to enumerate over items in the dictionary via the generic Entry
property, which returns a System.Collections.DictionaryEntry class type. In addition, we are
also able to traverse the name/value pairs using the Key/Value properties.

6.10.5 The Role of IHashCodeProvider


This interface contains only one Interface

public interface IHashCodeProvider


{
int GetHashCode(object obj);
}

Ravikiran
140 CHAPTER 6. INTERFACES AND COLLECTIONS

The types that implement this interface provides the ability to retrieve the hash code for a particu-
lar type (which may or may not leverage the type’s implementation of System.Object.GetHashCode()).

6.10.6 The Role of IList


The final key interface of System.Collections is IList, which provides the ability to insert, remove,
and index items into a container.

public interface IList:IEnumerable, ICollection


{
bool IsFixedSize{get;}
bool IsReadOnly{get;}
object this[int index] {get; set; }
int Add(object value);
void Clear();
bool Contains(object value);
int IndexOf(object value);
void Insert(int index,object value);
void Remove(object value);
void RemoveAt(int index);
}

6.10.7 The Class Types of System.Collections


The following are the class types that are included in the System.Collections namespace.

ArrayList

ArrayList is a useful class for shuffling elements around in an array.

• You can add an element to the end of an ArrayList by using its Add method. You supply
the element to be added. The ArrayList resizes itself if necessary.

• You can insert an element into the middle of an ArrayList by using its Insert method.
Again, the ArrayList resizes itself if necessary. For example

static void Main()


{
ArrayList array = new ArrayList();
//Adding element to Array List
array.Add(new Person(”Ravi”, 28));
Person[] p = new Person[2];
p[0] = new Person(”Kiran”, 29);
p[1] = new Person(”Kumar”, 27);

Ravikiran
6.10. EXPLORING THE SYSTEM.COLLECTIONS NAMESPACE 141

// Adding Range of elements to an array


array.AddRange(p);
//Inserting new Element into an array
array.Insert(0, new Person(”Bandari”,30));
// Removing element from an array
array.RemoveAt(3);
foreach (object o in array)
{
Person person = o as Person;
Console.WriteLine(person);
}
}

The Queue Class

The Queue class implements a first-in first-out (FIFO) mechanism. An element is inserted into
the queue at the back (the enqueue operation) and is removed from the queue at the front (the
dequeue operation). The Queue class contains three methods

1. Dequeue() : Removes and returns the object at the beginning of the Queue

2. Enqueue() : Adds an object to the end of the Queue

3. Peek() : Returns the object at the beginning of the Queue without removing it

Example

static void Main()


{
Queue q = new Queue();
q.Enqueue(new Person(”Bandari”, 28));
q.Enqueue(new Person(”Ravi”, 27));
q.Enqueue(new Person(”Kiran”, 29));
while (q.Count >0)
{
Person p = q.Dequeue() as Person;
Console.WriteLine(p);
}
Console.WriteLine(”Total Elements in Queue {0 }”,q.Count); // Prints ZERO
}

The Stack Class

The Stack class implements a last-in first-out (LIFO) mechanism. An element joins the stack at
the top (the push operation) and leaves the stack at the top (the pop operation).

Ravikiran
142 CHAPTER 6. INTERFACES AND COLLECTIONS

static void Main()


{
Stack s = new Stack();
s.Push(new Person(”Bandari”, 28));
s.Push(new Person(”Ravi”, 27));
s.Push(new Person(”Kiran”, 29));
while (q.Count >0)
{
Person p = q.Pop() as Person;
Console.WriteLine(p);
}
Console.WriteLine(”Total Elements in Stack {0 }”,s.Count); // Prints ZERO
}

The Hashtable Class

The array and ArrayList types provide a way to map an integer index to an element. We provide
an integer index inside square brackets (for example, [4]), and you get back the element at index
4 (which is actually the fifth element). However, sometimes we might want to provide a mapping
where the type you map from is not an int but rather some other type, such as string, double,
or Time. In other languages, this is often called an associative array. The Hashtable class
provides this functionality by internally maintaining two object arrays, one for the keys you’re
mapping from and one for the values you’re mapping to. When you insert a key/value pair into a
Hashtable, it automatically tracks which key belongs to which value, and enables you to retrieve
the value that is associated with a specified key. There are some important consequences of the
design of the Hashtable class:

1. A Hashtable cannot contain duplicate keys. If we call the Add method to add a key that
is already present in the keys array, we will get an exception. We can test whether a
Hashtable already contains a particular key by using the ContainsKey method.

2. When we use a foreach statement to iterate through a Hashtable, you get back a Dictio-
naryEntry. The DictionaryEntry class provides access to the key and value elements in
both arrays through the Key property and the Value properties.

Example

static void Main()


{
Hashtable ht = new Hashtable();
ht.Add(”Ravi”, new Person(”Ravi”, 28));
ht.Add(”Kiran”, new Person(”Kiran”, 29));
foreach (DictionaryEntry element in ht)

Ravikiran
6.10. EXPLORING THE SYSTEM.COLLECTIONS NAMESPACE 143

{
Console.WriteLine(”Key is {0 }”, element.Key);
Console.WriteLine(”Value is {0 }”,element.Value);
}
}

Ravikiran

You might also like