You are on page 1of 945

Visual C# 3.

0
Application Design
FunctionX Press
INDEX
1 - INTRODUCTION TO C#...............................................................................................................................14
INTRODUCTION...................................................................................................................................................14
C# is a Sharp C.............................................................................................................................................14
Console Applications....................................................................................................................................14
WRITING CODE...................................................................................................................................................16
Practical Learning: Creating a Program.....................................................................................................16
Comments......................................................................................................................................................16
Practical Learning: Creating Comments......................................................................................................16
Code Colors..................................................................................................................................................17
Indentation....................................................................................................................................................18
SOLUTION AND PROJECT MANAGEMENT............................................................................................................18
A Project........................................................................................................................................................18
Saving a Project............................................................................................................................................19
A Solution......................................................................................................................................................19
Executing a Project.......................................................................................................................................21
Practical Learning: Executing an Application.............................................................................................22
Adding a Project...........................................................................................................................................22
2 - INTRODUCTION TO VARIABLES............................................................................................................25
VARIABLES.........................................................................................................................................................25
Practical Learning: Introducing Variables..................................................................................................25
Names in C#..................................................................................................................................................25
Values and Variables on the Console...........................................................................................................27
THE NUMERIC SYSTEMS.....................................................................................................................................27
The Binary System.........................................................................................................................................28
The Decimal System......................................................................................................................................28
The Hexadecimal System...............................................................................................................................29
Signed and Unsigned.....................................................................................................................................30
Data Types....................................................................................................................................................30
REPRESENTING NUMBERS...................................................................................................................................31
A Bit...............................................................................................................................................................32
The Four-Bit Combination............................................................................................................................32
A BYTE...............................................................................................................................................................35
Characters.....................................................................................................................................................36
Escape Sequences..........................................................................................................................................37
The Byte Data Type.......................................................................................................................................38
Practical Learning: Using Bytes...................................................................................................................39
Signed Byte....................................................................................................................................................40
A WORD..............................................................................................................................................................41
Short Integers................................................................................................................................................42
Unsigned Short Integers................................................................................................................................43
Practical Learning: Using Unsigned Short Integers....................................................................................44
3 – USING VARIABLES......................................................................................................................................46
A DOUBLE-WORD...............................................................................................................................................46
Practical Learning: Using Unsigned Integers..............................................................................................48
Signed Integers..............................................................................................................................................49
Unsigned Integers.........................................................................................................................................50
Practical Learning: Using Unsigned Integers..............................................................................................51
A QUAD-WORD..................................................................................................................................................52
Long Integers................................................................................................................................................53
Unsigned Long Integers................................................................................................................................55
REAL NUMBERS..................................................................................................................................................55
Floating-Point Numbers................................................................................................................................56
Double-Precision Numbers...........................................................................................................................56
Practical Learning: Using a Double-Precision Variable.............................................................................58
Decimal.........................................................................................................................................................59
Practical Learning: Using Decimal Values..................................................................................................62
ACCESSORY DATA TYPES...................................................................................................................................63
Strings...........................................................................................................................................................63

C# 3.0 Practical Learning 2


Practical Learning: Using Strings................................................................................................................64
Dates and Times............................................................................................................................................66
Objects...........................................................................................................................................................66
CONSTANTS.........................................................................................................................................................68
Custom Constants..........................................................................................................................................68
Built-in Constants..........................................................................................................................................70
4 - INTRODUCTION TO CLASSES..................................................................................................................71
FUNDAMENTALS OF CLASSES.............................................................................................................................71
Practical Learning: Introducing Classes.................................................................................................71
Creating a Class............................................................................................................................................71
Practical Learning: Introducing Classes......................................................................................................73
Visually Managing Classes...........................................................................................................................73
Declaring a Variable of a Class Type...........................................................................................................74
Sharing a Class.............................................................................................................................................76
Garbage Collection.......................................................................................................................................76
CLASS' FIELDS....................................................................................................................................................77
Practical Learning: Introducing Class Members.........................................................................................77
ACCESSING CLASS MEMBERS.............................................................................................................................79
Private Members...........................................................................................................................................79
Internal Members..........................................................................................................................................80
INITIALIZING AN OBJECT....................................................................................................................................80
Practical Learning: Using a Class' Fields....................................................................................................82
Using an Anonymous Type............................................................................................................................83
THE METHODS OF A CLASS................................................................................................................................84
The Solution Explorer...................................................................................................................................86
Practical Learning: Creating the Methods of a Class..................................................................................87
Accessing a Method.......................................................................................................................................89
THE STATIC MEMBERS OF A CLASS...................................................................................................................90
Static Fields...................................................................................................................................................90
Static Methods...............................................................................................................................................94
Static Classes................................................................................................................................................95
CHARACTERISTICS OF MEMBERS OF A CLASS....................................................................................................96
Constants.......................................................................................................................................................96
this Instance..................................................................................................................................................96
Practical Learning: Using this......................................................................................................................97
5 - C# AND CODE ORGANIZATION...............................................................................................................99
NAMESPACES......................................................................................................................................................99
Practical Learning: Creating a Namespacep>.............................................................................................99
Accessing Members of a Namespace..........................................................................................................100
Namespace Nesting.....................................................................................................................................101
THE SYSTEM NAMESPACE................................................................................................................................102
Using a Namespace.....................................................................................................................................103
Practical Learning: Using the Keyword.....................................................................................................103
.NET SUPPORT OF DATA TYPES.......................................................................................................................103
C# LANGUAGE ACCESSORIES...........................................................................................................................104
Command Line Options...............................................................................................................................104
Unsafe Code................................................................................................................................................105
Code Editor Region Delimiter..............................................................................................................107
6 - DATA READING AND FORMATTING...................................................................................................112
DATA READING.................................................................................................................................................112
Practical Learning: Introducing Data Reading..........................................................................................112
String Value Request...................................................................................................................................112
Practical Learning: Reading String Values................................................................................................113
Number Request..........................................................................................................................................114
Practical Learning: Reading Numeric Values............................................................................................115
Requesting Dates and Times.......................................................................................................................117
Practical Learning: Requesting Date and Time Values.............................................................................118
FORMATTING DATA DISPLAY...........................................................................................................................121
Practical Learning: Displaying Data With Placeholders...........................................................................122

C# 3.0 Practical Learning 3


Conversion To String..................................................................................................................................124
Practical Learning: Converting to String...................................................................................................125
Number Formatting.....................................................................................................................................126
Practical Learning: Formatting Data Display...........................................................................................127
Line Formatting..........................................................................................................................................130
Data and Time Formatting........................................................................................................................130
Practical Learning: Controlling Date/Time Formatting............................................................................131
DETAILS ON THE METHODS OF A CLASS...............................................................................................134
METHODS AND LOCAL VARIABLES..................................................................................................................134
Practical Learning: Using a Method's Local Variables.............................................................................134
A Method that Returns a Value...................................................................................................................136
Practical Learning: Returning a Value From a Method............................................................................137
The Main Method of an Application...........................................................................................................138
METHODS' ARGUMENTS....................................................................................................................................139
Practical Learning: Passing Arguments.....................................................................................................140
TECHNIQUES OF PASSING ARGUMENTS............................................................................................................142
Passing an Argument by Value...................................................................................................................142
Passing an Argument by Reference.............................................................................................................142
Practical Learning: Passing Arguments By Reference...............................................................................145
Method Overloading...................................................................................................................................146
Practical Learning: Overloading a Method...............................................................................................147
CLASS CONSTRUCTION AND DESTRUCTION.....................................................................................................151
Method Initializer........................................................................................................................................151
Default Constructor....................................................................................................................................154
The Constructor Initializer..........................................................................................................................155
Constructor Overloading............................................................................................................................156
The Destructor of a Class...........................................................................................................................158
COMBINATIONS OF CLASSES.....................................................................................................................160
CLASSES COMBINATIONS..................................................................................................................................160
Class Nesting...............................................................................................................................................160
A Class as a Field.......................................................................................................................................164
Practical Learning: Using a Class as a Field............................................................................................165
RETURNING A CLASS OR PASSING A CLASS.....................................................................................................167
Returning a Class From a Method..............................................................................................................167
Passing a Class as Argument......................................................................................................................168
Practical Learning: Return a Class or Passing One as Argument.............................................................171
INVOLVING A CLASS AND ITS OWN METHODS.................................................................................................174
Passing a Class as its Own Argument.........................................................................................................174
Returning a Class From its Own Method...................................................................................................178
INTRODUCTION TO CONDITIONS.............................................................................................................182
BOOLEAN VARIABLES.......................................................................................................................................182
Practical Learning: Introducing Boolean Variables..................................................................................182
Declaring a Boolean Variable....................................................................................................................186
Retrieving the Value of a Boolean Variable...............................................................................................188
Creating a Boolean Field............................................................................................................................188
Boolean Arguments.....................................................................................................................................190
ENUMERATIONS................................................................................................................................................190
Declaring an Enumeration Variable...........................................................................................................192
Initializing an Enumeration Variable.........................................................................................................192
Enumerations Visibility...............................................................................................................................194
An Enumeration as a Member Variable......................................................................................................194
Practical Learning: Creating and Using Enumerations.............................................................................196
LOGICAL OPERATORS.......................................................................................................................................200
The Equality Operator ==..........................................................................................................................201
The Logical Not Operator !.........................................................................................................................202
The Inequality Operator !=.........................................................................................................................203
The Comparison for a Lower Value <........................................................................................................204
Combining Equality and Lower Value <=.................................................................................................205
The Comparison for a Greater Value >......................................................................................................205

C# 3.0 Practical Learning 4


The Greater Than or Equal Operator >=..................................................................................................206
LOGICALLY INCREMENTING OR DECREMENTING A VALUE..............................................................................207
Incrementing a Variable.............................................................................................................................207
Pre and Post-Increment..............................................................................................................................209
Decrementing a Value.................................................................................................................................210
Pre Decrementing a Value..........................................................................................................................212
Techniques of Incrementing and Decrementing a Variable.......................................................................213
CONDITIONAL STATEMENTS.....................................................................................................................216
IF ACONDITION IS TRUE...................................................................................................................................216
Practical Learning: Introducing Conditional Expressions.........................................................................216
if...................................................................................................................................................................217
Practical Learning: Using the Simple if Condition....................................................................................222
if…else.........................................................................................................................................................224
Practical Learning: Using the if...else Condition.......................................................................................226
LOGICAL CONJUNCTION: AND.........................................................................................................................229
Combining Conjunctions.............................................................................................................................236
LOGICAL DISJUNCTION: OR.............................................................................................................................239
Combinations of Disjunctions.....................................................................................................................243
CONDITIONAL SWITCHES...........................................................................................................................244
IF SWITCHES......................................................................................................................................................244
The Ternary Operator (?:)..........................................................................................................................244
Practical Learning: Introducing Conditional Switches..............................................................................245
if…else if and if…else if…else.....................................................................................................................246
CASE SWITCHES................................................................................................................................................249
Practical Learning: Using Conditional Switches.......................................................................................254
Combining Cases........................................................................................................................................258
Using Enumerations....................................................................................................................................260
COUNTING AND LOOPING...........................................................................................................................262
CONDITIONAL LOOPING....................................................................................................................................262
while a Condition is True............................................................................................................................262
do This while a Condition is True...............................................................................................................263
Practical Learning: Introducing Counting and Looping............................................................................265
for................................................................................................................................................................271
CONTROLLING THE CONDITIONAL STATEMENTS..............................................................................................272
Nesting a Conditional Statement.................................................................................................................272
Practical Learning: Nesting Conditions.....................................................................................................274
Breaking the Flow of a Conditional Statement...........................................................................................279
Continuing a Conditional Statement...........................................................................................................280
Going to a Designated Label......................................................................................................................281
Conditional Return......................................................................................................................................281
RECURSION.......................................................................................................................................................283
Creating a Recursive Methods....................................................................................................................284
Using Recursive Methods............................................................................................................................285
THE PROPERTIES OF A CLASS...................................................................................................................287
OVERVIEW OF PROPERTIES...............................................................................................................................287
Accessories for Properties..........................................................................................................................287
Practical Learning: Introducing Properties...........................................................................................288
TYPES OF PROPERTIES......................................................................................................................................289
Property Readers........................................................................................................................................289
Practical Learning: Creating Property Readers........................................................................................292
Property Writers..........................................................................................................................................295
Read/Write Properties.................................................................................................................................297
Practical Learning: Creating Property Writers.........................................................................................297
A Boolean Property.....................................................................................................................................300
PROPERTIES OF EXTERNAL CLASSES................................................................................................................301
Properties and Enumerations.....................................................................................................................301
Practical Learning: Creating an Enumeration Property............................................................................301
A Class as a Property..................................................................................................................................304

C# 3.0 Practical Learning 5


Practical Learning: Creating a Property of a Class Type..........................................................................305
INHERITANCE..................................................................................................................................................311
INTRODUCTION TO INHERITANCE.....................................................................................................................311
Practical Learning: Introducing Inheritance..............................................................................................311
Class Derivation..........................................................................................................................................317
Practical Learning: Inheriting....................................................................................................................322
Implementation of Derived Members..........................................................................................................328
The new Modifier........................................................................................................................................332
POLYMORPHISM AND ABSTRACTION.....................................................................................................334
CHARACTERISTICS OF INHERITANCE................................................................................................................334
Namespaces and Inheritance......................................................................................................................334
Practical Learning: Using Inheritance With Namespaces.........................................................................336
Protected Members.....................................................................................................................................337
Virtual Members..........................................................................................................................................339
Practical Learning: Using Virtual Members..............................................................................................340
Abstract Classes..........................................................................................................................................343
Practical Learning: Creating an Abstract Class........................................................................................343
Abstract Properties and Methods................................................................................................................344
Practical Learning: Creating an Abstract Property...................................................................................344
Sealed Classes.............................................................................................................................................347
INTERFACES......................................................................................................................................................348
Practical Learning: Introducing Interfaces................................................................................................348
The Members of an Interface......................................................................................................................348
Practical Learning: Creating Members of an Interface.............................................................................349
AN INTERFACE AS A BASE CLASS....................................................................................................................350
Practical Learning: Inheriting From an Interface......................................................................................351
Implementation of Derived Classes of an Interface....................................................................................352
Practical Learning: Implementing Derived Members of an Interface........................................................354
Class Partial Implementation.....................................................................................................................358
Practical Learning: Partially Implementing a Class..................................................................................363
DELEGATES AND EVENTS............................................................................................................................369
FUNDAMENTALS OF DELEGATES......................................................................................................................369
Practical Learning: Introducing Delegates................................................................................................369
Creating a Delegate....................................................................................................................................374
ACCESSING A DELEGATE..................................................................................................................................375
A Static Method for a Delegate...................................................................................................................376
An Anonymous Delegate.............................................................................................................................377
The Lambda Operator.................................................................................................................................378
A Delegate that Returns a Value.................................................................................................................379
Delegates Compositions..............................................................................................................................380
DELEGATES AND ARGUMENTS.........................................................................................................................380
Using an Argumentative Delegate..............................................................................................................381
A Lambda Expression.................................................................................................................................382
A Delegate With Many Arguments..............................................................................................................384
Practical Learning: Passing Arguments to a Delegate..............................................................................385
A Delegate Passed as Argument.................................................................................................................388
DELEGATES AND CLASSES................................................................................................................................392
A Delegate that Returns an Object..............................................................................................................393
A Delegate that Takes an Object as Argument...........................................................................................395
EVENTS.............................................................................................................................................................396
Event Creation............................................................................................................................................397
STRUCTURES....................................................................................................................................................400
FUNDAMENTALS OF STRUCTURES....................................................................................................................400
Structure Declaration..................................................................................................................................401
TECHNIQUES OF USING STRUCTURES...............................................................................................................402
A Structure as a Property............................................................................................................................402
Returning a Structure From a Method........................................................................................................404
Passing a Structure as Argument................................................................................................................405

C# 3.0 Practical Learning 6


BUILT-IN STRUCTURES: THE INTEGRAL DATA TYPES.....................................................................................409
Conversion to a String................................................................................................................................409
Parsing a String..........................................................................................................................................409
The Minimum and Maximum Values of a Primitive Type...........................................................................412
Value Comparisons.....................................................................................................................................415
BUILT-IN STRUCTURES: THE BOOLEAN TYPE..................................................................................................418
Parsing a Boolean Variable........................................................................................................................418
Comparisons of Boolean Variables............................................................................................................420
FLOATING-POINT NUMBERS.............................................................................................................................422
Operations on Floating-Point Numbers......................................................................................................423
Comparison Operations..............................................................................................................................424
BUILT-IN CLASSES..........................................................................................................................................426
THE OBJECT CLASS..........................................................................................................................................426
Practical Learning: Introducing Ancestor Classes.....................................................................................426
Equality of Two Class Variables.................................................................................................................428
Practical Learning: Implementing Equality...............................................................................................429
Stringing a Class.........................................................................................................................................430
Practical Learning: Converting to String...................................................................................................431
Boxing and Un-Boxing................................................................................................................................434
Finalizing a Variable..................................................................................................................................435
Other Built-In Classes.................................................................................................................................435
RANDOM NUMBERS...........................................................................................................................................435
Getting a Random Number..........................................................................................................................435
The Seed of a Random Number...................................................................................................................437
Generating Random Numbers in a Range of Numbers...............................................................................438
BUILT-IN ASSEMBLIES AND LIBRARIES............................................................................................................440
Microsoft Visual Basic Functions...............................................................................................440
C# CUSTOM LIBRARIES....................................................................................................................................441
Creating a Library......................................................................................................................................441
Practical Learning: Creating a Library.....................................................................................................442
A LIBRARY CREATED IN ANOTHER LANGUAGE...............................................................................................445
Using a Visual C++/CLI Library...............................................................................................................445
Creating a Library......................................................................................................................................445
Using the Library........................................................................................................................................446
Using the Win32 Library.............................................................................................................................447
INTRODUCTION TO EXCEPTION HANDLING........................................................................................448
INTRODUCTION TO EXCEPTIONS.......................................................................................................................448
Overview.....................................................................................................................................................448
Practical Learning: Introducing Exception Handling................................................................................449
Exceptional Behaviors................................................................................................................................452
Practical Learning: Introducing Vague Exceptions...................................................................................454
Exceptions and Custom Messages..............................................................................................................456
Practical Learning: Displaying Custom Messages.....................................................................................456
EXCEPTIONS IN THE .NET FRAMEWORK..........................................................................................................458
The Exception Class....................................................................................................................................458
The Exception's Message............................................................................................................................459
Custom Error Messages..............................................................................................................................460
A REVIEW OF .NET EXCEPTION CLASSES........................................................................................................462
The FormatException Exception.................................................................................................................462
Practical Learning: Using the FormatException Class..............................................................................463
The OverflowException Exception..............................................................................................................467
The ArgumentOutOfRangeException Exception.........................................................................................468
The DivideByZeroException Exception......................................................................................................468
USING EXCEPTION HANDLING..................................................................................................................470
TECHNIQUES OF USING EXCEPTIONS................................................................................................................470
Practical Learning: Using Exceptions........................................................................................................470
Throwing an Exception...............................................................................................................................479
Practical Learning: Throwing an Exception..............................................................................................480
Catching Various Exceptions......................................................................................................................482

C# 3.0 Practical Learning 7


Practical Learning: Catching Various Exceptions.....................................................................................486
Exception Nesting........................................................................................................................................493
Exceptions and Methods.............................................................................................................................495
CUSTOM EXCEPTIONS.......................................................................................................................................500
Creating an Exceptional Class....................................................................................................................500
INTRODUCTION TO ARRAYS......................................................................................................................503
A SERIES OF SIMILAR ITEMS............................................................................................................................503
Practical Learning: Introducing Arrays.................................................................................................504
Array Creation............................................................................................................................................504
Practical Learning: Creating an Array......................................................................................................505
Introduction to Initializing an Array...........................................................................................................505
Practical Learning: Initializing Some Arrays.............................................................................................507
Other Techniques of Initializing an Array..................................................................................................508
ACCESSING THE MEMBERS OF AN ARRAY.......................................................................................................510
Practical Learning: Using the Members of an Array.................................................................................511
For an Indexed Member of the Array.........................................................................................................512
Practical Learning: Using a for Loop........................................................................................................515
For Each Member in the Array...................................................................................................................517
ANONYMOUS ARRAYS......................................................................................................................................518
Creating an Anonymous Array....................................................................................................................518
Accessing the Members of an Anonymous Array........................................................................................520
SELECTING A VALUE FROM AN ARRAY...........................................................................................................522
Using for and foreach.................................................................................................................................522
Practical Learning: Checking a Value From an Array..............................................................................523
ARRAYS AND CLASSES..................................................................................................................................526
AN ARRAY OF A PRIMITIVE TYPE AS A FIELD.................................................................................................526
Practical Learning: Introducing Arrays and Classes............................................................................527
Presenting the Array...................................................................................................................................528
Practical Learning: Presenting an Array...............................................................................................529
ARRAYS AND METHODS...................................................................................................................................530
An Array Passed as Argument....................................................................................................................531
Returning an Array From a Method...........................................................................................................533
MAIN()'S ARGUMENT........................................................................................................................................535
Command Request from Main()..................................................................................................................536
AN ARRAY OF OBJECTS....................................................................................................................................538
Practical Learning: Introducing Arrays of Objects....................................................................................539
Creating an Array of Objects......................................................................................................................540
Initializing an Array of Objects...................................................................................................................541
Accessing the Members of the Array...........................................................................................................543
Practical Learning: Using an Array of Objects..........................................................................................545
A CLASS ARRAY AS A FIELD............................................................................................................................547
Using the Array...........................................................................................................................................548
ARRAYS OF OBJECTS AND METHODS...............................................................................................................551
Passing an Array of Objects as Argument..................................................................................................551
Returning an Array of Objects....................................................................................................................552
Practical Learning: Using Array of Objects With Methods.......................................................................554
ARRAYS AND DELEGATES................................................................................................................................556
An Array of Delegates.................................................................................................................................557
MULTIDIMENSIONAL ARRAYS..................................................................................................................560
FUNDAMENTALS OF MULTIDIMENSIONAL ARRAYS..........................................................................................560
Practical Learning: Introducing Multidimensional Arrays........................................................................560
Creating a Two-Dimensional Array............................................................................................................561
Practical Learning: Creating a Two-Dimensional Array...........................................................................563
Accessing the Members of a Two-Dimensional Array................................................................................564
Practical Learning: Accessing the Members..............................................................................................567
MULTIDIMENSIONAL ARRAYS..........................................................................................................................569
Creating a Multidimensional Array............................................................................................................569
Initializing a Multidimensional Array.........................................................................................................570
Access to Members of a Multidimensional Array.......................................................................................570

C# 3.0 Practical Learning 8


MULTIDIMENSIONAL ARRAYS AND CLASSES...................................................................................................575
A Multidimensional Array as Argument.....................................................................................................577
Returning a Multi-Dimensional Array........................................................................................................578
A MULTIDIMENSIONAL ARRAY OF OBJECTS....................................................................................................580
A Variable of a Multidimensional Array of Objects...................................................................................580
Accessing the Members of a Multidimensional Array of Objects...............................................................583
MULTIDIMENSIONAL ARRAYS OF OBJECTS AND CLASSES...............................................................................584
Passing a Multidimensional Array of Objects............................................................................................586
Returning a Multidimensional Array of Objects.........................................................................................587
INTRODUCTION TO JAGGED ARRAYS................................................................................................................589
Practical Learning: Introducing Jagged Arrays.........................................................................................589
Initialization of a Jagged Array..................................................................................................................590
Practical Learning: Initializing a Jagged Array........................................................................................591
Access to Members of a Jagged Array........................................................................................................593
Practical Learning: Using a Jagged Array................................................................................................595
THE ARRAY CLASS.........................................................................................................................................599
INTRODUCTION TO THE ARRAY CLASS.............................................................................................................599
Overview.....................................................................................................................................................599
The Length of an Array...............................................................................................................................600
The Rank of an Array..................................................................................................................................601
FUNDAMENTAL OPERATIONS ON AN ARRAY....................................................................................................601
Adding Items to an Array............................................................................................................................601
Accessing the Members of an Array............................................................................................................602
MULTIDIMENSIONAL ARRAYS..........................................................................................................................603
Two-Dimensional Arrays............................................................................................................................604
Three-Dimensional Arrays..........................................................................................................................606
Multidimensional Arrays.............................................................................................................................611
ARRANGING THE LIST.......................................................................................................................................612
Arranging the Items in Alphabetical or Numerical Order..........................................................................612
Reversing the Arrangement.........................................................................................................................613
LOCATING AN ELEMENT IN AN ARRAY............................................................................................................613
Locating the Index of an Element................................................................................................................613
The Bounds of an Array..............................................................................................................................614
STRINGS.............................................................................................................................................................616
THE CHARACTERS OF A STRING.......................................................................................................................616
Practical Learning: Introducing Strings.....................................................................................................616
The String: An Array of Characters............................................................................................................626
Converting Characters to the Opposite Case.............................................................................................627
Replacing a Character................................................................................................................................628
WORKING WITH STRINGS.................................................................................................................................629
The Length of a String.................................................................................................................................630
Practical Learning: Using Characters of a String.....................................................................................631
Replacing a Sub-String...............................................................................................................................635
Formatting a String.....................................................................................................................................635
Copying a String.........................................................................................................................................636
OPERATIONS ON STRINGS.................................................................................................................................637
String Concatenation..................................................................................................................................637
STRINGS COMPARISONS....................................................................................................................................638
String Equality............................................................................................................................................640
WORKING WITH SUB-STRINGS.........................................................................................................................640
Sub-String Creation....................................................................................................................................641
INTRODUCTION TO INDEXERS..................................................................................................................642
A PROPERTY CAN BE INDEXED........................................................................................................................642
Practical Learning: Introducing Indexed Properties.................................................................................642
An Indexer...................................................................................................................................................647
Indexed Properties of Other Primitive Types..............................................................................................648
Using a Non-Integer-Based Index...............................................................................................................650
Practical Learning: Creating an Indexer...................................................................................................653
TOPICS ON INDEXED PROPERTIES.....................................................................................................................655

C# 3.0 Practical Learning 9


Multi-Parameterized Indexed Properties....................................................................................................655
Overloading an Indexed Property...............................................................................................................659
READ/WRITE INDEXED PROPERTIES.................................................................................................................662
A Read/Write Property of a Primitive Type................................................................................................663
CLASSES AND INDEXERS..............................................................................................................................666
FUNDAMENTALS OF INDEXED PROPERTIES AND CLASSES...............................................................................666
Practical Learning: Introducing Indexers and Classes..............................................................................666
An Integer-Based Indexed Property............................................................................................................671
Practical Learning: Using an Integer-Based Indexer................................................................................673
An Indexed Property Using Another Primitive Type..................................................................................674
TOPICS ON INDEXED PROPERTIES AND CLASSES..............................................................................................678
A Class as Index..........................................................................................................................................678
Overloading a Class-Based Indexed Property............................................................................................682
Practical Learning: Overloading an Indexer.............................................................................................691
Read/Write Indexed Properties...................................................................................................................692
INTRODUCTION TO COLLECTIONS..........................................................................................................695
ARRAY-BASED LISTS........................................................................................................................................695
Setting Up a Collection...............................................................................................................................695
The Number of Items in a Collection..........................................................................................................696
ROUTINE OPERATIONS ON AN ARRAY-BASED LIST.........................................................................................697
Adding an Item............................................................................................................................................698
Getting an Item From a List........................................................................................................................699
Inserting an Item in the List........................................................................................................................701
Removing an Item From the List.................................................................................................................703
A COLLECTION OF ITEMS.................................................................................................................................707
Practical Learning: Introducing Collections..............................................................................................707
Implementing a Collection..........................................................................................................................714
Practical Learning: Creating a Class Collection.......................................................................................716
The Beginning of a Collection.....................................................................................................................716
Linking the Items of a Collection................................................................................................................717
Practical Learning: Creating a List's Monitor.......................................................................................718
OPERATIONS ON A COLLECTION.......................................................................................................................719
Adding an Item............................................................................................................................................719
Practical Learning: Adding Items to a Collection......................................................................................720
Retrieving an Item.......................................................................................................................................721
Practical Learning: Retrieving the Items of a Collection...........................................................................722
Removing an Item........................................................................................................................................725
Practical Learning: Retrieving the Items of a Collection...........................................................................726
Locating an Item.........................................................................................................................................730
ITERATING THROUGH A COLLECTION..................................................................................................734
ENUMERATING THE MEMBERS OF A COLLECTION...........................................................................................734
Introduction to System Collections..........................................................................................................734
Practical Learning: Introducing Built-In Collections................................................................................734
Introduction to the IEnumerator Interface..................................................................................................737
Practical Learning: Introducing Enumerations..........................................................................................738
The Current Item of an Enumeration..........................................................................................................739
Practical Learning: Getting to the Current Item........................................................................................739
Resetting the Tag of the Current Item.........................................................................................................740
Practical Learning: Resetting the Tag of the Current Item........................................................................741
Moving to the Next Item in the Enumerator................................................................................................742
Practical Learning: Moving to the Next Item in the Enumerator...............................................................743
AN ENUMERABLE COLLECTION........................................................................................................................744
Getting the Enumerator...............................................................................................................................744
Practical Learning: Getting the Enumerator..............................................................................................745
Using foreach..............................................................................................................................................746
Practical Learning: Using foreach on an Enumerator...............................................................................748
INTRODUCTION TO BUILT-IN COLLECTION CLASSES......................................................................751
OVERVIEW OF .NET COLLECTIONS..................................................................................................................751

C# 3.0 Practical Learning 10


The ICollection Interface.....................................................................................................................751
Introduction to the ArrayList Class.............................................................................................................751
Practical Learning: Introducing the ArrayList Class.................................................................................751
The Capacity of a List.................................................................................................................................755
A Read-Only List.........................................................................................................................................756
Item Addition...............................................................................................................................................756
Practical Learning: Adding Items to an ArrayList List..............................................................................756
The Number of Items in the List..................................................................................................................769
Item Retrieval..............................................................................................................................................769
Practical Learning: Retrieving Items From an ArrayList List...................................................................770
Item Location..............................................................................................................................................792
Item Deletion...............................................................................................................................................793
GENERICS..........................................................................................................................................................794
GENERIC METHODS..........................................................................................................................................794
Practical Learning: Introducing Generics.............................................................................................795
Generic Method Creation...........................................................................................................................798
Practical Learning: Creating a Generic Method........................................................................................798
Calling a Generic Method...........................................................................................................................799
Practical Learning: Calling a Generic Method..........................................................................................800
A GENERIC METHOD WITH VARIOUS PARAMETERS........................................................................................801
Practical Learning: Using a Method With Various Parameters................................................................802
A Generic Method With Various Parameter Types.....................................................................................803
Calling a Generic Method With Various Parameter Types........................................................................804
GENERIC CLASSES............................................................................................................................................805
Practical Learning: Introducing Generic Classes.................................................................................806
Using a Generic Class................................................................................................................................808
Passing a Parameter Type to a Method......................................................................................................809
Returning a Parameter Type.......................................................................................................................810
Practical Learning: Returning a Parameter Type......................................................................................811
A Property of the Parameter Type..............................................................................................................813
A GENERIC CLASS WITH MULTIPLE PARAMETERS..........................................................................................814
Using Multiple Type Parameters................................................................................................................814
A Class as a Parameter Type......................................................................................................................816
GENERIC CLASSES AND INHERITANCE..............................................................................................................818
Generic Classes and Interfaces...................................................................................................................823
Constraining a Generic Class.....................................................................................................................824
INTRODUCTION TO FILE PROCESSING...................................................................................................829
OVERVIEW OF FILE PROCESSING AND DEFINITIONS.........................................................................................829
Files.............................................................................................................................................................829
Streams........................................................................................................................................................829
STREAMING PREREQUISITES.............................................................................................................................830
Practical Learning: Introducing Streaming................................................................................................830
The Name of a File......................................................................................................................................836
Practical Learning: Specifying the Name of a File....................................................................................837
The Path to a File........................................................................................................................................838
THE .NET SUPPORT FOR FILES.........................................................................................................................839
File Existence..............................................................................................................................................840
Practical Learning: Checking the Existence of a File................................................................................840
File Creation...............................................................................................................................................842
Access to a File...........................................................................................................................................842
File Sharing.................................................................................................................................................843
The Mode of a File......................................................................................................................................843
FUNDAMENTALS OF FILE STREAMING..............................................................................................................844
Practical Learning: Creating a Stream......................................................................................................844
Stream Writing............................................................................................................................................845
Stream Closing............................................................................................................................................846
Practical Learning: Writing to a Stream....................................................................................................847
Stream Reading...........................................................................................................................................850
Practical Learning: Reading From a Stream.............................................................................................851
DETAILS ON FILE PROCESSING.................................................................................................................862

C# 3.0 Practical Learning 11


EXCEPTION HANDLING IN FILE PROCESSING....................................................................................................862
Finally.........................................................................................................................................................862
Practical Learning: Finally Releasing Resources......................................................................................864
.NET Framework Exception Handling for File Processing........................................................................874
Practical Learning: Handling File Processing Exceptions........................................................................876
FILE INFORMATION...........................................................................................................................................884
Practical Learning: Introducing File Information...............................................................................884
File Initialization.........................................................................................................................................887
File Creation...............................................................................................................................................887
File Existence..............................................................................................................................................888
Writing to a File..........................................................................................................................................889
Practical Learning: Writing to a File.........................................................................................................889
Appending to a File.....................................................................................................................................890
Practical Learning: Appending to a File....................................................................................................890
FILES OPERATIONS........................................................................................................................................893
ROUTINE OPERATIONS ON FILES......................................................................................................................893
Opening a File.............................................................................................................................................893
Deleting a File.............................................................................................................................................893
Copying a File.............................................................................................................................................894
Moving a File..............................................................................................................................................894
CHARACTERISTICS OF A FILE............................................................................................................................895
The Date and Time a File Was Created......................................................................................................895
The Date and Time a File Was Last Accessed............................................................................................896
The Name of a File......................................................................................................................................896
The Extension of a File...............................................................................................................................896
The Size of a File.........................................................................................................................................897
The Path to a File........................................................................................................................................897
The Attributes of a File...............................................................................................................................898
DIRECTORIES.....................................................................................................................................................898
Practical Learning: Introducing Directories..............................................................................................899
Directory Creation......................................................................................................................................900
Checking for a Directory Existence............................................................................................................901
Locating a File............................................................................................................................................901
Practical Learning: Using Directories and Files.......................................................................................901
SERIALIZATION..............................................................................................................................................914
OBJECT SERIALIZATION AND DE-SERIALIZATION............................................................................................914
Practical Learning: Introducing Serialization............................................................................................917
Serialization................................................................................................................................................920
Practical Learning: Serializing an Object..................................................................................................922
De-Serialization..........................................................................................................................................934
Practical Learning: De-Serializing an Object............................................................................................936
SOAP SERIALIZATION......................................................................................................................................939
Practical Learning: Introducing SOAP Serialization.................................................................................939
Serialization With SOAP.............................................................................................................................942
Practical Learning: Serializing With SOAP...............................................................................................943
De-Serialization With SOAP.......................................................................................................................945
Practical Learning: Deserializing With SOAP...........................................................................................946
DETAILS ON SERIALIZATION.............................................................................................................................949
Partial Serialization....................................................................................................................................949
Implementing a Custom Serialized Class....................................................................................................952
.NET Built-In Serialized Classes.................................................................................................................952

C# 3.0 Practical Learning 12


1 - Introduction to C#
 

Introduction
 

C# is a Sharp C

C#, pronounced c sharp, is a computer language used to give instructions that tell the
computer what to do, how to do it, and when to do it. This is a universal language that is
used on many operating systems, including Microsoft Windows. C# is one of the
languages used in the Microsoft .NET Framework. The Microsoft .NET Framework is a
library of objects that create or draw things on the computer.

Console Applications

The C# language is used to create applications that display on a black window referred to
as the DOS prompt or DOS window. Those are the types of applications we will create in
our lessons.

To study the C# language, we will use Microsoft Visual C# 2008 Express Edition or
Microsoft Visual C# 2008 Professional. To get Microsoft Visual C# 2008 Express Edition,
you can download it free from the Microsoft web site. After downloading it, you can
install it.

To launch Microsoft Visual C# 2008 Express Edition, you can click Start -> (All) Programs
-> Microsoft Visual C# 2008 Expression Edition:
To launch Microsoft Visual C# 2008 Professional, you can click Start -> (All) Programs ->
Microsoft Visual Studio 2008. To create the type of applications we will study in our
lessons, on the main menu, you can click File -> New Project... In the Templates section
of the New Project dialog box, you can click Console Application, accept the default name
or change it:

After clicking OK, a skeleton code would be created for you. Right now, we will not review
every part of the code. Everything will be introduced and explained as we move on.

C# 3.0 Practical Learning 14


Writing Code
 

Introduction

The programs we will write are meant to give instructions to the computer about what to
do, when to do something, and how to do it. You write these instructions in an easy to
understand English format, using words we will study. This means that a regular
instruction uses normal text with alphabetic characters, numbers, and non-readable
symbols. Normally, you can write your instructions using any text editor such as Notepad,
WordPad, WordPerfect, or Microsoft Word, etc. When writing your instructions, there are
rules your must follow and suggestions you should observe. We sill study each one of
them as we move on.

The group of instructions used by your program is also referred to as code. To assist you
with writing code, Microsoft Visual C# 2008 includes a text editor referred to as the Code
Editor. This is the window that displays when you have just created a console application.
Besides the Code Editor, the integrated development interface (IDE) of the Microsoft
Visual C# 2008 is made of various parts, which we will review when necessary.

Practical Learning: Creating a Program

1. Start Microsoft Visual C# 2008 Express Edition or Microsoft Visual C# 2008


Professional

2. To create a new application, on the Start Page, on the right side of Create, click
Project

3. In the Templates section, click Console Application

4. Change the Name to GeorgetownCleaningServices1 and click OK

Comments

A comment is a line or paragraph of text that will not be considered as part of your code
of a program. There are two types of comments recognized by C#.

To display a comment on a line of text, start the line with two forward slashes //. Anything
on the right side of // would be ignored. Here is an example:
// This line will be ignored. I can write in it anything I want

The above type of comment is used on only one line. You can also start a comment
with /*. This type of comment ends with */. Anything between this combination of /* and
*/ would not be read. Therefore, you can use this technique to span a comment on more
than one line.

Practical Learning: Creating Comments

1. To create comments, change the file as follows:


 

C# 3.0 Practical Learning 15


using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Text;
/*
namespace GeorgetownCleaningServices1
{*/
class Program
{
static void Main(/* string[] args */)
{
}
}
//}

2. To save the project, on the Standard toolbar, click the Save All button
 

3. Accept the name as GeorgetownCleaningServices1 and click Save

Code Colors

Code is written in a wide area with a white background. This is the area you use the
keyboard to insert code with common readable characters. The Code Editor uses some
colors to differentiate categories of words or lines of text. The colors used are highly
customizable. To change the colors, on the main menu, you can click Tools -> Options...
In the Options dialog box, in the Environment section, click Fonts and Colors. To set the
color of a category, in the Display Items section, click the category. In the Item
Foreground combo box, select the desired color. If you want the words of the category to
have a colored background, click the arrow of the Item Background combo box and select
one:

C# 3.0 Practical Learning 16


In both cases, the combo boxes display a fixed list of colors. If you want more colors, you
can click a Custom button to display the Color dialog box that allows you to "create" a
color.

Indentation 

Indentation is another feature that makes your program easy to read. Indentation is a
technique of grouping lines of code by category. To delimit the items of your code, you
should indent them by two empty spaces or one tab. Indentation should be incremental.
That is, when a line of code appears to be a child of the previous line, the new line should
be indented.

Solution and Project Management


 

A Project 

We have seen how to create a console application. Microsoft Visual C# allows you to
create various other types of applications. This is why you should first display the New
Project dialog box to select your option. Besides console applications, in future lessons, we
will start some applications with the Empty Project. We will also learn how to create a
library using the Class Library option. We will ignore the other three options in this book.

To control the indentation of your code, on the main menu, click Tools -> Options... In the
left list, expand C#, followed by Formatting and click Indentation. Then change the
options on the right side:

C# 3.0 Practical Learning 17


After making the changes, click OK to validate or Cancel to ignore.

Saving a Project 

In previous versions of Microsoft Visual C# (namely 2002 and 2003), you always had to
formally create a project in order to use one and you always had to save it. After realizing
that many of the projects that developers or students create are for experimental
purposes, Microsoft provided the ability to only temporarily create a project, then to save
it or not. Saving a project allows you to keep on a medium so you can refer to it later.

When Microsoft Visual Studio 2008 (any edition) is installed, it creates a folder named
Visual Studio 2008 in your My Documents folder. The My Documents folder is called your
personal drive or your personal directory. Inside of the Visual Studio 2008 folder, it creates
a sub-folder named Projects. By default, this is where it would save your projects, each
with its own folder.

To save a project, on the Standard toolbar, you can click the Save All button .
Alternatively, on the main menu, you can click File -> Save All. If the project had already
been saved but you want to save it under a different name, on the main menu, you can
click File -> Save project name As...

A Solution

A solution is used to coordinate the different aspects of an application that is being


created. When you create a project, it represents one detail of the application you have in
mind. Besides the code you are writing, you may want to add other items. Instead of one
project, in the next sections, we will see that a solution can contain more than one
project.

When creating a project, the solution holds the same name as the project. You can see
their names in the Solution Explorer:
C# 3.0 Practical Learning 18
The solution and a project can have different names. While working on a project, to
rename the solution, in the Solution Explorer, you can click the first node, which is the
name of the solution starting with Solution. Then, in the Properties window, click (Name)
and type the name of your choice:

This name is temporary, especially if you have not yet saved the project. If you want to
permanently save a solution for later use, there are two techniques you can use.

If you start saving a project for the first time, it would bring the Save Project dialog box.
By default, Microsoft Visual Studio selects your personal directory as the path to the
solution. This is called the location. In the location, Microsoft Visual Studio creates a folder
as the solution of the project. The solution must have, or must be stored, in its own
folder. As mentioned earlier, Microsoft Visual Studio uses the name of the project as the
name of the solution. To rename the solution, you can change the string in the Solution
Name text box. Remember that you can enter the name of the project in the Name text
box. Here is an example:

C# 3.0 Practical Learning 19


When you save a project (for the first time), by default, Microsoft Visual C# creates a new
folder for it in the My Documents\Visual Studio 2008\Projects folder. It uses the name of
the solution to name the folder. It creates some files and stores them in that new folder.
Then, it creates a sub-folder, using the name of the project, inside of the folder of the
solution. Besides the sub-folder with the name as the project, it creates another folder
named debug. It also creates another folder named Debug in the sub-folder of the name
of the project. In each folder and some other folders, it creates some files that we will not
pay attention to for now.

If the project had already been saved but you want to change the name of the solution,
on the main menu, you can click File -> Save solution-name.sln As... This would bring the
Save File As dialog box where you can specify the name of the solution and click Save.

Executing a Project

After creating a project and writing code, you may want to see the result. To do this, you
must execute the application. This would create an executable that you can use on other
computers and that you can distribute to other people.

To execute an application, on the main menu, you can click Debug -> Start Without
Debugging. Instead of going through the main menu every time, you can add the Start
Without Debugging button to a toolbar. To do this, you can right-click any toolbar and
click Customize... In the Commands property page of the Customize dialog box, you can
click Debug in the Categories click, then drag Start Without Debugging, and drop it on a
toolbar. Here is an example:

C# 3.0 Practical Learning 20


After adding the button(s), you can click Close. The next time you want to execute an
application, you can just click this button.

Practical Learning: Executing an Application

1. To execute the application, on the main menu, click Debug -> Start Without
Debugging

2. After viewing the result in a DOS window, press Enter to close it

Adding a Project 

One of the most valuable features of Microsoft Visual Studio 2005 is that it allows you to
work on more than one project without launching more than one instance of the studio.
This means that you can add a project to another project you are working on and treat
each as a separate entity.

C# 3.0 Practical Learning 21


Before adding one project to another, you must save, or you must have saved, the current
project. To add a project, in the Solution Explorer, you can right-click the most top node
(it starts with Solution) and position the mouse on Add:

If you have a project that was previously saved but you don't want to open a separate
instance of Microsoft Visual Studio for it, you can click Existing Project... This would bring
the Add Existing Project dialog box that allows you to select a project from a folder.

To add a new project, after right-clicking, you can click New Project... If you add a new
project, and if you want to keep it for future references, you must save it. To save the
new project, you can click the Save All button on the Standard toolbar. After saving the
new project, a folder with its name would be created inside of the folder of the solution.

On the right side of the name of the solution in Solution, the number of its projects is
specified in parentheses, as 1 project, or 2 projects, etc.

After adding a project, each would be represented by its own node in the Solution
Explorer and in the Class View. Here is an example:

Also, a sub-folder for each project is created in the folder of the solution:

C# 3.0 Practical Learning 22


In the Solution, the name of one of the projects, if there is more than one, is in bold
characters. This project is called the StartUp Project. If, on the main menu, you click
Debug -> Start Without Debugging, the project in bold characters would be executed. If
you want to change the start up project, you can right-click its node and click Set As
StartUp Project.

C# 3.0 Practical Learning 23


2 - INTRODUCTION TO
VARIABLES
 

Variables
 

Definition

A computer receives information from different applications in various forms.


Sometimes a person types it using the keyboard. Sometimes the user  clicks the mouse.
Sometimes information comes from another, more complicated source. The idea is that
the computer spends a great deal of its time with various pieces of information.
Information provided to the computer through a program is called datum and the plural is
data. Sometimes the word data is used both for singular and plural items.

Data used by the computer comes and goes regularly as this information changes. For this
reason, such information is called a variable.

When the user enters data in a program, the computer receives it and must store it
somewhere to eventually make it available to the program as needed. For a program used
to process employment applications, the types of information a user would enter into the
program are the name, the residence, the desired salary, years of experience, education
level, etc. Because there can be so much information for the same program, you must
specify to the computer what information you are referring to and when. To do this, each
category of piece of information must have a name.

Practical Learning: Introducing Variables

1. Start Microsoft Visual C# 2008 Express Edition or Microsoft Visual C# 2008


Professional
 

From now on, we will only refer to Microsoft Visual C#

2. To create a new application, on the Start Page, on the right side of Create, click
Project

3. In the Templates section, click Console Application

4. Change the Name to GeorgetownCleaningServices2 and click OK

Names in C#

C# 3.0 Practical Learning 24


To name the variables of your program, you must follow strict rules. In fact, everything else in
your program must have a name. C# uses a series of words, called keywords, for its internal
use. This means that you must avoid naming your objects using one of these keywords. They
are:

abstract const extern int out short typeof

as continue false interface override sizeof uint

base decimal finally internal params stackalloc ulong

bool default fixed is private static unchecked

break delegate float lock protected string unsafe

byte do for long public struct ushort

case double foreach namespace readonly switch using

catch else goto new ref this virtual

char enum if null return throw void

checked event implicit object sbyte true volatile

class explicit in operator sealed try while

Besides these keywords, C# has other words that should be reserved only depending on how
and where they are used. These are referred to as contextual keywords and they are:

get partial set value where yield

Once you avoid these words, there are rules you must follow when naming your objects.
On this site, here are the rules we will follow:

 The name must start with a letter or an underscore

 After the first letter or underscore, the name can have letters, digits, and/or
underscores

 The name must not have any special characters other than the underscore

 The name cannot have a space

Besides these rules, you can also create your own but that abide by the above.
C# 3.0 Practical Learning 25
C# is case-sensitive. This means that the names Case, case, and CASE are completely
different. For example, main is always written Main.

Values and Variables on the Console

As mentioned already, the applications we will create display in a dark object called the
DOS window. Here is an example showing some values:

To display a value in this window, you can enter it in the parentheses of the
Console.Write() or Console.WriteLine(). Here are two examples:

using System;

class Program
{
static void Main()
{
Console.WriteLine(248);
Console.Write(1);
}
}

If you write Console.WriteLine() with empty parentheses, an empty line would be


displayed. In future lessons, we will learn what the meanings of Console, Write(), and
WriteLine().

The Numeric Systems


 

Introduction

When a computer boots, it “loads” the operating system. If you want to use a program,
you must find it either on the Start menu or from its directory and take the necessary
action to open it. Such a program uses numbers, characters, meaningful words, pictures,
graphics, etc, that are part of the program. As these things are numerous, so is the size of
the program, and so is the length of time needed to come up. Your job as a programmer
is to create such programs and make them available to the computer, then to people who
want to interact with the machine.

C# 3.0 Practical Learning 26


To write your programs, you will be using alphabetic letters that are a, b, c, d, e, f, g, h, I,
j, k, l, m, n, o, p, q, r, s, t, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R,
S, T, U, V, W, X, Y, Z. You will also use numeric symbols 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Additionally, you will use characters that are not easily readable but are part of the
common language; they are ` ~ ! @ # $ % ^ & * ( ) _ + - = : “ < > ; ‘ , . /. Some of
these symbols are used in the C# language while some others are not. When creating
your programs, you will be combining letters and/or symbols to create English words or
language instructions.

Some of the instructions you will give to the computer could consist of counting the
number of oranges, converting water to soup, or making sure that a date occurs after
January 15. After typing an instruction, the compiler would translate it to machine
language. The computer represents any of your instructions as a group of numbers. Even
if you ask the computer to use an orange, it would translate it into a set of numbers. As
you give more instructions or create more words, the computer stores them in its memory
using a certain amount of space for each instruction or each item you use.

There are three numeric systems that will be involved in your programs, with or without
your intervention.

The Binary System

When dealing with assignments, the computer considers a piece of information to be true
or to be false. To evaluate such a piece, it uses two symbols: 0 and 1. When a piece of
information is true, the computer gives it a value of 1; otherwise, its value is 0. Therefore,
the system that the computer recognizes and uses is made of two symbols: 0 and 1. As
the information in your computer is greater than a simple piece, the computer combines
0s and 1s to produce all sorts of numbers. Examples of such numbers are 1, 100, 1011, or
1101111011. Therefore, because this technique uses only two symbols, it is called the
binary system.

When reading a binary number such as 1101, you should not pronounce "One Thousand
One Hundred And 1", because such a reading is not accurate. Instead, you should
pronounce 1 as One and 0 as zero or o. 1101 should be pronounced One One Zero One,
or One One o One.

The sequence of the symbols of the binary system depends on the number that needs to
be represented.

The Decimal System

The numeric system that we are familiar with uses ten symbols that are 0, 1, 2, 3, 4, 5, 6,
7, 8, and 9. Each of these symbols is called a digit. Using a combination of these digits,
you can display numeric values of any kind, such as 240, 3826 or 234523. This system of
representing numeric values is called the decimal system because it is based on 10 digits.

When a number starts with 0, a calculator or a computer ignores the 0. Consequently,


0248 is the same as 248; 030426 is the same as 30426. From now on, we will represent a
numeric value in the decimal system without starting with 0: this will reduce, if not
eliminate, any confusion.

C# 3.0 Practical Learning 27


Decimal Values: 3849, 279, 917293, 39473
Non- Decimal Values: 0237, 0276382, k2783, R3273

The decimal system is said to use a base 10. This allows you to recognize and be able to
read any number. The system works in increments of 0, 10, 100, 1000, 10000, and up. In
the decimal system, 0 is 0*10 0 (= 0*1, which is 0); 1 is 1*10 0 (=1*1, which is 1); 2 is
2*100 (=2*1, which is 2), and 9 is 9*10 0 (= 9*1, which is 9). Between 10 and 99, a
number is represented by left-digit * 101 + right-digit * 100. For example, 32 = 3*101 +
2*100 = 3*10 + 2*1 = 30 + 2 = 32. In the same way, 85 = 8*10 1 + 5*100 = 8*10 + 5*1
= 80 + 5 = 85. Using the same logic, you can get any number in the decimal system.
Examples are:

2751 = 2*103 + 7*102 + 5*101 + 1*100 = 2*1000 + 7*100 + 5*10 + 1 = 2000 + 700 +
50 + 1 = 2751

67048 = 6*104 + 7*103 + 0*102 + 4*101 + 8*100 = 6*10000 +


7*1000+0*100+4*10+8*1 = 67048
Another way you can represent this is by using the following table:

etc Add 0 to the preceding value 1000000 100000 10000 1000 100 10 0

When these numbers get large, they become difficult to read; an example is
279174394327. To make this easier to read, you can separate each thousand fraction with
a comma. Our number would become 279,174,394,327. You can do this only on paper,
never in a program: the compiler would not understand the comma(s).

The Hexadecimal System

While the decimal system uses 10 digits (they are all numeric), the hexadecimal system
uses sixteen (16) symbols to represent a number. Since the family of Latin languages
consists of only 10 digits, we cannot make up new ones. To compensate for this, the
hexadecimal system uses alphabetic characters. After counting from 0 to 9, the system
uses letters until it gets 16 different values. The letters used are a, b, c, d, e, and f, or
their uppercase equivalents A, B, C, D, E, and F. The hexadecimal system counts as
follows: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f; or 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C,
D, E, F. To produce a hexadecimal number, you use a combination of these sixteen
symbols.
Examples of hexadecimal numbers are 293, 0, df, a37, c23b34, or ffed54. At first glance, the
decimal representation of 8024 and the hexadecimal representation of 8024 are the same.
Also, when you see fed, is it a name of a federal agency or a hexadecimal number? Does CAB
represent a taxi, a social organization, or a hexadecimal number?

From now on, to express the difference between a decimal number and a
hexadecimal one, each hexadecimal number will start with 0x or 0X. The number
will be followed by a valid hexadecimal combination. The letter can be in
uppercase or lowercase.

Legal Hexadecimals: 0x273, 0xfeaa, 0Xfe3, 0x35FD, 0x32F4e


Non-Hex Numbers: 0686, ffekj, 87fe6y, 312

C# 3.0 Practical Learning 28


There is also the octal system but we will not use it anywhere in our applications.

Signed and Unsigned

The numbers we have used so far were counting from 0, then 1, then 2, and up to any
number desired, in incrementing values. Such a number that increments from 0, 1, 2, and
up is qualified as positive. By convention, you do not need to let the computer or someone
else know that such a number is positive: by just displaying or saying it, the number is
considered positive. This is the basis of our counting items.

In real life, there are numbers counted in decrement values. Such numbers start at –1 and
move down to -2, -3, -4 etc. These numbers are qualified as negative.

When you write a number “normally”, such as 42, 502, or 1250, the number is positive. If
you want to express the number as negative, you use the – on the left side of the
number. The – symbol is called a sign. Therefore, if the number does not have the –
symbol, C++ (or the compiler) considers such a number as unsigned. In C++, if you
declare a variable that would represent a numeric value and you do not initialize (assign a
value to) such a variable, the compiler will consider that the variable can hold either a
signed or an unsigned value. If you want to let the compiler know that the variable should
hold only a positive value, you will declare such a variable as unsigned.

Data Types

In order to use a variable in your program, the compiler must be aware of it. Once the
compiler knows about a variable, it would reserve an amount of memory space for that
variable

Using its name, you can refer to a particular variable when necessary. Because there are
various types of variables a program can use, such as the employee's name, his home
address, the desired salary, years of experience, education level, etc for our employment
application analogy, the compiler needs a second piece of information for each variable
you intend to use. This piece of information specifies the amount of space that a variable
needs. You can see that, to store a character, such as an employee's gender (M or F) or
an answer as Y or N to a question, the compiler would certainly not need the same
amount of space to store the name of the last school attended by an employee.

A data type is an amount of space needed to store the information related to a particular
variable.

The name of a variable allows you and the compiler to refer to a particular category of
information in your program. The data type allows the compiler to reserve an adequate
amount of memory space for a variable. Because you are the one who writes a program,
you also tell the compiler the amount of memory space each particular variable will need.
Based on this, the C# language provides categories of data types used to specify this
amount of space needed for a variable.

C# 3.0 Practical Learning 29


As stated already, before using a variable, you must communicate your intentions to the
compiler. Making the compiler aware is referred to as declaring the variable. To declare a
variable, you have two options:
 If you know the type of variable you want to use, you can provide it followed by the name
of the variable. Based on this, one syntax used to declare a variable is:
 
DataType VariableName;

 As an alternative, you can provide only a name for the variable but let the compiler
specify its data type. To declare such a variable, you use the var keyword followed
by the name of the variable. This certainly would not be enough. For the compiler
to know how much space is necessary, you must provide a value for the variable

Providing a value for a variable is referred to as initializing it. This can be done for
declared with either a data type or the var keyword:

 If you declare a variable using data type, the initialization could be optional
(depending on how you will access the variable)

 If you declare a variable using the var keyword, you must initialize it

To initialize a variable, on the right side of its name, type the assignment operation, which
is =, followed by a value:

 If you declare a variable using a data type, you must initialize it with an appropriate
value. When we study the data type, we will see what value is appropriate for what
data type

 If you declare a variable using the var keyword, you can initialize it with almost any
type of value (of course there are exceptions). The purpose of using the var
keyword is to let the compiler decides what type the variable is. To make this decision, the
compiler refers to the type of value the variable was assigned with.

For illustrative purposes, in many lessons, we will use the var keyword to declare
variables. In practicality, don't abuse or overuse the var keyword. It can be
confusing. The beauty of var, which is one of its rules, is that you MUST initialize
its variable. This makes it possible to know the type of variable you are using. On
the other hand, if you declare too many  variables with var and initialize them
with the same types of values, you could get confused with the type of data that
each of those variables is holding. So, use the var keyword sparingly: It can be a
beauty but, if overused, it can be confusing. The good news is that the compiler
knows exactly what it is doing and what it is asked to do.

Representing Numbers
 

A Bit

C# 3.0 Practical Learning 30


The computer (or an Intel computer, or a computer that runs on an Intel microprocessor)
uses the binary system to represent its information. It represents data using only a 0 or 1
value:

0 1

You can represent a piece of information with one of two states. This technique of
representing values is the same as the binary system. In the computer, it uses values 0
and/or 1, which themselves are called digits. The entity used to represent such a value is
called a binary digit; in its abbreviated form, it is called a bit (for binary digit). The bit
(binary digit) is the most fundamental representation of the computer's counting system.

Although the C# compiler recognizes a bit, you cannot store a variable in a bit. However,
eventually, you will be able to manipulate the information stored in a bit.

The Four-Bit Combination

The single bit is used only to represent a tinny piece of information. To get effective numbers,
the computer combines the bits. The first combination of bits consists of grouping four
consecutive bits.

To count the bits, we number them starting at 0, followed by 1, 2, and 3. The count starts
with the most right bit:

The first bit, on the right side of the group, is called the Low Order bit or LO bit. This is
also called the least significant bit. The last bit, on the left side of the group, is called the
High Order bit or HI bit; it is also called the most significant bit. The bit on the right side is
counted as bit 0. The bit on the left side is counted as bit 3. The other bits are called by
their positions: bit 1 and bit 2.
Once again, each bit can have one of two states. Continuing with our illustration, when a cup is
empty, it receives a value of 0. Otherwise, it has a value of 1. On a group of four consecutive
bits, we can have the following combinations:

C# 3.0 Practical Learning 31


This produces the following binary combinations: 0000, 0001, 0010, 0011, 0100, 0101,
0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111 = 16 combinations. When
using the decimal system, these combinations can be represented as 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, and 15.

This combination is also a system that the computer uses to count bits internally.
Sometimes, in your program or in the help files, you will encounter a number that is less
than four bits, such as 10 or 01 or 101. The technique used to complete and fill out the
group of 4 bits consists of displaying 0 for each non-represented bit. The binary number
10 will be the same as 0010. The number 01 is the same as 0001. The number 101 is the
same as 0101. This technique is valuable and allows you to always identify a binary
number as a divider of 4.

When all bits of a group of 4 are 0, the combination has the lowest value, which is 0000.
Any of the other combinations has at least one 0 bit, except for the last one. When all bits
are 1, this provides the highest value possible for a group of 4 bits. The lowest value, also
considered the minimum value, can be represented in the decimal system as 0. The
highest value, also considered the maximum, can be expressed in decimal value as 2 4 (2
represents the fact that there are two possible states: 0 and 1; 4 represents the fact that
there are four possible combinations), which is 16. This produces 16 because 2 4 = 16.
As you can see, the binary system can appear difficult to read when a value combines various
bit representations. To make it easier, the computer recognizes the hexadecimal
representation of bits. Following the box combinations above, we can represent each 4-bit of
the sixteen combinations using the decimal, hexadecimal, and binary systems as follows:

Decimal Binary Hexadecimal

0 0000 0

1 0001 1

2 0010 2

3 0011 3

C# 3.0 Practical Learning 32


4 0100 4

5 0101 5

6 0110 6

7 0111 7

8 1000 8

9 1001 9

10 1010 A

11 1011 B

12 1100 C

13 1101 D

14 1110 E

15 1111 F

Table of Numeric Conversions

When looking at a binary value represented by 4 bits, you can get its decimal or hexadecimal
values by referring to the table above. A group of four consecutive bits has a minimum and
maximum values on each system as follows:

Decimal Hexadecimal Binary

Minimum 0 0x0 0000

Maximum 15 0xf 1111

Although the C# compiler recognizes a group of four consecutive bits, you cannot store
any variable in it. You can, however, manipulate the bits of the group.

A Byte
 
C# 3.0 Practical Learning 33
Introduction

A byte is a group or eight consecutive bits. The bits are counted from right to left starting
at 0:

The most right bit is bit 0; it is called the least significant bit. It is also referred to as the
Low Order bit, the LO bit, or LOBIT. The most left bit is bit 7; it is called the most
significant bit. It is also referred to as the High Order bit, the HI bit, or HIBIT. The other
bits are referred to following their positions:

Using the binary system, you can represent the byte using a combination of 0s and 1s.
When all bits have a value of 0, the byte is represented as 00000000. On the other hand,
when all bits have a value of 1, the byte is represented as 11111111. When the number
grows very large, it becomes difficult to read. Therefore, you can represent bits in groups
of four. Instead of writing 00000000, you can write 0000 0000. This makes the number
easier to read.

If you have the patience to create combinations of bits using the boxes as we did for the
group of 4, you would find out that there are 256 possible combinations. Another way to
find it out is by using the base 2 technique:

27 + 2 6 + 2 5 + 2 4 + 2 3 + 2 2 + 2 1 + 2 0
= 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
= 255

Therefore, the maximum decimal value you can store in a byte is 255.

Remember that the byte with all bits having a value of 0 has its value set to 0. Since this
byte also holds a valid value, the number of combinations = 255 + 1 = 256.
When a byte is completely represented with 0s, it provides the minimum value it can hold; this
is 0000 0000, which is also 0. When all bits have a value of 1, which is 1111 1111, a byte
holds its maximum value that we calculated as 255 in the decimal system. As done with the
group of 4 bits, we get the following table:

Decimal Hexadecimal Binary

Minimum 0 0x0 0000

C# 3.0 Practical Learning 34


Maximum 255 0xff 1111 1111

The minimum storage area offered by the (Intel) computer is the byte. As you know
already, a byte is a group of 8 consecutive bits. The amount of memory space offered by
a byte can be used to store just a single symbol, such as those you see on your keyboard.
These symbols, also called characters, have been organized by the American Standard
Code for Information Exchange (ASCII) in a set list. But, ASCII uses only 128 decimal
numbers (based on a 7-bit format) to represent symbols counted from 0 to 127. To
compensate for the remaining 1 bit, IBM used it to organize special characters, foreign
language characters, mathematical symbols, small graphics, etc. Each one of these
characters has a decimal, a hexadecimal, and a binary equivalents.

Each one of the characters you see on your keyboard is represented as a numeric value,
but whether it appears as a number, a letter, or a symbol, each one of these is considered
a character. To display any character on your screen, you can pass it to Write() or
WriteLine() and include the character between single-quotes, as follows:

using System;

class Exercise
{
static void Main()
{
Console.WriteLine('n');
}
}

Characters

In the English alphabet, a character is one of the following symbols: a, b, c, d, e, f, g, h, i,


j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
R, S, T, U, V, W, X, Y, and Z. Besides these readable characters, the following symbols are
called digits and they are used to represent numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. In
addition, some symbols on the (US QWERTY) keyboard are also called characters or
symbols. They are ` ~ ! @ # $ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' < ? . / , > "

Besides the English language, other languages use other or additional characters that
represent verbal or written expressions.

C# recognizes that everything that can be displayed as a symbol is called a character. To


declare a variable whose value would be a character, you can use the var keyword and
initialize the variable with a character in single-quotes. Here is an example:
using System;

class Exercise
{
static void Main()
{
var Gender = 'F';

Console.Write("Student Gender: ");


Console.WriteLine(Gender);
}
C# 3.0 Practical Learning 35
}

Alternatively, you can use the char keyword. Here is an example:


using System;

class Exercise
{
static void Main()
{
char Gender = 'M';

Console.Write("Student Gender: ");


Console.WriteLine(Gender);
}
}

This would produce:


Student Gender: M

Escape Sequences

An escape sequence is a special character that displays non-visibly. For example, you can
use this type of character to indicate the end of line, that is, to ask the program to
continue on the next line. An escape sequence is represented by a backslash character, \,
followed by another character or symbol. For example, the escape sequence that moves to
the next line is \n.

An escape can be included in single-quotes as in '\n'. It can also be provided in double-


quotes as "\n".
The C# language recognizes other escape sequences.

Escape
Name Description
Sequence

\a Bell (alert) Makes a sound from the computer

\b Backspace Takes the cursor back

\t Horizontal Tab Takes the cursor to the next tab stop

Takes the cursor to the beginning of the next


\n New line
line

\v Vertical Tab Performs a vertical tab

\f Form feed

\r Carriage Causes a carriage return


C# 3.0 Practical Learning 36
return

\" Double Quote Displays a quotation mark (")

\' Apostrophe Displays an apostrophe (')

\? Question mark Displays a question mark

\\ Backslash Displays a backslash (\)

\0 Null Displays a null character

To use an escape sequence, you can also first declare a char variable and initialize it with
the desired escape sequence in single-quotes.

The Byte Data Type

A byte is an unsigned number whose value can range from 0 to 255 and therefore can be
stored in one byte. You can use it when you know a variable would hold a relatively small
value such as people's age, the number of children of one mother, etc. To declare a
variable that would hold a small natural number, use the byte keyword. Here is an
example:
byte Age;

You can initialize a byte variable when declaring it or afterwards. Here is an example that
uses the byte data type:
using System;

class ObjectName
{
static void Main()
{
Byte Age = 14;
Console.Write("Student Age: ");
Console.WriteLine(Age);

Age = 12;
Console.Write("Student Age: ");
Console.WriteLine(Age);
}
}

Make sure you do not use a value that is higher than 255 for a byte variable, you would
receive an error. When in doubt, or when you think that there is a possibility a variable
would hold a bigger value, don't use the byte data type as it doesn't like exceeding the
255 value limit.
C# 3.0 Practical Learning 37
Alternatively, you can also use the var keyword to declare the variable and initialize it with
a small number. Here is an example:
using System;

class Exercise
{
static void Main()
{
var Age = 14;
Console.Write("Student Age: ");
Console.WriteLine(Age);

Age = 12;
Console.Write("Student Age: ");
Console.WriteLine(Age);
}
}

Instead of a decimal number, you can also initialize an integral variable with a
hexadecimal value. When doing this, make sure the decimal equivalent is less than 255.
Here is an example:
using System;

class Exercise
{
static void Main()
{
var Number = 0xFE;

Console.Write("Number: ");
Console.WriteLine(Number);
}
}

This would produce:


Number: 254
Press any key to continue . . .

Practical Learning: Using Bytes

1. Change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices2
{
class Program
{
static void Main(string[] args)
{
byte Shirts;
byte Pants;
C# 3.0 Practical Learning 38
Shirts = 4;
Pants = 1;

Console.WriteLine("-/- Georgetown Cleaning Services


-/-");
Console.WriteLine("========================");
Console.WriteLine("Item Type Qty");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.WriteLine(Shirts);
Console.Write("Pants ");
Console.WriteLine(Pants);
Console.WriteLine("========================");
Console.WriteLine();
}
}
}

2. Execute the program. This would produce:


 
-/- Georgetown Cleaning Services -/-
========================
Item Type Qty
------------------------
Shirts 4
Pants 1
========================

3. Close the DOS window

Signed Byte

A byte number is referred to as signed if it can hold a negative of a positive value that
ranges from -128 to 127, which can therefore fit in a byte. To declare a variable for that
kind of value, use the sbyte keyword. Here is an example:
using System;

class NumericRepresentation
{
static void Main()
{
sbyte RoomTemperature = -88;

Console.Write("When we entered, the room temperature was ");


Console.WriteLine(RoomTemperature);
Console.WriteLine();
}
}

This would produce:


When we entered, the room temperature was -88

A Word
C# 3.0 Practical Learning 39
 

Introduction

A word is a group of 16 consecutive bits. The bits are counted from right to left starting at
0:

Considered as a group of 16 bits, the most right bit of a word, bit 0, is called the least
significant bit or Low Order bit or LO bit or LOBIT. The most left bit, bit 15, is called the
most significant bit or High Order bit or HI bit or HIBIT. The other bits are referred to
using their positions: bit 1, bit 2, bit 3, etc.

Considering that a word is made of two bytes, the group of the right 8 bits is called the
least significant byte or Low Order byte or LO byte or LOBYTE. The other group is called
the most significant byte or High Order byte or HI byte or HIBYTE.

The representation of a word in binary format is 0000000000000000. To make it easier to


read, you can group bits by 4, like this: 0000 0000 0000 0000. Therefore, the minimum
binary value represented by a word is 0000 0000 0000 0000. The minimum decimal value
of a word is 0. The minimum hexadecimal value you can store in a word is
0x0000000000000000. This is also represented as 0x00000000, or 0x0000, or 0x0. All
these numbers produce the same value, which is 0x0.

The maximum binary value represented by a word is 1111 1111 1111 1111. To find out
the maximum decimal value of a word, you can use the base 2 formula, filling out each bit
with 1:

1*215+1*214+1*213 + 1*212 + 1*211 + 1*210 + 1*29 + 1*28 + 1*27 + 1*26 + 1*25 + 1*24 +
1*23 + 1*22 + 1*21 + 1*20

= 32768 + 16384 + 8192 + 4096 + 2048 + 1024 + 512 + 256 + 128 + 64 + 32 + 16 +


8+4+2+1

= 65535
To find out the maximum hexadecimal number you can store in a word, replace every group of
4 bits with an f or F:

1111 1111 1111 1111

f f f f

= 0xffff

= 0xFFFF

C# 3.0 Practical Learning 40


= 0Xffff

= 0XFFFF

Short Integers

A word, which is a group of 16 contiguous bits or 2 bytes, can be used to hold a natural
number. As we have studied, the maximum numeric value that can fit in a word is 65535.
To declare a variable for such a value, you can use the var keyword and initialize the
variable with a value between –32768 to 32767. Here is an example:
using System;

class Exercise
{
static void Main()
{
var SchoolEffective = 1400; // Number of Students

Console.Write("School Effective: ");


Console.WriteLine(SchoolEffective);
}
}

This would produce:


School Effective: 1400
Press any key to continue . . .

Since the byte is used for characters and very small numbers, whenever you plan to use a
number in your program, the minimum representation you should use is a word.

A natural number is also called an integer. If you want to declare the variable using a data
type, the smallest integer you can store in a word is declared with the short keyword.
Because a short integer is signed by default, it can store a value that ranges from –
32768 to 32767. Here is an example program that uses two short integers:
using System;

class Exercise
{
static void Main()
{
short NumberOfPages;
short Temperature;

NumberOfPages = 842;
Temperature = -1544;

Console.Write("Number of Pages of the book: ");


Console.WriteLine(NumberOfPages);
Console.Write("Temperature to reach during the experiment: ");
Console.Write(Temperature);
C# 3.0 Practical Learning 41
Console.WriteLine(" degrees\n");
}
}

This would produce:


Number of Pages of the book: 842
Temperature to reach during the experiment: -1544 degrees

Because a short integer handles numbers that are larger than the signed byte, any
variable you can declare for a signed byte can also be declared for a short variable.

Unsigned Short Integers

If a variable must hold positive and relatively small numbers, it is referred as an unsigned
short integer. Such a variable can be declared using either the var of the ushort
keyword. An unsigned short integer can hold numbers that range from 0 to 65535 and
therefore can fit in 16 bits. Here is an example:
using System;

class NumericRepresentation
{
static void Main()
{
// These variables must hold only positive integers
ushort NumberOfTracks;
ushort MusicCategory;

NumberOfTracks = 16;
MusicCategory = 2;

Console.Write("This music album contains ");


Console.Write(NumberOfTracks);
Console.WriteLine(" tracks");
Console.Write("Music Category: ");
Console.Write(MusicCategory);
Console.WriteLine();
}
}

This would produce:


This music album contains 16 tracks
Music Category: 2

Practical Learning: Using Unsigned Short Integers

1. To use unsigned short integers, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices2

C# 3.0 Practical Learning 42


{
class Program
{
static void Main(string[] args)
{
byte Shirts;
byte Pants;
ushort OtherItems;

Shirts = 4;
Pants = 1;
OtherItems = 3;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


Console.WriteLine("========================");
Console.WriteLine("Item Type Qty");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.WriteLine(Shirts);
Console.Write("Pants ");
Console.WriteLine(Pants);
Console.Write("Other Items ");
Console.WriteLine(OtherItems);
Console.WriteLine("========================");
Console.WriteLine();
}
}
}

2. Execute the program. This would produce:


 
-/- Georgetown Cleaning Services -/-
========================
Order Date: 7/15/2002
------------------------
Item Type Qty
------------------------
Shirts 4
Pants 1
Other Items 3
========================

Press any key to continue . . .

3. Close the DOS window

C# 3.0 Practical Learning 43


3 – USING VARIABLES
 

A Double-Word
 

Introduction

A double-word is a group of two consecutive Words. This means that a double-word


combines 4 bytes or 32 bits. The bits, counted from right to left, start at 0 and end at 31.

The most right bit, bit 0, is called the Low Order bit or LO bit or LOBIT. The most left bit,
bit 31, is called the High Order bit or HI bit or HIBIT. The other bits are called using their
positions.

The group of the first 8 bits (from bit 0 to bit 7), which is the right byte, is called the Low
Order Byte, or LO Byte. It is sometimes referred to as LOBYTE. The group of the last 8 bits
(from bit 24 to bit 31), which is the left byte, is called the High Order Byte, or HI Byte or
HIBYTE. The other bytes are called by their positions.

The group of the right 16 bits, or the right Word, is called the Low Order Word, or LO
Word, or LOWORD. The group of the left 16 bits, or the left Word, is called the High Order
Word, or HI Word, or HIWORD.  

The minimum binary number you can represent with a double-word is 0. The minimum
decimal value of a double-word is 0. To find out the maximum decimal value of a word,
you can use the base 2 formula giving a 1 value to each bit:
 

2n-1 230  229  228 227  226 225 224

etc 1,073,741,824 536,870,912 268,435,456 134,217,728 67,108,864 33,554,432 16,777,216

223 222 221 220 219 218 217 216

8,388,608 4,194,304 2,097,152 1,048,576 524,288 262,144 131,072 65,536

C# 3.0 Practical Learning 44


 

215 214 213 212 211 210 29 28

32,768 16,384 8,192 4,096 2,048 1,024 512 256

27 26 25 24 23 22 21 20

128 64 32 16 8 4 2 1

1*231+1*230+1*229 + 1*228 + 1*227 + 1*226 + 1*225 + 1*224 + 1*223 + 1*222 + 1*221 +


1*220 + 1*219 + 1*218 + 1*217 + 1*216 + 1*215 + 1*214 + 1*213 + 1*212 + 1*211 + 1*210 +
1*29 + 1*28 + 1*27 + 1*26 + 1*25 + 1*24 + 1*23 + 1*22 + 1*21 + 1*20

= 2,147,483,648 + 1,073,741,824 + 536,870,912 + 268,435,456 + 134,217,728 +


67,108,864 + 33,554,432 + 16,777,216 + 8,388,608 + 4,194,304 + 2,097,152 +
1,048,576 + 524,288 + 262,144 + 131,072 + 65,536 + 32,768 + 16,384 + 8,192 + 4,096
+ 2,048 + 1,024 + 512 + 256 + 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1

= 4,286,578,708
The minimum hexadecimal value you can store in a double-word is
0x00000000000000000000000000000000 which is the same as 0x0. To find out the maximum
hexadecimal number you can represent with a word, replace every group of 4-bits with an f or
F:

1111 1111 1111 1111 1111 1111 1111 1111

f f f f f f f f

= 0xffffffff = 0Xffffffff = 0XFFFFFFFF = 0xFFFFFFFF

To declare a variable that can hold large values, you can use the var keyword and
initialize the variable with the desired value. Here is an example:

using System;

class Exercise
{
static void Main()
{
var Population = 72394475;

C# 3.0 Practical Learning 45


Console.Write("Country Population: ");
Console.WriteLine(Population);
}
}

This would produce:


Country Population: 72394475
Press any key to continue . . .

Practical Learning: Using Unsigned Integers

1. Start Microsoft Visual C#

2. To create a new application, on the main menu, click File -> New -> Project...

3. In the Templates section, click Console Application

4. Change the Name to GeorgetownCleaningServices3 and click OK

5. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices3
{
class Program
{
static void Main(string[] args)
{
byte Shirts;
byte Pants;
ushort OtherItems;

Shirts = 4;
Pants = 0;
OtherItems = 3;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


Console.WriteLine("========================");
Console.WriteLine("------------------------");
Console.WriteLine("Item Type Qty");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.WriteLine(Shirts);
Console.Write("Pants ");
Console.WriteLine(Pants);
Console.Write("Other Items ");
Console.WriteLine(OtherItems);
Console.WriteLine("========================");
Console.WriteLine();
}
}
}
C# 3.0 Practical Learning 46
6. Execute the program to see the result 

7. Close the DOS window

Signed Integers

A double-word is large enough to contain double the amount of data that can be stored in
a word. This is equivalent to 32 bits or 4 bytes or 4,294,967,295. Therefore, a double-
word is used for large numbers that would not fit in a word.

To use a variable that would hold quite large numbers, besides the var keyword, you can
declare it using the int keyword. A variable declared as int can store values between –
2,147,483,648 and 2,147,484,647 negative or positive, that can fit in 32 bits.

Here is an example:
using System;

class Exercise
{
static void Main()
{
int CoordX;
int CoordY;

CoordX = 12;
CoordY = -8;

Console.Write("Cartesian Coordinate System: ");


Console.Write("P(");
Console.Write(CoordX);
Console.Write(", ");
Console.Write(CoordY);
Console.WriteLine(")\n");
}
}

When executed, the program would produce:


Cartesian Coordinate System: P(12, -8)

If you declare an integer variable using the var keyword and initialize it with a value lower
than 2,147,484,647, the compiler concludes that the memory needed to store that
variable is 32 bits:

C# 3.0 Practical Learning 47


When initializing an integral variable, instead of a decimal number, you can also initialize it
with a hexadecimal value whose decimal equivalent is less than 2,147,484,647. Here is an
example:
using System;

class Exercise
{
static void Main()
{
var Number = 0xF0488EA;

Console.Write("Number: ");
Console.WriteLine(Number);
}
}

This would produce:


Number: 251955434
Press any key to continue . . .

Unsigned Integers

If the variable must hold only positive natural numbers, you can declared it using the uint
keyword. The uint keyword is used to identify a 32-bit positive integer whose value
would range from 0 to 2,147,484,647. Here is an example:
using System;

class Exercise
{
static void Main()
{
C# 3.0 Practical Learning 48
uint DayOfBirth;
uint MonthOfBirth;
uint YearOfBirth;

DayOfBirth = 8;
MonthOfBirth = 11;
YearOfBirth = 1996;

Console.WriteLine("Red Oak High School");

Console.Write("Student Date of Birth: ");

Console.Write(MonthOfBirth);
Console.Write("/");
Console.Write(DayOfBirth);
Console.Write("/");
Console.Write(YearOfBirth);
Console.WriteLine();
}
}

This would produce:


Red Oak High School
Student Date of Birth: 11/8/1996

Practical Learning: Using Unsigned Integers

1. To use unsigned variables, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices3
{
class Program
{
static void Main(string[] args)
{
byte Shirts;
byte Pants;
ushort OtherItems;

uint OrderDay;
uint OrderMonth;
uint OrderYear;

Shirts = 4;
Pants = 0;
OtherItems = 3;
OrderDay = 15;
OrderMonth = 7;
OrderYear = 2002;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


Console.WriteLine("========================");
C# 3.0 Practical Learning 49
Console.Write("Order Date: ");
Console.Write(OrderMonth);
Console.Write('/');
Console.Write(OrderDay);
Console.Write('/');
Console.WriteLine(OrderYear);
Console.WriteLine("------------------------");
Console.WriteLine("Item Type Qty");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.WriteLine(Shirts);
Console.Write("Pants ");
Console.WriteLine(Pants);
Console.Write("Other Items ");
Console.WriteLine(OtherItems);
Console.WriteLine("========================");
Console.WriteLine();
}
}
}

2. Execute the program. This would produce:


 
-/- Georgetown Cleaning Services -/-
========================
Order Date: 7/15/2002
------------------------
Item Type Qty
------------------------
Shirts 4
Pants 0
Other Items 3
========================

Press any key to continue . . .

3. Close the DOS window

A Quad-Word
 

Introduction

Sometimes you may want to store values that a double-word cannot handle. To store a
very large number in a variable, you can consider a combination of 64 bits. The group can
also be referred to as a quad-word. A quad-word is so large it can store numbers in the
range of –9,223,372,036,854,775,808 and 9,223,372,036,854,775,807.

If you declare an integer variable using the var keyword and initialize it with a value
between 2,147,484,647 and 9,223,372,036,854,775,807, the compiler concludes that the
memory needed to store that variable is 64 bits:

C# 3.0 Practical Learning 50


Long Integers

If you want to use a variable that can hold very large numbers that would require up to 64
bits, you can declare it using either the var or the long keyword.

In C++, the long data type is 32 bits while in C#, the long data type is 64
bits.

As stated previously, if you initialize the variable with a value lower than 2,147,484,647,
the compiler would allocate 32 bits of memory for it. If you initialize the variable with a
value between 2,147,484,647 and 9,223,372,036,854,775,807, the compiler would
allocate 64 bits of memory for it. If the value is higher than 9,223,372,036,854,775,807,
which is too large, the compiler would present an error:

C# 3.0 Practical Learning 51


This means that you should limit the values assigned to integral variables to 64 bits, which
is very significant.

Here is an example that uses the long data type:


using System;

class Exercise
{
static void Main()
{
var CountryArea = 5638648;

Console.Write("Country Area: ");


Console.Write(CountryArea);
Console.Write("km2\n");
}
}

This would produce:


Country Area: 5638648km2
Press any key to continue . . .

As mentioned for other integral types, you can initialize a long variable with a
hexadecimal value.

Although the long data type is used for large number, it mainly indicates the amount of
space available but you do not have to use the whole space. For example, you can use the
long keyword to declare a variable that would hold the same range of numbers as the
short, the int, or the uint data types. If you declare a variable as long but use it for
small numbers that don't require 64 bits, the compiler would allocate the appropriate
amount of space to accommodate the values of the variable. Consequently, the amount of
space made available may not be as large as 64 bits. If you insist and want the compiler
C# 3.0 Practical Learning 52
to reserve 64 bits, when assigning a value to the variable, add an L suffix to it. Here is an
example that uses space of a long data type to store a number that would fit in 32 bits:
using System;

class NumericRepresentation
{
static void Main()
{
long CountryArea;

CountryArea = 5638648L;

Console.Write("Country Area: ");


Console.Write(CountryArea);
Console.Write("km2\n");
}
}

Therefore, keep in mind that an int, a uint, a short, or a ushort can fit in a long
variable.

Unsigned Long Integers

You can use a combination of 64 bits to store positive or negative integers. In some cases,
you will need a variable to hold only positive, though large, numbers. To declare such a
variable, you can use the ulong data type. A variable declared as ulong can handle
extremely positive numbers that range from 0 to 18,446,744,073,709,551,615 to fit in 64
bits.

Real Numbers
 

Introduction

A real number is a number that displays a decimal part. This means that the number can
be made of two sections separated by a symbol that is referred to as the Decimal
Separator or Decimal Symbol. This symbol is different by language, country, group of
languages, or group of countries. In US English, this symbol is the period as can be
verified from the Regional (and Language) Settings of the Control Panel:

C# 3.0 Practical Learning 53


On both sides of the Decimal Symbol, digits are used to specify the value of the number.
The number of digits on the right side of the symbol determines how much precision the
number offers.

Floating-Point Numbers

The integers we have used so far have the main limitation of not allowing decimal values.
C# provides floating values that would solve this problem. The most fundamental floating
variable is declared with the float keyword. A variable declared a float can store real
numbers that range from ±1.5 × 10−45 to ±3.4 × 1038 with a precision of 7 digits in 32
bits. Here is an example:
using System;

class NumericRepresentation
{
static void Main()
{
float Distance;
}
}

Double-Precision Numbers

When a variable is larger than the float can handle and requires more precision, you
should declare it using either the var or the the double keyword. Here is an example:
C# 3.0 Practical Learning 54
using System;

class Exercise
{
static void Main()
{
var Number = 62834.9023;

Console.Write("Number: ");
Console.WriteLine(Number);
}
}

This would produce:


Number: 62834.9023
Press any key to continue . . .

A variable declared as double uses 64 bits to store very large numbers ranging from
±5.0 × 10−324 to ±1.7 × 10308 with a precision of 15 or 16 digits. Because the double
data type provides a better result with a better precision than the float, whenever you
declare a variable using either the var or the float keyword and assign it a value, the
compiler allocates 64 bits to store the values of the variable. If you insist on the variable
being treated as float, when assigning it a value, add an F suffix to the value. Here is an
example:
using System;

class NumericRepresentation
{
static void Main()
{
float Distance;

Distance = 248.38F;

Console.Write("Distance = ");
Console.Write(Distance);
Console.WriteLine("km\n");
}
}

This would produce:


Distance = 248.38km

Remember that if you declare the variable as var and want to treat it as a value with
single precision, add an F suffix to the value assigned to it. Here is an example:
using System;

class Exercise
{
static void Main()
{
var Number = 62834.9023F;

Console.Write("Number: ");
Console.WriteLine(Number);

C# 3.0 Practical Learning 55


}
}

On the other hand, if you want a value to be treated with double-precision, add a D suffix
to it. Here is an example:
using System;

class Exercise
{
static void Main()
{
var Number = 62834.9023D;

Console.Write("Number: ");
Console.WriteLine(Number);
}
}

Practical Learning: Using a Double-Precision Variable

1. To use a double-precision value, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices3
{
class Program
{
static void Main(string[] args)
{
byte Shirts;
byte Pants;
ushort OtherItems;

uint OrderDay;
uint OrderMonth;
uint OrderYear;

double MondayDiscount;

Shirts = 4;
Pants = 0;
OtherItems = 3;
OrderDay = 15;
OrderMonth = 7;
OrderYear = 2002;
MondayDiscount = 0.25D; // 25%

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


Console.WriteLine("========================");
Console.Write("Order Date: ");
Console.Write(OrderMonth);
Console.Write('/');
Console.Write(OrderDay);
C# 3.0 Practical Learning 56
Console.Write('/');
Console.WriteLine(OrderYear);
Console.WriteLine("------------------------");
Console.WriteLine("Item Type Qty");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.WriteLine(Shirts);
Console.Write("Pants ");
Console.WriteLine(Pants);
Console.Write("Other Items ");
Console.WriteLine(OtherItems);
Console.WriteLine("------------------------");
Console.Write("Monday Discount: ");
Console.Write(MondayDiscount);
Console.WriteLine('%');
Console.WriteLine("========================");
Console.WriteLine();
}
}
}

2. Execute the application to see the result:


 
-/- Georgetown Cleaning Services -/-
========================
Order Date: 7/15/2002
------------------------
Item Type Qty
------------------------
Shirts 4
Pants 0
Other Items 3
------------------------
Monday Discount: 0.25%
========================

Press any key to continue . . .

3. Close the DOS window

Decimal

The decimal data type can be used to declare a variable that would hold significantly
large values that can be stored in a combination of 128 bits. You declare such a variable
using the decimal keyword. The values stored in a decimal variable can range from
±1.0 × 10−28 to ±7.9 × 1028 with a precision of 28 to 29 digits. Because of this high level
of precision, the decimal data type is suitable for currency values.

After declaring a decimal variable, you can initialize it with a natural number. To indicate
that the variable holds a decimal value, when initializing it, add an M suffix to its value.
Here is an example:
using System;

class NumericRepresentation
{
static void Main()
C# 3.0 Practical Learning 57
{
decimal HourlySalary;

HourlySalary = 24.25M;

Console.Write("Hourly Salary = ");


Console.WriteLine(HourlySalary);
Console.WriteLine();
}
}

This would produce:


Hourly Salary = 24

As seen in previous sections and this one, when declaring and initializing a real variable,
the suffix you give to its assigned value indicates to the compiler the actual type of value
and the type of memory that would be allocated for the variable:

 If the value receives an F suffix, it is considered a floating point number with single
precision
 

 If the value receives a D suffix, it is considered a floating point number with double
precision

C# 3.0 Practical Learning 58


 

 If the value receives an M suffix, it is considered a large decimal number


 

C# 3.0 Practical Learning 59


 

Practical Learning: Using Decimal Values

1. To use decimal variables, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices3
{
class Program
{
static void Main(string[] args)
{
byte Shirts;
decimal PriceOneShirt;
byte Pants;
decimal PriceAPairOfPants;
ushort OtherItems;
decimal PriceOtherItems;

uint OrderDay;
uint OrderMonth;
uint OrderYear;

double MondayDiscount;

Shirts = 5;
PriceOneShirt = 0.95M;
Pants = 2;
PriceAPairOfPants = 1.95M;
OtherItems = 3;
PriceOtherItems = 4.55M;
OrderDay = 15;
OrderMonth = 7;
OrderYear = 2002;
MondayDiscount = 0.25D; // 25%

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


Console.WriteLine("========================");
Console.Write("Order Date: ");
Console.Write(OrderMonth);
Console.Write('/');
Console.Write(OrderDay);
Console.Write('/');
Console.WriteLine(OrderYear);
Console.WriteLine("------------------------");
Console.WriteLine("Item Type Qty Unit Price");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.Write(Shirts);
Console.Write(" ");
Console.WriteLine(PriceOneShirt);
Console.Write("Pants ");

C# 3.0 Practical Learning 60


Console.Write(Pants);
Console.Write(" ");
Console.WriteLine(PriceAPairOfPants);
Console.Write("Other Items ");
Console.Write(OtherItems);
Console.Write(" ");
Console.WriteLine(PriceOtherItems);
Console.WriteLine("------------------------");
Console.Write("Monday Discount: ");
Console.Write(MondayDiscount);
Console.WriteLine('%');
Console.WriteLine("========================");
Console.WriteLine();
}
}
}

2. Execute the program. This would produce:


 
-/- Georgetown Cleaning Services -/-
========================
Order Date: 7/15/2002
------------------------
Item Type Qty Unit Price
------------------------
Shirts 5 0.95
Pants 2 1.95
Other Items 3 4.55
------------------------
Monday Discount: 0.25%
========================

Press any key to continue . . .

3. Close the DOS window

Accessory Data Types


 

Strings

A string is an empty space, a character, a word, or a group of words that you want the
compiler to consider "as is", that is, not to pay too much attention to what the string is
made of, unless you explicitly ask it to. This means that, in the strict sense, you can put in
a string anything you want.

Primarily, the value of a string starts with a double quote and ends with a double-quote.
An example of a string is "Welcome to the World of C# Programming!". You can include
such a string in Console.Write() to display it on the console. Here is an example:
using System;

class Exercise
{
static void Main()
C# 3.0 Practical Learning 61
{
Console.WriteLine("Welcome to the World of C# Programming!");
}
}

This would produce:


Welcome to the World of C# Programming!
Press any key to continue . . .

Sometimes, you will need to use a string whose value is not known in advance. Therefore,
you can first declare a string variable. To do this, use either the var or the string
keyword followed by a name for the variable. The name will follow the rules we defined
above. When declaring a string variable, you can initialize it with an empty space, a
character, a symbol, a word, or a group of words. The value given to a string must be
included in double-quotes. Here are two examples:
using System;

class Exercise
{
static void Main()
{
var Team = "Real Madrid";
string Country = "Guinée Equatoriale";

Console.WriteLine("Welcome to the World of C# Programming!");


Console.Write("Team: ");
Console.WriteLine(Team);
Console.Write("Country: ");
Console.WriteLine(Country);
Console.WriteLine();
}
}

This would produce:


Welcome to the World of C# Programming!
Team: Real Madrid
Country: Guinée Equatoriale

Press any key to continue . . .

Practical Learning: Using Strings

1. To use strings, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices3
{
class Program
{
static void Main(string[] args)

C# 3.0 Practical Learning 62


{
string CustomerName;
string CustomerHomePhone;

byte Shirts;
decimal PriceOneShirt;
byte Pants;
decimal PriceAPairOfPants;
ushort OtherItems;
decimal PriceOtherItems;

uint OrderDay;
uint OrderMonth;
uint OrderYear;

double MondayDiscount;

CustomerName = "Gregory Almas";


CustomerHomePhone = "(301) 723-4425";
Shirts = 5;
PriceOneShirt = 0.95M;
Pants = 2;
PriceAPairOfPants = 1.95M;
OtherItems = 3;
PriceOtherItems = 4.55M;
OrderDay = 15;
OrderMonth = 7;
OrderYear = 2002;
MondayDiscount = 0.25D; // 25%

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


Console.WriteLine("========================");
Console.Write("Customer: ");
Console.WriteLine(CustomerName);
Console.Write("Home Phone: ");
Console.WriteLine(CustomerHomePhone);
Console.Write("Order Date: ");
Console.Write(OrderMonth);
Console.Write('/');
Console.Write(OrderDay);
Console.Write('/');
Console.WriteLine(OrderYear);
Console.WriteLine("------------------------");
Console.WriteLine("Item Type Qty Unit Price");
Console.WriteLine("------------------------");
Console.Write("Shirts ");
Console.Write(Shirts);
Console.Write(" ");
Console.WriteLine(PriceOneShirt);
Console.Write("Pants ");
Console.Write(Pants);
Console.Write(" ");
Console.WriteLine(PriceAPairOfPants);
Console.Write("Other Items ");
Console.Write(OtherItems);
Console.Write(" ");
Console.WriteLine(PriceOtherItems);
Console.WriteLine("------------------------");
Console.Write("Monday Discount: ");
Console.Write(MondayDiscount);
C# 3.0 Practical Learning 63
Console.WriteLine('%');
Console.WriteLine("========================");
Console.WriteLine();
}
}
}

2. Execute the program. This would produce:


 
-/- Georgetown Cleaning Services -/-
========================
Customer: Gregory Almas
Home Phone: (301) 723-4425
Order Date: 7/15/2002
------------------------
Item Type Qty Unit Price
------------------------
Shirts 5 0.95
Pants 2 1.95
Other Items 3 4.55
------------------------
Monday Discount: 0.25%
========================

Press any key to continue . . .

3. Close the DOS window

Dates and Times

A date is a unit that measures the number of years, months, or days elapsed in a specific
period. A time is a unit that counts the number of seconds that have elapsed since
midnight of the day considered. Although dates and times are large subjects that would
require a detailed study, at this time, we will consider them in simple terms.

To declare a variable that would hold date or time values, use the DateTime data type.
using System;

class NumericRepresentation
{
static void Main()
{
DateTime DateHired;
}
}

The .NET Framework sets its starting periodic date to January 1, 0001 at midnight
(12:00:00 or 0:00 AM). If not assigned a specific value (in future lessons, we will learn
that this is equivalent to declaring a variable using the default constructor), the variable is
initialized to 1/1/0001 at midnight.

Objects

C# 3.0 Practical Learning 64


The object data type is used to declare a variable whose type is not primarily defined
and can be any of the other data types we have introduced. After creating an object
variable, you can use its value as you see fit. For example, you can enter the variable in
the parentheses of Console.Write() or Console.WriteLine() to display it in the
console window. Here is an example:
using System;

class Exercise
{
static void Main()
{
var EmployeeName = "Ernestine Lamb";
object Address = "10244 Lockwood Drive";

Console.Write("Employee Name: ");


Console.WriteLine(EmployeeName);
Console.Write("Home Address: ");
Console.WriteLine(Address);
Console.WriteLine();
}
}

This would produce:


Employee Name: Ernestine Lamb
Home Address: 10244 Lockwood Drive

Press any key to continue . . .

A variable declared with object can embrace almost any value. This means that, when
initializing the variable, you can use any of the types of values we have seen so far. Here
are examples:
using System;
class Program
{
static void Main()
{
object PropertyNumber = "293749";
object PropertyType = 'S';
object Stories = 3;
object Bedrooms = 4;
object Value = 425880;

Console.WriteLine("=//= Altair Realty =//=");


Console.WriteLine("Properties Inventory");
Console.Write("Property #: ");
Console.WriteLine(PropertyNumber);
Console.Write("Property Type: ");
Console.WriteLine(PropertyType);
Console.Write("Stories: ");
Console.WriteLine(Stories);
Console.Write("Bedrooms: ");
Console.WriteLine(Bedrooms);
Console.Write("Market Value: ");
Console.WriteLine(Value);
}
}
C# 3.0 Practical Learning 65
This would produce:
=//= Altair Realty =//=
Properties Inventory
Property #: 293749
Property Type: S
Stories: 3
Bedrooms: 4
Market Value: 425880
Press any key to continue . . .

Constants
 

Custom Constants

Suppose you intend to use a number such as 39.37 over and over again. Here is an
example:
using System;

class Exercise
{
static void Main()
{
double Meter, Inch;

Meter = 12.52D;
Inch = Meter * 39.37D;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");
}
}

Here is an example of running the program:


12.52m = 492.9124in

If you use this 39.37 many times in your program, at one time, you may make a mistake
and type it as 3937 or 3.937 or else. Consider the following program:
using System;

class Exercise
{
static void Main()
{
double Meter, Inch;

Meter = 12.52D;
Inch = Meter * 39.37;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");
C# 3.0 Practical Learning 66
Meter = 12.52D;
Inch = Meter * 3.937;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");

Meter = 12.52D;
Inch = Meter * 393.7;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");
}
}

This would produce:


12.52m = 492.9124in

12.52m = 49.29124in

12.52m = 4929.124in

Because of mistakes in the way to represent the number, the same calculation produces
different results. To make sure that this is unlikely, you can instead use a variable that
holds the value. Then, when you need that value, you can access the variable instead of
the value itself. A number such as 39.37 is called a constant.

A constant is a value that never changes such as 244, "ASEC Mimosa", 39.37, or True.
These are constant values you can use in your program any time. You can also declare a
variable and make it a constant; that is, use it so that its value is always the same.

To create a constant, type the const keyword to its left. When declaring a constant, you
must initialize it with an appropriate value. Here is an example:
const double ConversionFactor = 39.37D;

Once a constant has been created and it has been appropriately initialized, you can use its
name where the desired constant would be used. Here is an example of a constant
variable used various times:
using System;

class Exercise
{
static void Main()
{
const double ConversionFactor = 39.37D;
double Meter, Inch;

Meter = 12.52D;
Inch = Meter * ConversionFactor;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");

C# 3.0 Practical Learning 67


Meter = 12.52D;
Inch = Meter * ConversionFactor;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");

Meter = 12.52D;
Inch = Meter * ConversionFactor;
Console.Write(Meter);
Console.Write("m = ");
Console.Write(Inch);
Console.WriteLine("in\n");
}
}

This would produce:


12.52m = 492.9124in

12.52m = 492.9124in

12.52m = 492.9124in

Notice that, this time, the calculation is more accurate. Also, this time, if you mistype the
name of the variable in an operation, you would receive a compiler error, giving you the
time to fix it.

To initialize a constant variable, the value on the right side of the assignment operator "="
must be a constant or a value that the compiler can determine as constant. Instead of
using a known constant, you can also assign it another variable that has already been
declared as constant.

Built-in Constants

There are two main categories of constants you will use in your programs. You can create
your own constant as we saw above. The C# language also provides various constants.
Some constants are part of the C# language. Some other constants are part of the .NET
Framework. Before using a constant, of course, you must first know that it exists. Second,
you must know how to access it. A constant that is part of the C# language can be
accessed anywhere in your code. Those constant are normally defined in the System
namespace. Other constant are defined in various appropriate namespaces.

null: The null keyword is a constant used to indicate that a variable doesn't hold a known
value

PI: PI is a constant used as the ratio of the circumference of a circle to its diameter. PI is
defined in Math. To use it, you would type Math.PI.

C# 3.0 Practical Learning 68


4 - INTRODUCTION TO
CLASSES
 

Fundamentals of Classes
 

Introduction

In the previous two lessons, to use a variable, we were declaring it using either var or a
known and simple data type. For example, we could use an integer to declare a variable
that represented the number of bedrooms of a house. Here is an example:

using System;

class Program
{
static void Main()
{
int bedrooms = 3;
}
}

As opposed to a simple variable, in C#, you can use one or more variables to create a
more complete or complex object.

Instead of only one file, you can create a program with many of them. Each file can
contain different instructions that, when put together, can create an application as
complete as possible. To create a code file, on the main menu, you can click Project ->
Add New Item... In the Templates list, click Code File, accept or change the name of the
file. You can omit the .cs extension. If you do, a file with the extension .cs would be
added.

Practical Learning: Introducing Classes

1. Start Microsoft Visual C#

2. Create a Console Application named DepartmentStore1

3. Execute the application to see the result

4. Close the DOS window

Creating a Class

C# 3.0 Practical Learning 69


A class is a technique of using one or a group of variables to be used as a foundation for a
more detailed variable. To create a class, you start with the class keyword followed by
a name and its body delimited by curly brackets. Here is an example of a class called
House:
class House
{
}

A class is created in a code file. As such, you can include it in the first file of your project.
Here is an example:
using System;

class House
{
}

class Program
{
static void Main()
{
int bedrooms = 3;
}
}

You can also create a class in its own file. To assist you with this, Microsoft Visual C#
provides a wizard. To use it, on the main menu, you can click Project -> Add Class... or
Project -> Add New Item... In the Templates list, click Class. In the Name text box, accept
or change the default name and click Add. A new file named after the class with the .cs
extension would be added to your project.

When a project is made of various files, each file is represented by a tab in the top section
of the Code Editor:

C# 3.0 Practical Learning 70


To access a file, you can click its tab.

Practical Learning: Introducing Classes

1. To create a new class, on the main menu, click Project -> Add Class...

2. In the Add New Item dialog box, change the name to DepartmentStore and click
Add

Visually Managing Classes

To assist you with managing the various classes of a project, Microsoft Visual C# includes
various tools and windows. One of the windows you can use is called the Class View. To
display it, on the main menu, you can click View -> Class View:

C# 3.0 Practical Learning 71


The Class View is made of four sections. The toolbar under the title bar includes four
buttons. To identify a button, you can position the mouse on it and a tool tip would
appear.

Under the toolbar, another bar made of a combo box and a button allow you to search.

The main top section of the Class View is made of various nodes. To expand a node, you
can click its + button. To collapse a node, you can click its - button. The top node displays
the name of the project. Under the project node, the names of classes display. The
bottom section of the Class View is used to display the members of a class. To see the
members of a class, you can click it in the top window. Here is an example:

To add a new class, besides the main menu, you can right-click the name of the project in
the Class View, position the mouse on Add, and click Class...

Declaring a Variable of a Class Type

Like any normal variable, to use a class in your program, you can first declare a variable
for it. Like the variables we introduced in the previous lesson, to declare a variable of a
class, you can use the var keyword. Alternatively, you can type its name followed by a

C# 3.0 Practical Learning 72


name for the variable. For example, to declare a variable of the above House class, you
could type the following:
using System;

class House
{
}

class Program
{
static void Main()
{
var property . . .
}
}

Or the following:
using System;

class House
{
}

class Program
{
static void Main()
{
House property;
}
}

The variables we have declared so far are called value variables. This is because such
variables of primitive types hold their value. The C# language supports another type of
variable. This time, when you declare the variable, its name does not hold the value of the
variable; it holds a reference to the address where the actual variable is stored in memory.
This reference type is the kind used to declare a variable for a class.

To use a variable as reference, you must initialize it using an operator called new. Here is
an example:
using System;

class House
{
}

class Program
{
static void Main()
{
var Property = new House();
}
}

If you are using the name of the class instead of var to declare the variable, you can first
declare it. Then, on another line, you can allocate memory for it using the new operator.
Here is an example:
C# 3.0 Practical Learning 73
using System;

class House
{
}

class Program
{
static void Main()
{
House Property;

// You can do something here

Property = new House();


}
}

In C#, as well as Visual Basic, if you create a class in any of the files that belong to the
same project, the class is made available to all other files of the same project.

Sharing a Class

Unlike its sisters the C and the C++ languages, C# was developed with the idea of
working complementarily with other languages such as C++/CLI, Visual Basic, and J#. In
other words, code from these other languages should be able to "read" or access code
written in a C# application. To make this possible, a C# class can be created as a public
object.

If you want your class to be accessible to code written in other languages, precede the
class keyword with public when creating it. Here is an example:

using System;

public class Exercise

{
static void Main()
{
var Number = 244;
var Thing = "Vehicle";

Console.WriteLine(Number);
Console.WriteLine(Thing);
}
}

Garbage Collection

When you initialize a variable using the new operator, you are in fact reserving some space
in the heap memory. The memory is "allocated" for the variable. When that variable is no
longer needed, such as when your program closes, it (the variable) must be removed from
memory and the space it was using can be made available to other variables or other
programs. This is referred to as garbage collection. In the past, namely in C/C++, this was

C# 3.0 Practical Learning 74


a concern for programmers because they usually had to remember to manually delete
such a variable (a pointer) and free its memory.

The .NET Framework solves the problem of garbage collection by "cleaning" the
memory after you. This is done automatically when necessary so that the programmer
doesn't need to worry about this issue.

Class' Fields
 

Introduction

Consider a class named House:


public class House
{
}

The section between the curly brackets, { and }, of a class is referred to as its body. In
the body of a class, you can create a list of the parts that make up the class. Each of
these parts must be a complete variable with a name and a data type. For example, here
are the characteristics that make up a house, declared as the parts of the above Book
class and each declared as a variable:
public class House
{
string PropertyNumber;
char PropertyType;
byte Stories;
uint bedrooms;
decimal Value;
}

The variables declared in the body of a class are referred to as its member variables and
each member variable is referred to as a field. The fields can be any type we have seen in
the previous lesson. When creating a class, it is your job to decide what your object is
made of.

Practical Learning: Introducing Class Members

Imagine you want to write a (console-based) program for a department store and the
customer has given you a preliminary catalog as follows:

C# 3.0 Practical Learning 75


Stock #: 437876 Stock #: 792475 Stock #: 740797
Women Scoop Neck Dress Men Lightweight Jacket Girls Velour Active Skirt
Unit Price: $148.00 Unit Price: $185 Unit Price: $22.85

Stock: 681432
Stock #: 759470 Stock #: 482746
Women Python Print Leather
Men Escalade Slip-On Shoes Boys Leather Bomber Jacket 
Bag
$89.85 $255.50
$75.00

Each item in this catalog is represented by its Stock number, its name or description, and
its price. Based on this, you can create a class that represents each item.

1. Change the DepartmentStore class as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore1
{
class DepartmentStore
{
long StockNumber;
char Category;
string ItemName;
decimal UnitPrice;
C# 3.0 Practical Learning 76
}
}

2. Save the file

Accessing Class Members


 

Private Members

The parts of an object fall into two main categories: those you can touch and those you
don't have access to. For example, for a car parked at the mall, you can see or touch its
doors and its tires but you don't see its engine or its spare tire, you don't even know if it
has one. The parts of an object that you have access to are referred to as public. Those
you can't see or touch are referred to as private.

A C# class also recognizes that some parts of a class can be made available to other
classes and some other parts can be hidden from other classes. A part that must be
hidden from other classes is private and it can be declared starting with the private
keyword. If you declare a member variable and want to make it available to other classes,
you must start its name with the public keyword. The public and private keywords
are referred to as access level.

By default, if you declare a member variable (or anything else) in a class but don't specify
its access level, the member is considered private and cannot be accessed from outside,
that is by a non-member, of that class. Therefore, to make a member accessible by other
classes, you must declare it as public.

You can use a mix of public and private members in a class and there is no rule on which
access level should be listed first or last. Here are examples:
public class House
{
string PropertyNumber;
public char PropertyType;
byte Stories;
public uint bedrooms;
private decimal Value;
}

Just keep in mind that if you omit or forget the access level of a member of a class, the
member is automatically made private. To reduce confusion as to what member is public
or private, you should always specify the access level of a member variable.
public class House
{
public string PropertyNumber;
public char PropertyType;
public byte Stories;
public uint Bedrooms;
public decimal Value;
}

C# 3.0 Practical Learning 77


After creating a member of a class, to access it from another class, first declare a variable
from its class as we saw earlier. To actually access the member, use the period operator
".".

Internal Members

We have seen that the public keyword is used to let objects of the same program and
objects of other programs access the public member. The private keyword is used to let
only members of a class access the (private) member of the class. If you want to create a
member of a class so that only objects of the same program can access that member, you
can mark it with the internal keyword. The differences between these keywords can be
resumed as follows:

  If a class member is marked as

  public private internal

Members of its class can access


Yes Yes Yes
this member

Members of this program,


including outside of the class, Yes No Yes
can access this member

Objects outside of this program


Yes No No
can access this member

Initializing an Object
 

Introduction

 After declaring an instance of a class, you can access each of its members and assign it
the desired value. Here is an example:
using System;

public class House


{
internal long PropertyNumber;
internal string PropertyType;
internal uint Bedrooms;
internal double Value;
}

C# 3.0 Practical Learning 78


public class Exercise
{
static void Main()
{
var Property = new House();

Property.PropertyNumber = 283795;
Property.PropertyType = "Single Family";
Property.Bedrooms = 4;
Property.Value = 652880;
}
}

Once a member variable has been initialized, you can use the period operator to access it
and retrieve its value:
using System;

public class House


{
internal long PropertyNumber;
internal string PropertyType;
internal uint Bedrooms;
internal double Value;
}

public class Exercise


{
static void Main()
{
var Property = new House();

Property.PropertyNumber = 283795;
Property.PropertyType = "Single Family";
Property.Bedrooms = 4;
Property.Value = 652880;

Console.WriteLine("=//= Altair Realty =//=");


Console.WriteLine("Properties Inventory"); ;
Console.Write("Property #: ");
Console.WriteLine(Property.PropertyNumber);
Console.Write("Property Type: ");
Console.WriteLine(Property.PropertyType);
Console.Write("Bedrooms: ");
Console.WriteLine(Property.Bedrooms);
Console.Write("Market Value: ");
Console.WriteLine(Property.Value);
}
}

This would produce:


=//= Altair Realty =//=
Properties Inventory
Property #: 283795
Property Type: Single Family
Bedrooms: 4
Market Value: 652880
Press any key to continue . . .
C# 3.0 Practical Learning 79
Practical Learning: Using a Class' Fields

1. To make public the members of the DepartmentStore class, type the public
keyword to their left:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore1
{
class DepartmentStore
{
public long StockNumber;
public char Category;
public string ItemName;
public double UnitPrice;
}
}

2. To access the Program.cs file, click its tab above the Code Editor

3. Change Main() as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore1
{
class Program
{
static void Main(string[] args)
{
DepartmentStore dptStore = new DepartmentStore();

dptStore.StockNumber = 437876;
dptStore.Category = 'W';
dptStore.ItemName = "Scoop Neck Dress";
dptStore.UnitPrice = 148.00D;

Console.WriteLine("Department Store");
Console.Write("Stock #: ");
Console.WriteLine(dptStore.StockNumber);
Console.Write("Category: ");
Console.WriteLine(dptStore.Category);
Console.Write("Name: ");
Console.WriteLine(dptStore.ItemName);
Console.Write("Unit Price: ");
Console.WriteLine(dptStore.UnitPrice);
Console.WriteLine();
}
}
}

C# 3.0 Practical Learning 80


4. Execute the application. This would produce:
 
Department Store
Stock #: 437876
Category: W
Name: Scoop Neck Dress
Unit Price: 148.00

Press any key to continue . . .

5. Close the DOS window

Using an Anonymous Type

We saw that, to use a class, you could first declare a variable for it and initialize it.
Fortunately, you don't have to use a class to initialize an object. You can declare a variable
that resembles an instance of a class and initialize it as you see fit. This is referred to as
an anonymous type. To use it, declare the variable using the var keyword and use the
new operator to allocate memory for it. Instead of using the name of a class, type an
opening and a closing curly brackets after the new operator. In the curly brackets, state a
name for each member as if it were the member of the class and initialize each member
variable with the desired value. After the closing curly bracket, end the declaration with a
semi-colon. Here is an example:
using System;

public class Exercise


{
static void Main()
{
var BookInformation = new
{

Title = "Calculus 6e Edition",

Pages = 1074,
Cover = "Hard Back"
};
}
}

After initializing the anonymous type, you can access each one of its members using the
name of the variable followed by the period operator, and followed by the member
variable. Here is an example:
using System;

public class Exercise


{
static void Main()
{
var BookInformation = new
{
Title = "Calculus 6e Edition",
Pages = 1074,
Cover = "Hard Back"

C# 3.0 Practical Learning 81


};

Console.WriteLine("=//= BookInformation =//=");


Console.Write("Title: ");
Console.WriteLine(BookInformation.Title);
Console.Write("Nbr of Pages: ");
Console.WriteLine(BookInformation.Pages);
Console.Write("Type of Cover: ");
Console.WriteLine(BookInformation.Cover);
}
}

This would produce:


=//= BookInformation =//=
Title: Calculus 6e Edition
Nbr of Pages: 1074
Type of Cover: Hard Back
Press any key to continue . . .

Remember that spreading the declaration on many lines only makes it easy to read.
Otherwise, you can as well include everything on the same line.
using System;

public class Exercise


{
static void Main()
{
var Book = new { Title = "Calculus 6e Edition", Pages = 1074 };

Console.WriteLine("=//= BookInformation =//=");


Console.Write("Title: ");
Console.WriteLine(BookInformation.Title);
Console.Write("Nbr of Pages: ");
Console.WriteLine(BookInformation.Pages);
}
}

The Methods of a Class


 

Introduction

When you create a class, the fields are meant to describe it. For a class named House,
such aspects as the number of bedrooms, the property type, or its value, are used to
describe it:
public class House
{
public char PropertyType;
public uint Bedrooms;
}

Besides the characteristics used to describe it, an object can also perform actions or
assignments. An action performed by a class is called a method. A method is simply a
section of code that takes care of a particular detail for the functionality of the class. To

C# 3.0 Practical Learning 82


create a method, you specify its name, which follows the rules we defined for variables.
The name of a method is followed by parentheses.

A method's job is to carry a specific assignment within a program. As such, it could


provide a value once the assignment has been carried. In some cases, a method must
produce a result. If it doesn't, then it is considered void. The type of value that a method
can provide (or return) is written on the left side of the method name. If the method
doesn't produce a result, type void to its left. The assignment that a method carries is
included between an opening curly bracket "{" and a closing curly bracket "}". Here is an
example:
public class House
{
public char PropertyType;
public uint Bedrooms;

void Display()
{
}
}

The most regularly used method of a C# program is called Main.

Like a member variable:

 If the method will be accessed only by members of the same class, you can mark it
as private  or not mark it with an access keyword

 If the method will be accessed by members of the class and other parts of the
same program but not outside of the program, mark it with the internal keyword

 In the method can be accessed by the members of the same class, other parts of
the same program, and other parts of other programs, mark it as public

After creating a method, in its body delimited by its curly brackets, you can define the
desired behavior. For example, you can write the member variables in the parentheses of
Console.Write() or Console.WriteLine(). Here are examples:

public class House


{
public char PropertyType;
public uint Bedrooms;

internal void Display()


{
Console.WriteLine("=//= Altair Realty =//=");
Console.WriteLine("Properties Inventory"); ;
Console.Write("Property Type: ");
Console.WriteLine(PropertyType);
Console.Write("Bedrooms: ");
Console.WriteLine(Bedrooms);
}
}

In the same way, you can create as many methods as you want in a class. To assist you
with managing the methods of a class, the Code Editor is equipped with two combo boxes.

C# 3.0 Practical Learning 83


The left combo box, called Types, displays the classes that are part of the project. The
right combo box, named Members, displays the members of the class that is selected in
the Types combo box:

If you select an item from the Members combo box, the caret would be displayed on its
declaration in the file.

The Solution Explorer

The Solution Explorer is a window that displays the file names and other items used in
your project. The items of this window display in a tree. To expand a node, you can click
its + button. To collapse it, click its - button. To explore an item, you can double-click it.
The result depends on the item you double-clicked.

The Solution Explorer can be used to create and add a new class or a new item to the
current project. It can also be used to add a another project to the current project. To

C# 3.0 Practical Learning 84


perform any of these operations, you can right-click a folder node such as the name of
the project and position the mouse on Add to select the desired operation:

Remember that you can also perform any of these operations from the Project category of
the main menu.

Besides adding new items to the project, you can also use the Solution Explorer to build
the project or change its properties. If you add one or more other project(s) to the current
one, one of the project must be set as the default. That project would be the first to come
up when the user executes the application. By default, the first project created is set as
the default. If you have more than one project, to set the default, right-click the name of
the desired project in Solution Explorer and click Set As StartUp Project.

The Solution Explorer also allows you to rename or delete some of the items that belong
to your project.

Practical Learning: Creating the Methods of a Class

1. Access the DepartmentStore.cs file

2. To add some methods to the DepartmentStore class, change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore1
{
class DepartmentStore
{
public long StockNumber;

C# 3.0 Practical Learning 85


public char Category;
public string ItemName;
public double UnitPrice;

public void CreateItem()


{
StockNumber = 792475;
Category = 'M';
ItemName = "Lightweight Jacket";
UnitPrice = 185.00D;
}

public void ShowItem()


{
Console.WriteLine("Department Store");

Console.Write("Stock #: ");
Console.WriteLine(StockNumber);
Console.Write("Category: ");
Console.WriteLine(Category);
Console.Write("Name: ");
Console.WriteLine(ItemName);
Console.Write("Unit Price: ");
Console.WriteLine(UnitPrice);
Console.WriteLine();
}
}
}

3. Access the Program.cs file and change Main() as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore1
{
class Program
{
static void Main(string[] args)
{
DepartmentStore dptStore = new DepartmentStore();

dptStore.CreateItem();
dptStore.ShowItem();
}
}
}

4. Execute the application. This would produce:


 
Department Store
Stock #: 792475
Category: M
Name: Lightweight R4 Jacket
Unit Price: $185.00

C# 3.0 Practical Learning 86


Press any key to continue . . .

5. Close the DOS window

Accessing a Method

After creating a method, you can access it outside of its class. You do this following the
same rules used to access a field, using the period operator. Unlike a field, the name of a
class must be followed by parentheses. Here is an example:
using System;

public class House


{
public char PropertyType;
public uint Bedrooms;

internal void Display()


{
Console.WriteLine("=//= Altair Realty =//=");
Console.WriteLine("Properties Inventory"); ;
Console.Write("Property Type: ");
Console.WriteLine(PropertyType);
Console.Write("Bedrooms: ");
Console.WriteLine(Bedrooms);
}
}

public class Program


{
static void Main()
{
var Property= new House();

Property.PropertyType = 'S';
Property.Bedrooms = 4;

Property.Display();
}
}

This would produce:


=//= Altair Realty =//=
Properties Inventory
Property Type: S
Bedrooms: 4
Press any key to continue . . .

The Static Members of a Class


 

Static Fields

C# 3.0 Practical Learning 87


Imagine you create a class called Book. To access it in the Main() method, you can
declare its variable, as we have done so far. A variable you have declared of a class is also
called an instance of the class. In the same way, you can declare various instances of the
same class as necessary:
using System;

public class Book


{
public string Title;
public string Author;
public short YearPublished;
public int NumberOfPages;
public char CoverType;
}

public class Exercise


{
static void Main()
{
var written = new Book();
var bought = new Book();
}
}

Each one of these instances gives you access to the members of the class but each
instance holds the particular values of the members of its instance. Consider the results of
the following program:
using System;

public class Book


{
public string Title;
public string Author;
public short YearPublished;
public int NumberOfPages;
public char CoverType;
}

public class Exercise


{
static void Main()
{
var First = new Book();

First.Title = "Psychology and Human Evolution";


First.Author = "Jeannot Lamm";
First.YearPublished = 1996;
First.NumberOfPages = 872;
First.CoverType = 'H';

Console.WriteLine("Book Characteristics");
Console.Write("Title: ");
Console.WriteLine(First.Title);
Console.Write("Author: ");
Console.WriteLine(First.Author);
Console.Write("Year: ");
Console.WriteLine(First.YearPublished);

C# 3.0 Practical Learning 88


Console.Write("Pages: ");
Console.WriteLine(First.NumberOfPages);
Console.Write("Cover: ");
Console.WriteLine(First.CoverType);

var Second = new Book();

Second.Title = "C# First Step";


Second.Author = "Alexandra Nyango";
Second.YearPublished = 2004;
Second.NumberOfPages = 604;
Second.CoverType = 'P';

Console.WriteLine("Book Characteristics");
Console.Write("Title: ");
Console.WriteLine(Second.Title);
Console.Write("Author: ");
Console.WriteLine(Second.Author);
Console.Write("Year: ");
Console.WriteLine(Second.YearPublished);
Console.Write("Pages: ");
Console.WriteLine(Second.NumberOfPages);
Console.Write("Cover: ");
Console.WriteLine(Second.CoverType);
Console.WriteLine();
}
}

This would produce:


Book Characteristics
Title: Psychology and Human Evolution
Author: Jeannot Lamm
Year: 1996
Pages: 872
Cover: H

Book Characteristics
Title: C# First Step
Author: Alexandra Nyango
Year: 2004
Pages: 604
Cover: P

All of the member variables and methods of classes we have used so far are referred to as
instance members because, in order to access them, you must have an instance of a class
declared in another class in which you want to access them.

C# allows you to declare a class member and refer to it regardless of which instance of an
object you are using. Such a member variable is called static. To declare a member
variable of a class as static, type the static keyword on its left. Whenever you have a
static member, in order to refer to it, you must "qualify" it in the class in which you want
to call it. Qualifying a member means you must specify its class. Here is an example:
using System;

public class Book


{
public static string Title;

C# 3.0 Practical Learning 89


public static string Author;
public short YearPublished;
public int Pages;
public char CoverType;
}

public class Exercise


{
static void Main()
{
var First = new Book();

Book.Title = "Psychology and Human Evolution";


Book.Author = "Jeannot Lamm";
First.YearPublished = 1996;
First.Pages = 872;
First.CoverType = 'H';

Console.WriteLine("Book Characteristics");
Console.Write("Title: ");
Console.WriteLine(Book.Title);
Console.Write("Author: ");
Console.WriteLine(Book.Author);
Console.Write("Year: ");
Console.WriteLine(First.YearPublished);
Console.Write("Pages: ");
Console.WriteLine(First.Pages);
Console.Write("Cover: ");
Console.WriteLine(First.CoverType);

var Second = new Book();

Book.Title = "C# First Step";


Book.Author = "Alexandra Nyango";
Second.YearPublished = 2004;
Second.Pages = 604;
Second.CoverType = 'P';

Console.WriteLine("Book Characteristics");
Console.Write("Title: ");
Console.WriteLine(Book.Title);
Console.Write("Author: ");
Console.WriteLine(Book.Author);
Console.Write("Year: ");
Console.WriteLine(Second.YearPublished);
Console.Write("Pages: ");
Console.WriteLine(Second.Pages);
Console.Write("Cover: ");
Console.WriteLine(Second.CoverType);

Console.WriteLine();
}
}

Notice that when a member variable has been declared as static, you don't need an
instance of the class to access that member variable outside of the class. Based on this, if
you declare all members of a class as static, you don't need to declare a variable of their
class in order to access them. In the following example, the Title and Author fields of the

C# 3.0 Practical Learning 90


Book class are accessed from the Program class without using an instance of the Book
class:
using System;

public class Book


{
public static string Title;
public static string Author;
}

public class Exercise


{
static void Main()
{
Book.Title = "Psychology and Human Evolution";
Book.Author = "Jeannot Lamm";

Console.WriteLine("Book Characteristics");
Console.WriteLine("Title: ");
Console.WriteLine(Book.Title);
Console.WriteLine("Author: ");
Console.WriteLine(Book.Author);

Book.Title = "C# First Step";


Book.Author = "Alexandra Miles";

Console.WriteLine("Book Characteristics");
Console.WriteLine("Title: ");
Console.WriteLine(Book.Title);
Console.WriteLine("Author: ");
Console.WriteLine(Book.Author);

Console.ReadLine();
}
}

You can also declare member variables of the main class as static. If you are referring to a
static member variable in the same class in which it was declared, you don't have to
qualify it. Here is an example:
using System;

public class Exercise


{
static double Length;
static double Width;

static void Main()


{
Console.WriteLine("Rectangles Characteristics");

Length = 22.55;
Width = 20.25;

Console.WriteLine("\nRectangle 1");
Console.Write("Length: ");
Console.WriteLine(Length);
Console.Write("Width: ");
Console.WriteLine(Width);
C# 3.0 Practical Learning 91
Length = 254.04;
Width = 408.62;

Console.WriteLine("\nRectangle 2");
Console.Write("Length: ");
Console.WriteLine(Length);
Console.Write("Width: ");
Console.WriteLine(Width);

Console.WriteLine();
}
}

Static Methods

Like a member variable, a method of a class can be defined as static. Consequently, this
particular method can access any member of the class regardless of the instance if there
are many instances of the class declared.

To define a method as static, type the static keyword to its left. Here is an example:
using System;

public class Book


{
private static string Title;
static private string Author;
private static int Pages;
static private double Price;

static public void CreateBook()


{
Title = "Psychology and Human Evolution";
Author = "Jeannot Lamm";
Pages = 472;
Price = 24.95;
}

static public void ShowBook()


{
Console.WriteLine("Book Characteristics");
Console.Write("Title: ");
Console.WriteLine(Book.Title);
Console.Write("Author: ");
Console.WriteLine(Book.Author);
Console.Write("Pages: ");
Console.WriteLine(Pages);
Console.Write("Price: ");
Console.WriteLine(Price);
}
}

public class Exercise


{
static void Main()
{
Book.CreateBook();

C# 3.0 Practical Learning 92


Book.ShowBook();
}
}

This would produce:


Book Characteristics
Title: Psychology and Human Evolution
Author: Jeannot Lamm
Pages: 472
Price: 24.95

The ReadLine(), the Write(), and the WriteLine() methods of the Console class that
we have used so far are examples of static methods.

Static Classes

A static class:

1. Is a class whose members must be accessed without an instance of the class. In


other words, the members of a static class must be accessed directly from (using
the name of) the class, using the period operator

2. Is a class whose members must be created as static. In other words, you cannot
add a non-static member to a static class: all members, except for constants, must
be static

To create a static class, precede the class keyword with the static keyword. Based on
the above two rules, here is an example:
using System;

namespace Staticity
{
public static class Square
{
public static double Side;

public static double Perimeter()


{
return Side * 4;
}

public static double Area()


{
return Side * Side;
}
}

public class Exercise


{
static void Main(string[] args)
{
Square.Side = 36.84;

Console.WriteLine("Square Characteristics");
Console.Write("Side: ");
Console.WriteLine(Square.Side);
C# 3.0 Practical Learning 93
Console.Write("Perimeter: ");
Console.WriteLine(Square.Perimeter());
Console.Write("Area: ");
Console.WriteLine(Square.Area());
}
}
}

This would produce:


Square Characteristics
Side: 36.84
Perimeter: 147.36
Area: 1357.1856
Press any key to continue . . .

Characteristics of Members of a Class


 

Constants

Unlike C/C++, in C#, you can create a constant variable in a class. As done in Lesson 2
when studying variables, to declare a constant variable, type the const keyword to
the left of the variable. Once again, when declaring a constant, you must initialize it with
an appropriate constant value.

this Instance

If a class contains fields and methods, the (non-static) field members are automatically
available to the method(s) of the class, even fields that are private. When accessing a field
or a method from another method of the class, to indicate that the member you are
accessing belongs to the same class, you can precede it with the this member and the
period operator. Here are examples:
public class House
{
internal char PropertyType;
internal uint Bedrooms;

internal void Display()


{
Console.WriteLine("=//= Altair Realty =//=");
Console.WriteLine("Properties Inventory"); ;
Console.Write("Property Type: ");
Console.WriteLine(this.PropertyType);
Console.Write("Bedrooms: ");
Console.WriteLine(this.Bedrooms);
}
}

When using the this member variable (in C/C++, it is a pointer), you can access any
member of a class within any method of the same class. There are rules you must observe
when using this:

C# 3.0 Practical Learning 94


 The this member can never be declared: it is automatically implied when you
create a class

 this cannot be used in a class A to access a member of class B. The following will
cause an error:
 
public class Exercise
{
static void Main()
{
House property = new House();

property.PropertyType = 'S';
property.Bedrooms = 4;

this.property.Display();
}
}

 this cannot be used in a static method

Practical Learning: Using this

1. Access the DepartmentStore.cs file and, to use this, change the class as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore1
{
class DepartmentStore
{
public long StockNumber;
public char Category;
public string ItemName;
public double UnitPrice;

public void CreateItem()


{
this.StockNumber = 792475;
this.Category = 'M';
this.ItemName = "Lightweight Jacket";
this.UnitPrice = 185.00D;
}

public void ShowItem()


{
Console.WriteLine("Department Store");

Console.Write("Stock #: ");
Console.WriteLine(this.StockNumber);
Console.Write("Category: ");
Console.WriteLine(this.Category);
Console.Write("Name: ");
C# 3.0 Practical Learning 95
Console.WriteLine(this.ItemName);
Console.Write("Unit Price: ");
Console.WriteLine(this.UnitPrice);
Console.WriteLine();
}
}
}

2. Execute the application to see the result

3. Close the DOS window

C# 3.0 Practical Learning 96


5 - C# AND CODE
ORGANIZATION
 

Namespaces
 

Introduction

A namespace is a section of code that is identified with a specific name. The name could
be anything such as somebody's name, the name of the company's department, or a city.
To create a namespace, you start with the namespace keyword followed by the name of
the section. Like a class, the section that is part of a namespace starts with an opening
curly bracket "{" and ends with a closing curly bracket "}". Here is an example:
namespace Business
{
}

Between the curly brackets, you can type anything that is part of the namespace. For
example, you can create a class inside of a namespace. Here is an example:
namespace Business
{
class House
{
}
}

  

Practical Learning: Creating a Namespacep>

1. Start Microsoft Visual C# 2005 and create a new Console Application named
RealEstate1

2. To create a new class, in the Class View, right-click the name of the project,
position the mouse on Add and click Class...

3. Change the name to House and press Enter

4. Change the class as follows:


 

using System;

C# 3.0 Practical Learning 97


using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate1
{
public class House
{
public string PropertyNumber;
public char PropertyType;
public uint Stories;
public uint Bedrooms;
public float Bathrooms;
public double Value;
}
}

5. Save the file

Accessing Members of a Namespace

After creating the necessary members of a namespace, you can use the period operator to
access an item that is part of the namespace. To do this, in the desired location, type the
name of the namespace, followed by a period, followed by the desired member of the
namespace. Here is an example:
using System;

namespace Business
{
public class House
{
public string PropertyNumber;
public decimal Price;
}
}

public class Exercise


{
static void Main()
{
Business.House property = new Business.House();

property.PropertyNumber = "D294FF";
property.Price = 425880;

Console.WriteLine("=//= Altair Realty =//=");


Console.WriteLine("Properties Inventory");
Console.Write("Property #: ");
Console.WriteLine(property.PropertyNumber);
Console.Write("Market Value: ");
Console.WriteLine(property.Price);
Console.WriteLine();
}
}

This would produce:


=//= Altair Realty =//=
C# 3.0 Practical Learning 98
Properties Inventory
Property #: D294FF
Market Value: 425880

Press any key to continue . . .

Namespace Nesting

You can create one namespace inside of another namespace. Creating a namespace inside
of another is referred to as nesting the namespace. The namespace inside of another
namespace is nested. To create a namespace inside of another, simply type it as you
would create another namespace. Here is an example:
namespace Business
{
public class House
{
public string PropertyNumber;
public decimal Price;
}

namespace Dealer
{
}
}

In the example above, the Dealer namespace is nested inside of the Business namespace.
After creating the desired namespaces, nested or not, you can create the necessary
class(es) inside of the desired namespace. To access anything that is included in a nested
namespace, you use the period operator before calling a member of a namespace or
before calling the next nested namespace. Here is an example:
using System;

namespace Business
{
public class House
{
public string PropertyNumber;
public decimal Price;
}

namespace Dealer
{
public class Car
{
public decimal Price;
}
}
}

public class Exercise


{
static void Main()
{
Business.House property = new Business.House();

property.PropertyNumber = "D294FF";
C# 3.0 Practical Learning 99
property.Price = 425880;

Console.WriteLine("=//= Altair Realty =//=");


Console.WriteLine("Properties Inventory");
Console.Write("Property #: ");
Console.WriteLine(property.PropertyNumber);
Console.Write("Market Value: ");
Console.WriteLine(property.Price);
Console.WriteLine();

Business.Dealer.Car vehicle = new Business.Dealer.Car();


vehicle.Price = 38425.50M;

Console.Write("Car Value: ");


Console.WriteLine(vehicle.Price);
}
}

This would produce:


=//= Altair Realty =//=
Properties Inventory
Property #: D294FF
Market Value: 425880

Car Value: 38425.50


Press any key to continue . . .

In the same way, you can nest as many namespaces inside of other namespaces as you
judge necessary.

The System Namespace


 

Introduction

To make programming in C# a little easier, many classes ship with it and they are created
in various namespaces of the .NET Framework. Each namespace in C# is used to
provide a specific set of classes. The most regularly used namespace in the C# language
is called System. Inside of the System namespace is a class called Console. The Console
class is used to display things on the console screen also called the DOS window.

The Console class contains static methods to display information on the screen or to
retrieve information from the user who types it in the DOS window. The method that is
used to display text on the screen is called Write. To use the Write() method, inside of
the parentheses, type the sentence between double-quotes. Here is an example:
public class Exercise
{
static void Main()
{

System.Console.Write("The Wonderful World of C# Programming");

}
}

C# 3.0 Practical Learning 100


Besides the Write() method, the Console class also provides another static method
named WriteLine(). The difference is that, after displaying something on the screen, the
Write() method keeps the caret on the same line but WriteLine() transfers the caret to
the next line. We will see various examples of this behavior throughout our lessons.

Using a Namespace

We saw that, to call an object or a method that is part of a namespace, you must "qualify"
that method or object using the period operator. Instead of using this approach, if you
already know the name of a namespace that exists or has been created in another file,
you can use a special keyword to indicate that you are using a namespace that is defined
somewhere. This is done with the using keyword. To do this, on top of the file
(preferably), type using followed by the name of the namespace.

With the using keyword, you can include as many external namespaces as necessary.

Practical Learning: Using the Keyword

 Access the Program.cs file and notice that it has a using declaration

.NET Support of Data Types


 

Introduction

In C# (unlike many other languages such as C/C++, Pascal, etc), all of the data types we
have used so far are in fact complete classes. This means that they are equipped with
methods. These classes are defined in the System namespace. The classes of these data
types are defined as:

Equivalent Equivalent .
C# Data Type C# Data Type
.NET Class NET Class

bool Boolean char Char

byte Byte sbyte SByte

short Int16 ushort UInt16

int Int32 uint UInt32

long Int64 ulong UInt64

  float Single   double Double

C# 3.0 Practical Learning 101


  decimal Decimal      

This means that, if you don't want to use the data types we have reviewed so far, you can
use the class that is defined in the System namespace. To use one of these types, type
the System namespace followed by a period. Then type the equivalent class you want to
use. Here is an example:

class Operations

{
public double Addition()
{
System.Double a;
System.Double b;
System.Double c;

a = 128.76;
b = 5044.52;
c = a + b;

return c;
}
}

Because the regular names of data types we introduced in the previous lessons are more
known and familiar, we will mostly use them.

Because the data types are defined as classes, they are equipped with methods. One of
the methods that each one of them has is called ToString. As its name implies, it is used
to convert a value to a string.

C# Language Accessories
 

Command Line Options

 In Lesson 1, we saw that, to see the result of an application, you must execute it. To
make this possible,, Microsoft Visual C# ships with an internal program called a compiler.
A compiler is a computer program made of internal other sub-programs. One of the
sub-programs, in fact probably the first, of a compiler is called a parser. A parser "scans"
a file that contains (part of) the program. It checks for syntax, keywords, unknown words,
and some other routines. If the parser finds a problem, which could be anything, either it
stops or it continues making a list of the mistakes it found. Then it displays this list to you
to fix. Sometimes it would point to the exact line where the/a problem was found.
Sometimes it would point to the line where the problem showed its impact although the
problem may be found somewhere else. With experience, you will know how to fix the
programs or troubleshoot these problems. In this ebook, we will address as many issues
as possible.

If the parser doesn't find any problem, or after you have fixed the problems, it (the
parser) passes its result(s) to the compiler. The compiler calls another program called a

C# 3.0 Practical Learning 102


linker. If the program contains just one file, the linker considers it. If the program contains
more than one file, the linker considers them. The linker gathers some of the files that the
C# compiler shipped with (those files that your program needs in order to work, since
your program doesn't need all possible files that C# ships with), puts them together
("links" them) with your file(s) to get your instructions in a manner that can produce a
suitable result. If there is no significant problem, the compiler creates the program. This
doesn't mean that everything is alright, it only means that the compiler thinks that
everything is alright: it is still possible that the result may not be what you would expect.
To make your life easier, all of the sub-programs (parser, linker, debugger, etc) that ship
with C# are grouped in one large program: the compiler. Therefore, from now on, we will
use the word "compiler" to refer to the program you use to "translate" your English-
based instructions into a computer-based language.

The compiler that ships with the C# version we will use, that is, the compiler of the
Microsoft .NET Framework is a program called csc. Like most other programs, it has the
extension .exe. This csc name is not standard. This means that another C# compiler may
have another name; csc.exe is just the name of the compiler we will use.

The csc compiler is freely available if you download the .NET Framework from the
Microsoft web site.

In this book, we will create our program using Microsoft Visual C# but if you didn't have it,
you would still be able to create and execute applications. To do this, at the Command
Prompt, you would type csc, followed by the name of the file that contains the code with
its extension. An example would be:
csc Filename.cs

When you do this, an executable with the same name as the file is created. If you want,
you can ask the compiler to produce an executable using the name of your choice. To do
this, you would compile the project using the following formula:
csc /out:NameOfExecutate.exe Filename.cs

The NameOfExecutate factor in our formula represents the name you want the executable
to have. If the name you want is in one word, you can just type it. If you want a name
made of various words, you can include those words in double-quotes

The FileName factor is one we are familiar with.

Unsafe Code

When C# was invented, one of its biggest goals was to avoid some of the difficulties of
C/C++. Among them was the use of pointers. C/C++ uses pointers to refer to the area in
memory where a value is located. C# highly avoids pointers and takes over memory
management as opposed to letting the programmer take care of that aspect of an
application. You can still use pointers in C# in extreme cases when you judge them
necessary.

Because the C# compiler is in charge of managing the memory used by the values of an
application, pointers are said to be unsafe. If you want to use a pointer in your
application, you must precede the name of every method that uses unsafe code with the
unsafe keyword. Here is an example:

C# 3.0 Practical Learning 103


using System;

class Exercise
{
unsafe static void Main()
{
int Length = 224;
int *Len = &Length;

Console.Write("Length ");
Console.WriteLine(Length);
Console.Write("Length ");
Console.WriteLine(*Len);
Console.WriteLine();

Length = 804;
Console.Write("Length ");
Console.WriteLine(Length);
Console.Write("Length ");
Console.WriteLine(*Len);
}
}

To compile the application, you must indicate that you are using unsafe code. To do that,
use the /unsafe modifier. Here is an example:
csc /unsafe Exercise.cs

To apply this option in Microsoft Visual C#, on the main menu, you can click Project ->
Project Properties... In the Build section, click the Allow Unsafe Code check box:

C# 3.0 Practical Learning 104


Code Editor Region Delimiter

Microsoft Visual C# provides various techniques to assist you with code writing and
management. The characteristics include color-coded words, intuitive indentation,
delimitation of sections of code, etc. Consider the following contents of the Code Editor
based on what we have reviewed so far:

Notice that there are - buttons on the left side of some lines of code. These allow you to
collapse a section of code if you think you don't need to see it. To do this, you can click
the - button. If you click that - button, it changes into a + button. Here is an example:

C# 3.0 Practical Learning 105


The + button allows you to expand a hidden code section. This behavior of creating + and
- buttons is part of the Code Editor of Microsoft Visual Studio (yes, many other
programming environments use that behavior also). To create these sections, the
Code Editor follows some rules. For example, it looks for the start and end of such items
as directives, namespaces, classes, methods, etc.

Besides, or instead of, the sections of code created by the Code Editor, if you want, you
can create your own sections. To do this, start the section with
#region Whatever

and end it with


#endregion Whatever

When and where you start, the #region expression is required. On the right side of this
expression, you can type anything you want on the line. To end the section, type
#endregion, followed by anything you want. Consider the following example:

using System;

class House
{
void Create()
{
}
}

#region These are classes used for Student Registration


class Car
{
C# 3.0 Practical Learning 106
void Build()
{
}
}

class Student
{
void Register()
{
}
}
#endregion We can just stop it here

class Program
{
static void Main()
{
}
}

You don't have to type anything on the right side of #endregion. After creating the
region, the Code Editor would display a - button to the left side of #region with a line
from there to the left of #endregion:

This then allows you to expand and collapse that section at will:

C# 3.0 Practical Learning 107


We mentioned that you didn't have to type anything on the right side of #endregion and
you could leave it empty. In our example, notice that there is a rectangle with gray lines
around the string that follows #region. This rectangle doesn't cover the string that
follows #endregion. This means that if you don't type anything on the right side of
#endregion, that section on the right side the #region line would not show.

C# 3.0 Practical Learning 108


6 - DATA READING AND
FORMATTING
 

Data Reading
 

Introduction

In previous lessons, we saw that the Console class allows using the Write() and the
WriteLine() methods to display things on the screen. While the Console.Write()
method is used to display something on the screen, the Console class provides the
Read() method to get a value from the user. To use it, the name of a variable can be
assigned to it. The syntax used is:
VariableName = Console.Read();

This simply means that, when the user types something and presses Enter, what the user
had typed would be given (the word is assigned) to the variable specified on the left side
of the assignment operator.

Read() doesn't always have to assign its value to a variable. For example, it can be used
on its own line, which simply means that the user is expected to type something but the
value typed by the user would not be used for any significant purpose. For example some
versions of C# (even including Microsoft's C# and Borland C#Builder) would display the
DOS window briefly and disappear. You can use the Read() function to wait for the user
to press any key in order to close the DOS window.

Besides Read(), the Console class also provides the ReadLine() method. Like the
WriteLine() member function, after performing its assignment, the ReadLine() method
sends the caret to the next line. Otherwise, it plays the same role as the Read() function.

Practical Learning: Introducing Data Reading

 Start Microsoft Visual C# and create a Console Application named


GeorgetownCleaningServices4

String Value Request 

In most assignments of your programs, you will not know the value of a string when
writing your application. For example, you may want the user to provide such a string. To
request a string (or any of the variables we will see in this lesson), you can call the

C# 3.0 Practical Learning 109


Console.Read() or the Console.ReadLine() function and assign it to the name of the
variable whose value you want to retrieve. Here is an example:

using System;

public class Exercise


{
public static void Main()
{
string FirstName;

Console.Write("Enter First Name: ");


FirstName = Console.ReadLine();
}
}

Practical Learning: Reading String Values

1. To request strings from the user, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class Program
{
static void Main(string[] args)
{
string CustomerName, HomePhone;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


// Request customer information from the user
Console.Write("Enter Customer Name: ");
CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
HomePhone = Console.ReadLine();

Console.WriteLine();
// Display the receipt
Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.Write("Customer: ");
Console.WriteLine(CustomerName);
Console.Write("Home Phone: ");
Console.WriteLine(HomePhone);
Console.WriteLine("====================================\n");
}
}
}

C# 3.0 Practical Learning 110


2. Execute the program. This would produce:
 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: James Watson
Enter Customer Phone: (410) 493-2005

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: James Watson
Home Phone: (410) 493-2005
====================================

3. Close the DOS window

Number Request

In C#, everything the user types is a string and the compiler would hardly analyze it
without your explicit asking it to do so. Therefore, if you want to get a number from the
user, first request a string. Here is an example:
using System;

public class Exercise


{
public static void Main()
{
int Number;
string strNumber;

strNumber = Console.ReadLine();
}
}

After getting the string, you must convert it to a number. To perform this conversion, each
data type of the .NET Framework provides a mechanism called Parse. To use Parse(),
type the data type, followed by a period, followed by Parse, and followed by parentheses.
In the parentheses of Parse, type the string that you requested from the user. Here is an
example:
using System;

public class Exercise


{
public static void Main()
{
int Number;
string strNumber;

strNumber = Console.ReadLine();
Number = int.Parse(strNumber);
}
}

An advanced but faster way to do this is to type Console.ReadLine() in the parentheses


of Parse. This has the same effect. Here is an example:

C# 3.0 Practical Learning 111


using System;

public class Exercise


{
public static int Main()
{
int Number;

Number = int.Parse(Console.ReadLine());

return 0;
}
}

Practical Learning: Reading Numeric Values

1. To retrieve various numbers from the user, change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class Program
{
static void Main(string[] args)
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOneDress = 4.55;
const double TaxRate = 0.0575; // 5.75%

// Customer personal infoirmation


string CustomerName, HomePhone;
// Unsigned numbers to represent cleaning items
uint NumberOfShirts, NumberOfPants, NumberOfDresses;
// Each of these sub totals will be used for cleaning items
double SubTotalShirts, SubTotalPants, SubTotalDresses;
// Values used to process an order
double TotalOrder, TaxAmount, SalesTotal;
double AmountTended, Difference;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


// Request customer information from the user
Console.Write("Enter Customer Name: ");
CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
HomePhone = Console.ReadLine();

// Request the quantity of each category of items


Console.Write("Number of Shirts: ");
string strShirts = Console.ReadLine();
NumberOfShirts = uint.Parse(strShirts);

Console.Write("Number of Pants: ");


C# 3.0 Practical Learning 112
string strPants = Console.ReadLine();
NumberOfPants = uint.Parse(strPants);

Console.Write("Number of Dresses: ");


string strDresses = Console.ReadLine();
NumberOfDresses = uint.Parse(strDresses);

// Perform the necessary calculations


SubTotalShirts = NumberOfShirts * PriceOneShirt;
SubTotalPants = NumberOfPants * PriceAPairOfPants;
SubTotalDresses = NumberOfDresses * PriceOneDress;
// Calculate the "temporary" total of the order
TotalOrder = SubTotalShirts +
SubTotalPants +
SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.Write("\nThe Total order is: ");
Console.WriteLine(SalesTotal);
// and request money for the order
Console.Write("Amount Tended? ");
AmountTended = double.Parse(Console.ReadLine());

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;
Console.WriteLine();

// Display the receipt


Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.Write("Customer: ");
Console.WriteLine(CustomerName);
Console.Write("Home Phone: ");
Console.WriteLine(HomePhone);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.Write("Shirts ");
Console.Write(NumberOfShirts);
Console.Write(" ");
Console.Write(PriceOneShirt);
Console.Write(" ");
Console.WriteLine(SubTotalShirts);
Console.Write("Pants ");
Console.Write(NumberOfPants);
Console.Write(" ");
Console.Write(PriceAPairOfPants);
Console.Write(" ");
Console.WriteLine(SubTotalPants);
Console.Write("Dresses ");
Console.Write(NumberOfDresses);
Console.Write(" ");
Console.Write(PriceOneDress);
C# 3.0 Practical Learning 113
Console.Write(" ");
Console.WriteLine(SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.Write("Total Order: ");
Console.WriteLine(TotalOrder);
Console.Write("Tax Rate: ");
Console.Write(TaxRate * 100);
Console.WriteLine('%');
Console.Write("Tax Amount: ");
Console.WriteLine(TaxAmount);
Console.Write("Net Price: ");
Console.WriteLine(SalesTotal);
Console.WriteLine("------------------------------------");
Console.Write("Amount Tended: ");
Console.WriteLine(AmountTended);
Console.Write("Difference: ");
Console.WriteLine(Difference);
Console.WriteLine("====================================");
}
}
}

2. Execute the program and test it. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Genevieve Alton
Enter Customer Phone: (202) 974-8244
Number of Shirts: 8
Number of Pants: 2
Number of Dresses: 3

The Total order is: 28.711125


Amount Tended? 30

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Genevieve Alton
Home Phone: (202) 974-8244
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 8 0.95 7.60
Pants 2 2.95 5.90
Dresses 3 4.55 13.65
------------------------------------
Total Order: 27.15
Tax Rate: 5.7500%
Tax Amount: 1.561125
Net Price: 28.711125
------------------------------------
Amount Tended: 30
Difference: 1.288875
====================================

3. Close the DOS window

Requesting Dates and Times

C# 3.0 Practical Learning 114


As done with the regular numbers, you can request a date value from the user. This is
also done by requesting a string from the user. Here is an example:
using System;

namespace ValueRequests
{
class Exercise
{
static void Main()
{
string strDateHired;

strDateHired = Console.ReadLine();
}
}
}

After the user has entered the string you can then convert it to a DateTime value. Just
like any value you request from the user, a date or time value that the user types must be
valid, otherwise, the program would produce an error. Because dates and times follow
some rules for their formats, you should strive to let the user know how you expect the
value to be entered.

By default, if you request only a date from the user and the user enters a valid date, the
compiler would add the midnight value to the date. If you request only the time from the
user and the user enters a valid time, the compiler would add the current date to the
value. Later on, we will learn how to isolate either only the date or only the time.

Practical Learning: Requesting Date and Time Values

1. To deal with new dates and times, change the program as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class OrderProcessing
{
static void Main()
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOneDress = 4.55;
const double TaxRate = 0.0575; // 5.75%

// Basic information about an order


string CustomerName, HomePhone;
DateTime OrderDate;
// Unsigned numbers to represent cleaning items
uint NumberOfShirts, NumberOfPants, NumberOfDresses;
// Each of these sub totals will be used for cleaning items

C# 3.0 Practical Learning 115


double SubTotalShirts, SubTotalPants, SubTotalDresses;
// Values used to process an order
double TotalOrder, TaxAmount, SalesTotal;
double AmountTended, Difference;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


// Request order information from the user
Console.Write("Enter Customer Name: ");
CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
HomePhone = Console.ReadLine();
Console.WriteLine("Enter the order date and " +
"time (mm/dd/yyyy hh:mm AM/PM)");
OrderDate = DateTime.Parse(Console.ReadLine());

// Request the quantity of each category of items


Console.Write("Number of Shirts: ");
string strShirts = Console.ReadLine();
NumberOfShirts = uint.Parse(strShirts);

Console.Write("Number of Pants: ");


string strPants = Console.ReadLine();
NumberOfPants = uint.Parse(strPants);

Console.Write("Number of Dresses: ");


string strDresses = Console.ReadLine();
NumberOfDresses = uint.Parse(strDresses);

// Perform the necessary calculations


SubTotalShirts = NumberOfShirts * PriceOneShirt;
SubTotalPants = NumberOfPants * PriceAPairOfPants;
SubTotalDresses = NumberOfDresses * PriceOneDress;
// Calculate the "temporary" total of the order
TotalOrder = SubTotalShirts +
SubTotalPants +
SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.Write("\nThe Total order is: ");
Console.WriteLine(SalesTotal);
// and request money for the order
Console.Write("Amount Tended? ");
AmountTended = double.Parse(Console.ReadLine());

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;
Console.WriteLine();

// Display the receipt


Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.Write("Customer: ");
Console.WriteLine(CustomerName);
C# 3.0 Practical Learning 116
Console.Write("Home Phone: ");
Console.WriteLine(HomePhone);
Console.Write("Date & Time: ");
Console.WriteLine(OrderDate);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.Write("Shirts ");
Console.Write(NumberOfShirts);
Console.Write(" ");
Console.Write(PriceOneShirt);
Console.Write(" ");
Console.WriteLine(SubTotalShirts);
Console.Write("Pants ");
Console.Write(NumberOfPants);
Console.Write(" ");
Console.Write(PriceAPairOfPants);
Console.Write(" ");
Console.WriteLine(SubTotalPants);
Console.Write("Dresses ");
Console.Write(NumberOfDresses);
Console.Write(" ");
Console.Write(PriceOneDress);
Console.Write(" ");
Console.WriteLine(SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.Write("Total Order: ");
Console.WriteLine(TotalOrder);
Console.Write("Tax Rate: ");
Console.Write(TaxRate * 100);
Console.WriteLine('%');
Console.Write("Tax Amount: ");
Console.WriteLine(TaxAmount);
Console.Write("Net Price: ");
Console.WriteLine(SalesTotal);
Console.WriteLine("------------------------------------");
Console.Write("Amount Tended: ");
Console.WriteLine(AmountTended);
Console.Write("Difference: ");
Console.WriteLine(Difference);
Console.WriteLine("====================================");
}
}
}

2. Execute the program and test it. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Alexander Pappas
Enter Customer Phone: (301) 397-9764
Enter the order date and time (mm/dd/yyyy hh:mm AM/PM)
06/22/98 08:26 AM
Number of Shirts: 2
Number of Pants: 6
Number of Dresses: 0

The Total order is: 20.727000


Amount Tended? 50

C# 3.0 Practical Learning 117


====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Alexander Pappas
Home Phone: (301) 397-9764
Date & Time: 6/22/1998 8:26:00 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 2 0.95 1.90
Pants 6 2.95 17.70
Dresses 0 4.55 0
------------------------------------
Total Order: 19.60
Tax Rate: 5.7500%
Tax Amount: 1.127000
Net Price: 20.727000
------------------------------------
Amount Tended: 50
Difference: 29.273000
====================================

3. Return to Notepad

Formatting Data Display


 

Introduction

Instead of using two Write() or a combination of Write() and WriteLine() to display


data, you can convert a value to a string and display it directly. To do this, you can
provide two strings to the Write() or WriteLine() and separate them with a comma:

1. The first part of the string provided to Write() or WriteLine() is the complete
string that would display to the user. This first string itself can be made of different
sections:

a. One section is a string in any way you want it to display

b. Another section is a number included between an opening curly bracket "{"


and a closing curly bracket "}". This combination of "{" and "}" is referred to
as a placeholder

You can put the placeholder anywhere inside of the string. The first
placeholder must have number 0. The second must have number 1, etc.
With this technique, you can create the string anyway you like and use the
placeholders anywhere inside of the string

2. The second part of the string provided to Write() or WriteLine() is the value
that you want to display. It can be one value if you used only one placeholder with
0 in the first string. If you used different placeholders, you can then provide a
different value for each one of them in this second part, separating the values with
a comma

Here are examples:


C# 3.0 Practical Learning 118
using System;

public class Exercise


{
public static void Main()
{
var FullName = "Anselme Bogos";
var Age = 15;
var HSalary = 22.74;

Console.WriteLine("Full Name: {0}", FullName);


Console.WriteLine("Age: {0}", Age);
Console.WriteLine("Distance: {0}", HSalary);

Console.WriteLine();
}
}

This would produce:


Full Name: Anselme Bogos
Age: 15
Distance: 22.74

As mentioned already, the numeric value typed in the curly brackets of the first part is an
ordered number. If you want to display more than one value, provide each incremental
value in its curly brackets. The syntax used is:
Write("To Display {0} {1} {2} {n}", First, Second, Third, nth);

You can use the sections between a closing curly bracket and an opening curly bracket to
create a meaningful sentence.

Practical Learning: Displaying Data With Placeholders

1. To use curly brackets to display data, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class OrderProcessing
{
static void Main()
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOneDress = 4.55;
const double TaxRate = 0.0575; // 5.75%

// Basic information about an order


string CustomerName, HomePhone;
DateTime OrderDate;
// Unsigned numbers to represent cleaning items
C# 3.0 Practical Learning 119
uint NumberOfShirts, NumberOfPants, NumberOfDresses;
// Each of these sub totals will be used for cleaning items
double SubTotalShirts, SubTotalPants, SubTotalDresses;
// Values used to process an order
double TotalOrder, TaxAmount, SalesTotal;
double AmountTended, Difference;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


// Request order information from the user
Console.Write("Enter Customer Name: ");
CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
HomePhone = Console.ReadLine();
Console.WriteLine("Enter the order date and " +
"time (mm/dd/yyyy hh:mm AM/PM)");
OrderDate = DateTime.Parse(Console.ReadLine());

// Request the quantity of each category of items


Console.Write("Number of Shirts: ");
NumberOfShirts = uint.Parse(Console.ReadLine());

Console.Write("Number of Pants: ");


NumberOfPants = uint.Parse(Console.ReadLine());

Console.Write("Number of Dresses: ");


NumberOfDresses = uint.Parse(Console.ReadLine());

// Perform the necessary calculations


SubTotalShirts = NumberOfShirts * PriceOneShirt;
SubTotalPants = NumberOfPants * PriceAPairOfPants;
SubTotalDresses = NumberOfDresses * PriceOneDress;
// Calculate the "temporary" total of the order
TotalOrder = SubTotalShirts +
SubTotalPants +
SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.Write("\nThe Total order is: ");
Console.WriteLine(SalesTotal);
// and request money for the order
Console.Write("Amount Tended? ");
AmountTended = double.Parse(Console.ReadLine());

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;
Console.WriteLine();

// Display the receipt


Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}", CustomerName);
Console.WriteLine("Home Phone: {0}", HomePhone);
Console.WriteLine("Date & Time: {0}", OrderDate);
C# 3.0 Practical Learning 120
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0} {1} {2}",
NumberOfShirts,
PriceOneShirt, SubTotalShirts);
Console.WriteLine("Pants {0} {1} {2}",
NumberOfPants,
PriceAPairOfPants, SubTotalPants);
Console.WriteLine("Dresses {0} {1} {2}",
NumberOfDresses,
PriceOneDress, SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0}", TotalOrder);
Console.WriteLine("Tax Rate: {0}%", TaxRate * 100);
Console.WriteLine("Tax Amount: {0}", TaxAmount);
Console.WriteLine("Net Price: {0}", SalesTotal);
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0}", AmountTended);
Console.WriteLine("Difference: {0}", Difference);
Console.WriteLine("====================================");
}
}
}

2. Execute the program and test it

3. Close the DOS window

Conversion To String

We mentioned earlier that everything the user types using the keyboard is primarily a
string and it's your job to convert it to the appropriate type. In reverse, if you have a
value that is not a string, you can easily convert it to a string. To support this, each .NET
Framework data type provides a mechanism called ToString. Normally, in C#, as we
mentioned with boxing, and as we have done so far, this conversion is automatically or
transparently done by the compiler. In some cases, you will need to perform the
conversion yourself.

To convert a value of a primitive data type to a string, type the name of the variable,
followed by a period, followed by ToString(). Here is an example:
using System;

public class Exercise


{
public static void Main()
{
var FullName = "Anselme Bogos";
var Age = 15;
var HSalary = 22.74;

Console.WriteLine("Full Name: {0}", FullName);


Console.WriteLine("Age: {0}", Age.ToString());
Console.WriteLine("Distance: {0}", HSalary.ToString());

Console.WriteLine();
}
C# 3.0 Practical Learning 121
}

In some cases, you will type something in the parentheses of ToString().

Practical Learning: Converting to String

1. To convert some values to string, change the program as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class OrderProcessing
{
static void Main()
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOneDress = 4.55;
const double TaxRate = 0.0575; // 5.75%

. . . No Change

Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0} {1} {2}",
NumberOfShirts.ToString(),
PriceOneShirt,
SubTotalShirts.ToString());
Console.WriteLine("Pants {0} {1} {2}",
NumberOfPants, PriceAPairOfPants,
SubTotalPants);
Console.WriteLine("Dresses {0} {1} {2}",
NumberOfDresses, PriceOneDress,
SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0}", TotalOrder);
Console.WriteLine("Tax Rate: {0}%", TaxRate * 100);
Console.WriteLine("Tax Amount: {0}",
TaxAmount.ToString());
Console.WriteLine("Net Price: {0}", SalesTotal);
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0}", AmountTended);
Console.WriteLine("Difference: {0}", Difference);
Console.WriteLine("====================================");
}
}
}

2. Execute the program and test it

3. Close the DOS window

Number Formatting

C# 3.0 Practical Learning 122


To properly display data in a friendly and most familiar way, you can format it. Formatting
tells the compiler what kind of data you are using and how you want the compiler to
display it to the user. As it happens, you can display a natural number in a common value
or, depending on the circumstance, you may prefer to show it as a hexadecimal value.
When it comes to double-precision numbers, you may want to display a distance with
three values on the right side of the decimal separator and in some cases, you may want
to display a salary with only 2 decimal places.

The System namespace provides a specific letter that you can use in the Write() or
WriteLine()'s placeholder for each category of data to display. To format a value, in the
placeholder of the variable or value, after the number, type a colon and one of the
appropriate letters from the following table. If you are using ToString(), then, in the
parentheses of ToString(), you can include a specific letter or combination inside of
double-quotes. The letters and their meanings are:

  Character Used For

  c C Currency values

  d D Decimal numbers

  e E Scientific numeric display such as 1.45e5

  f F Fixed decimal numbers

General and most common type of


  g G
numbers

  n N Natural numbers

  r R Roundtrip formatting

  x X Hexadecimal formatting

  p P Percentages

Here are examples:


using System;

public class Exercise


{
public static void Main()
{
var Distance = 248.38782;
var Age = 15;
C# 3.0 Practical Learning 123
var NewColor = 3478;
var HSalary = 22.74;
var HoursWorked = 35.5018473;
var WeeklySalary = HSalary * HoursWorked;

Console.WriteLine("Distance: {0}", Distance.ToString("E"));


Console.WriteLine("Age: {0}", Age.ToString());

Console.WriteLine("Color: {0}", NewColor.ToString("X"));

Console.WriteLine("Weekly Salary: {0} for {1} hours",


WeeklySalary.ToString("c"),
HoursWorked.ToString("F"));

Console.WriteLine();
}
}

This would produce:


Distance: 2.483878E+002
Age: 15
Color: D96
Weekly Salary: $807.31 for 35.50 hours

As you may have noticed, if you leave the parentheses of ToString() empty, the
compiler would use a default formatting to display the value.

As opposed to calling ToString(), you can use the above letters in the curly brackets of
the first part of Write() or WriteLine(). In this case, after the number in the curly
brackets, type the colon operator followed by the letter.

Practical Learning: Formatting Data Display

1. To format data display, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class OrderProcessing
{
static void Main()
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOneDress = 4.55;
const double TaxRate = 0.0575; // 5.75%

// Basic information about an order


string CustomerName, HomePhone;
DateTime OrderDate;
// Unsigned numbers to represent cleaning items

C# 3.0 Practical Learning 124


uint NumberOfShirts, NumberOfPants, NumberOfDresses;
// Each of these sub totals will be used for cleaning items
double SubTotalShirts, SubTotalPants, SubTotalDresses;
// Values used to process an order
double TotalOrder, TaxAmount, SalesTotal;
double AmountTended, Difference;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


// Request order information from the user
Console.Write("Enter Customer Name: ");
CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
HomePhone = Console.ReadLine();
Console.WriteLine("Enter the order date and " +
"time (mm/dd/yyyy hh:mm AM/PM)");
OrderDate = DateTime.Parse(Console.ReadLine());

// Request the quantity of each category of items


Console.Write("Number of Shirts: ");
NumberOfShirts = uint.Parse(Console.ReadLine());

Console.Write("Number of Pants: ");


NumberOfPants = uint.Parse(Console.ReadLine());

Console.Write("Number of Dresses: ");


NumberOfDresses = uint.Parse(Console.ReadLine());

// Perform the necessary calculations


SubTotalShirts = NumberOfShirts * PriceOneShirt;
SubTotalPants = NumberOfPants * PriceAPairOfPants;
SubTotalDresses = NumberOfDresses * PriceOneDress;
// Calculate the "temporary" total of the order
TotalOrder = SubTotalShirts +
SubTotalPants + SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.Write("\nThe Total order is: ");
Console.WriteLine(SalesTotal);
// and request money for the order
Console.Write("Amount Tended? ");
AmountTended = double.Parse(Console.ReadLine());

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;
Console.WriteLine();

// Display the receipt


Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}", CustomerName);
Console.WriteLine("Home Phone: {0}", HomePhone);
Console.WriteLine("Date & Time: {0}", OrderDate);
Console.WriteLine("------------------------------------");
C# 3.0 Practical Learning 125
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0} {1:C} {2}",
NumberOfShirts.ToString(), PriceOneShirt,
SubTotalShirts.ToString("C"));
Console.WriteLine("Pants {0} {1:C} {2:C}",
NumberOfPants, PriceAPairOfPants,
SubTotalPants);
Console.WriteLine("Dresses {0} {1:C} {2:C}",
NumberOfDresses, PriceOneDress,
SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0:C}", TotalOrder);
Console.WriteLine("Tax Rate: {0:P}", TaxRate);
Console.WriteLine("Tax Amount: {0}",
TaxAmount.ToString("C"));
Console.WriteLine("Net Price: {0:F}", SalesTotal);
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0:C}", AmountTended);
Console.WriteLine("Difference: {0:C}", Difference);
Console.WriteLine("====================================");
}
}
}

2. Execute the application. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Gretchen McCormack
Enter Customer Phone: (410) 739-2884
Enter the order date and time (mm/dd/yyyy hh:mm AM/PM)
04/09/2001 10:25 AM
Number of Shirts: 5
Number of Pants: 12
Number of Dresses: 8

The Total order is: 80.951625


Amount Tended? 100

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Gretchen McCormack
Home Phone: (410) 739-2884
Date & Time: 4/9/2001 10:25:00 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 5 $0.95 $4.75
Pants 12 $2.95 $35.40
Dresses 8 $4.55 $36.40
------------------------------------
Total Order: $76.55
Tax Rate: 5.75 %
Tax Amount: $4.40
Net Price: 80.95
------------------------------------
Amount Tended: $100.00
Difference: $19.05
C# 3.0 Practical Learning 126
====================================

3. Close the DOS window

Line Formatting

In the above programs, to display a line of text, we easily used Write() or WriteLine().
To position text of different lengths one above the other, we had to "corrupt" a string by
including extra-empty spaces. Such a technique is uncertain and less professional.
Fortunately, you can highly format how a string or a line of text should display. The .NET
Framework provides mechanisms to control the amount of space used to display a string
of text and how to align that string on its line.

To specify the amount of space used to display a string, you can use its placeholder in
Write() or WriteLine(). To do this, in the placeholder, type the 0 or the incrementing
number of the placer and its formatting character if necessary and if any. Then, type a
comma followed by the number of characters equivalent to the desired width. Here are
examples:
using System;

public class Exercise


{
public static void Main()
{
var FullName = "Anselme Bogos";
var Age = 15;
var HSalary = 22.74;

Console.WriteLine("Full Name: {0,20}", FullName);


Console.WriteLine("Age:{0,14}", Age.ToString());
Console.WriteLine("Distance: {0:C,8}", HSalary.ToString());

Console.WriteLine();
}
}

This would produce:


Full Name: Anselme Bogos
Age: 15
Distance: 22.74

The sign you provide for the width is very important. If it is positive, the line of text is
aligned to the right. This should be your preferred alignment for numeric values. If the
number is negative, then the text is aligned to the left.

Data and Time Formatting

As mentioned earlier, when the user enters a date value for a DateTime variable, the
compiler adds a time part to the value. Fortunately, if you want to consider only the date
or only the time part, you can specify this to the compiler. To support this, the DateTime
data type provides a series of letters you can use to format how its value should be
displayed to the user. The character is entered in the placeholder of the DateTime
variable after the 0 or the incremental numeric value.
C# 3.0 Practical Learning 127
Practical Learning: Controlling Date/Time Formatting

1. To control formatting of date and time, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices4
{
class OrderProcessing
{
static void Main()
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOneDress = 4.55;
const double TaxRate = 0.0575; // 5.75%

// Basic information about an order


string CustomerName, HomePhone;
DateTime OrderDate, OrderTime;
// Unsigned numbers to represent cleaning items
uint NumberOfShirts, NumberOfPants, NumberOfDresses;
// Each of these sub totals will be used for cleaning items
double SubTotalShirts, SubTotalPants, SubTotalDresses;
// Values used to process an order
double TotalOrder, TaxAmount, SalesTotal;
double AmountTended, Difference;

Console.WriteLine("-/- Georgetown Cleaning Services -/-");


// Request order information from the user
Console.Write("Enter Customer Name: ");
CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
HomePhone = Console.ReadLine();
Console.Write("Enter the order date(mm/dd/yyyy): ");
OrderDate = DateTime.Parse(Console.ReadLine());
Console.Write("Enter the order time(hh:mm AM/PM): ");
OrderTime = DateTime.Parse(Console.ReadLine());

// Request the quantity of each category of items


Console.Write("Number of Shirts: ");
NumberOfShirts = uint.Parse(Console.ReadLine());

Console.Write("Number of Pants: ");


NumberOfPants = uint.Parse(Console.ReadLine());

Console.Write("Number of Dresses: ");


NumberOfDresses = uint.Parse(Console.ReadLine());

// Perform the necessary calculations


SubTotalShirts = NumberOfShirts * PriceOneShirt;
SubTotalPants = NumberOfPants * PriceAPairOfPants;
SubTotalDresses = NumberOfDresses * PriceOneDress;
// Calculate the "temporary" total of the order
C# 3.0 Practical Learning 128
TotalOrder = SubTotalShirts +
SubTotalPants +
SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.WriteLine("\nThe Total order is: {0:C}",
SalesTotal);
// and request money for the order
Console.Write("Amount Tended? ");
AmountTended = double.Parse(Console.ReadLine());

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;
Console.WriteLine();

// Display the receipt


Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}", CustomerName);
Console.WriteLine("Home Phone: {0}", HomePhone);
Console.WriteLine("Order Date: {0:D}", OrderDate);
Console.WriteLine("Order Time: {0:t}", OrderTime);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0} {1} {2}",
NumberOfShirts.ToString(),
PriceOneShirt.ToString("C"),
SubTotalShirts.ToString("C"));
Console.WriteLine("Pants {0} {1} {2}",
NumberOfPants.ToString(),
PriceAPairOfPants.ToString("C"),
SubTotalPants.ToString("C"));
Console.WriteLine("Dresses {0} {1} {2}",
NumberOfDresses.ToString(),
PriceOneDress.ToString("C"),
SubTotalDresses.ToString("C"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0}",
TotalOrder.ToString("C"));
Console.WriteLine("Tax Rate: {0}",
TaxRate.ToString("P"));
Console.WriteLine("Tax Amount: {0}",
TaxAmount.ToString("C"));
Console.WriteLine("Net Price: {0}",
SalesTotal.ToString("C"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0}",
AmountTended.ToString("C"));
Console.WriteLine("Difference: {0}",
Difference.ToString("C"));
Console.WriteLine("====================================");
}
C# 3.0 Practical Learning 129
}
}

2. Execute the program. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Antoinette Calhoun
Enter Customer Phone: (703) 797-1135
Enter the order date(mm/dd/yyyy): 04/12/2002
Enter the order time(hh:mm AM/PM): 2:12 PM
Number of Shirts: 5
Number of Pants: 2
Number of Dresses: 1

The Total order is: $16.07


Amount Tended? 20

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Antoinette Calhoun
Home Phone: (703) 797-1135
Order Date: Friday, April 12, 2002
Order Time: 2:12 PM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 5 $0.95 $4.75
Pants 2 $2.95 $5.90
Dresses 1 $4.55 $4.55
------------------------------------
Total Order: $15.20
Tax Rate: 5.75 %
Tax Amount: $0.87
Net Price: $16.07
------------------------------------
Amount Tended: $20.00
Difference: $3.93
====================================

3. Close the DOS window

C# 3.0 Practical Learning 130


DETAILS ON THE METHODS
OF A CLASS
 

Methods and Local Variables


 

Introduction

In the body of a method, you can declare one or more variables that would be used only
by the method. A variable declared in the body of a method is referred to as a local
variable. The variable cannot be accessed outside of the method it belongs to. After
declaring a local variable, it is made available to the method and you can use it as you see
fit, for example, you can assign it a value prior to using it.

  

Practical Learning: Using a Method's Local Variables

1. Start Microsoft Visual C# and create a Console Application named Geometry1

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to Cylinder and click Add

4. To declare and use local variables of a method, change the file as follows:
 

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry1
{
public class Cylinder
{
public void Process()
{
double Radius, Height;
double BaseArea, LateralArea, TotalArea;
double Volume;

Console.WriteLine("Enter the dimensions of the cylinder");


Console.Write("Radius: ");

C# 3.0 Practical Learning 131


Radius = double.Parse(Console.ReadLine());
Console.Write("Height: ");
Height = double.Parse(Console.ReadLine());

BaseArea = Radius * Radius * Math.PI;

LateralArea = 2 * Math.PI * Radius * Height;


TotalArea = 2 * Math.PI * Radius * (Height + Radius);
Volume = Math.PI * Radius * Radius * Height;

Console.WriteLine("\nCylinder Characteristics");
Console.WriteLine("Radius: {0}", Radius);
Console.WriteLine("Height: {0}", Height);
Console.WriteLine("Base: {0:F}", BaseArea);
Console.WriteLine("Lateral: {0:F}", LateralArea);
Console.WriteLine("Total: {0:F}", TotalArea);
Console.WriteLine("Volume: {0:F}", Volume);
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry1
{
public class Program
{
static void Main()
{
Cylinder cyl = new Cylinder();

cyl.Process();
Console.WriteLine();
}
}
}

6. Execute the application to test it. Here is an example:


 
Enter the dimensions of the cylinder
Radius: 38.64
Height: 22.48

Cylinder Characteristics
Radius: 38.64
Height: 22.48
Base: 4690.55
Lateral: 5457.75
Total: 14838.85
Volume: 105443.65

7. Close the DOS window


C# 3.0 Practical Learning 132
A Method that Returns a Value 

If a method has carried an assignment and must make its result available to other
methods or other classes, the method must return a value and cannot be void. To
declare a method that returns a value, provide its return type to the left of its name. Here
is an example:
using System;

class Exercise
{

static double Operation()

{
}

static void Main()


{
}
}

After a method has performed its assignment, it must clearly demonstrate that it is
returning a value. To do this, you use the return keyword followed by the value that the
method is returning. The value returned must be of the same type specified as the return
type of the method. Here is an example:
using System;

class Exercise
{
static double Operation()
{
return 24.55;
}

static void Main()


{
}
}

A method can also return an expression, provided the expression produces a value that is
conform to the return type. Here is an example:
using System;

class Exercise
{
static double Operation()
{
return 24.55 * 4.16;
}

static void Main()


{
}
}

C# 3.0 Practical Learning 133


When a method returns a value, the compiler considers such a method as if it were a
regular value. This means that you can use the Console.Write() or the
Console.WriteLine() method to display its value. To do this, simply type the name of
the method and its parentheses in the Console.Write() of the Console.WriteLine()
methods' parentheses. Here is an example:
using System;

class Exercise
{
static double Operation()
{
return 24.55;
}

static void Main()


{
Console.WriteLine(Operation());
}
}

In the same way, a method that returns a value can be assigned to a variable of the same
type.

Practical Learning: Returning a Value From a Method 

1. Access the Cylinder.cs file

2. To create methods that return values, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry1
{
class Cylinder
{
public double GetRadius()
{
double rad;

Console.Write("Radius: ");
rad = double.Parse(Console.ReadLine());

return rad;
}

public double GetHeight()


{
double h;

Console.Write("Height: ");
h = double.Parse(Console.ReadLine());

return h;
C# 3.0 Practical Learning 134
}

public void Process()


{
double Radius, Height;
double BaseArea, LateralArea, TotalArea;
double Volume;

Console.WriteLine("Enter the dimensions of the cylinder");


Radius = GetRadius();
Height = GetHeight();

BaseArea = Radius * Radius * Math.PI;


LateralArea = 2 * Math.PI * Radius * Height;
TotalArea = 2 * Math.PI * Radius * (Height + Radius);
Volume = Math.PI * Radius * Radius * Height;

Console.WriteLine("\nCylinder Characteristics");
Console.WriteLine("Radius: {0}", Radius);
Console.WriteLine("Height: {0}", Height);
Console.WriteLine("Base: {0:F}", BaseArea);
Console.WriteLine("Lateral: {0:F}", LateralArea);
Console.WriteLine("Total: {0:F}", TotalArea);
Console.WriteLine("Volume: {0:F}", Volume);
}
}
}

3. Execute the application. Here is an example:


 
Enter the dimensions of the cylinder
Radius: 52.08
Height: 36.44

Cylinder Characteristics
Radius: 52.08
Height: 36.44
Base: 8521.02
Lateral: 11924.20
Total: 28966.25
Volume: 310506.14

4. Close the DOS window

The Main Method of an Application

So far, we have used the Main() method as it is defined by default when you create an
application using using New Project dialog box. This default implementation of the Main()
method is of type void. Another way to implement the Main() method is to make it
return an integer. The rule is the same as for any method of type int. The Main() method
can return any type of integer as long as it is a valid integer. Here is an example:
using System;

class Exercise
{
static char HaveCharacter()
C# 3.0 Practical Learning 135
{
return 'G';
}

static int Main()


{
Console.Write("Character: ");
Console.WriteLine(HaveCharacter());

return 244006;
}
}

This would produce:


Character: G
Press any key to continue . . .

Methods' Arguments
 

Introduction

A method performs an assignment that completes the operations of a class. The methods
we used in the previous sections relied on local variables to exchange information with
other sections of the program. Sometimes, a method would need one or more values in
order to carry its assignment. The particularity of such a value or such values is that
another method that calls this one must supply the needed value(s). When a method
needs a value to complete its assignment, such a value is called an argument.

Like a variable, an argument is represented by its type of value. For example, one method
may need a character while another would need a string. Yet another method may require
a decimal number. This means that the method or class that calls a method is responsible
for supplying the right value, even though a method may have an internal mechanism of
checking the validity of such a value.

The value supplied to a method is typed in the parentheses of the method and it's called
an argument. In order to declare a method that takes an argument, you must specify its
name and the argument between its parentheses. Because a method must specify the
type of value it would need, the argument is represented by its data type and a name.

Suppose you want to define a method that displays the side length of a square. Since you
would have to supply the length, you can define such a method as follows:
using System;

public class Exercise


{
static void DisplaySide(double Length)
{
}

static int Main()


{
return 0;
}

C# 3.0 Practical Learning 136


}

In the body of the method, you may or may not use the value of the argument.
Otherwise, you can manipulate the supplied value as you see fit. In this example, you can
display the value of the argument as follows:
using System;

public class Exercise


{
static void DisplaySide(double Length)
{
Console.Write("Length: ");
Console.WriteLine(Length);
}

static int Main()


{
return 0;
}
}

When calling a method that takes an argument, you must supply a value for the
argument; otherwise you would receive an error. Also, you should/must supply the right
value; otherwise, the method may not work as expected and it may produce an unreliable
result. Here is an example:
using System;

public class Exercise


{
static void DisplaySide(double Length)
{
Console.Write("Length: ");
Console.WriteLine(Length);
}

static int Main()


{
DisplaySide(35.55);

return 0;
}
}

As mentioned already, a method that takes an argument can also declare its own local
variable(s). A method can take more than one argument. When defining such a method,
provide each argument with its data type and a name. The arguments are separated by a
comma.

Practical Learning: Passing Arguments

1. Access the Cylinder.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
C# 3.0 Practical Learning 137
using System.Text;

namespace Geometry1
{
public class Cylinder
{
public double GetRadius()
{
double rad;

Console.Write("Radius: ");
rad = double.Parse(Console.ReadLine());

return rad;
}

public double GetHeight()


{
double h;

Console.Write("Height: ");
h = double.Parse(Console.ReadLine());

return h;
}

public double CalculateBaseArea(double rad)


{
return rad * rad * Math.PI;
}

public double CalculateLateralArea(double rad, double hgt)


{
return 2 * Math.PI * rad * hgt;
}

public double CalculateTotalArea(double rad, double hgt)


{
return 2 * Math.PI * rad * (hgt + rad);
}

public double CalculateVolume(double rad, double hgt)


{
return Math.PI * rad * rad * hgt;
}

public void Process()


{
double Radius;
double Height;
double BaseArea;
double LateralArea;
double TotalArea;
double Volume;

Console.WriteLine("Enter the dimensions of the cylinder");


Radius = GetRadius();
Height = GetHeight();

BaseArea = CalculateBaseArea(Radius);
C# 3.0 Practical Learning 138
LateralArea = CalculateLateralArea(Radius, Height);
TotalArea = CalculateTotalArea(Radius, Height);
Volume = CalculateVolume(Radius, Height);

Console.WriteLine("\nCylinder Characteristics");
Console.WriteLine("Radius: {0}", Radius);
Console.WriteLine("Height: {0}", Height);
Console.WriteLine("Base: {0:F}", BaseArea);
Console.WriteLine("Lateral: {0:F}", LateralArea);
Console.WriteLine("Total: {0:F}", TotalArea);
Console.WriteLine("Volume: {0:F}", Volume);
}
}
}

2. Execute the program:


 
Enter the dimensions of the cylinder
Radius: 35.96
Height: 30.28

Cylinder Characteristics
Radius: 35.96
Height: 30.28
Base: 4062.46
Lateral: 6841.56
Total: 14966.49
Volume: 123011.33

3. Close the DOS window

Techniques of Passing Arguments


 

Passing an Argument by Value

When calling a methods that takes one or more arguments, we made sure we provided
the necessary value. This is because an argument is always required and the calling
method must provide a valid value when calling such a method.

Passing an Argument by Reference

Consider the following program:


using System;

public class Payroll


{
static void Earnings(double ThisWeek, double Salary)
{
ThisWeek = 42.50;

Console.WriteLine("\nIn the Earnings() function,");


Console.Write("Weekly Hours = ");

C# 3.0 Practical Learning 139


Console.WriteLine(ThisWeek);
Console.Write("Salary = ");
Console.WriteLine(Salary);
Console.Write("Weekly Salary: = ");
Console.WriteLine(ThisWeek * Salary);
}

static int Main()


{
double Hours, Rate;

Rate = 15.58;
Hours = 26.00;

Console.WriteLine("In the Main() method,");


Console.Write("\nWeekly Hours = ");
Console.Write(Hours);
Console.Write("\nSalary = ");
Console.WriteLine(Rate);
Console.Write("Weekly Salary = ");
Console.WriteLine(Hours * Rate);

Console.WriteLine("\nCalling the Earnings() method");

Earnings(Hours, Rate);

Console.Write("\nAfter calling the Earnings() method, ");


Console.WriteLine("\nin the Main() function,");
Console.Write("\nWeekly Hours = ");
Console.Write(Hours);
Console.Write("\nSalary = ");
Console.WriteLine(Rate);
Console.Write("Weekly Salary = ");
Console.WriteLine(Hours * Rate);

Console.Write("\n");
return 0;
}
}

This would produce:


In the Main() method,

Weekly Hours = 26
Salary = 15.58
Weekly Salary = 405.08

Calling the Earnings() method

In the Earnings() function,


Weekly Hours = 42.5
Salary = 15.58
Weekly Salary: = 662.15

After calling the Earnings() method,


in the Main() function,

Weekly Hours = 26
Salary = 15.58
C# 3.0 Practical Learning 140
Weekly Salary = 405.08

Press any key to continue

Notice that the weekly hours and salary values are the same before and after calling the
Earnings() method. 

When you declare a variable in a program, the compiler reserves an amount of space for
that variable. If you need to use that variable somewhere in your program, you call it and
make use of its value. There are two major issues related to a variable: its value and its
location in the memory. The location of a variable in memory is referred to as its address.

If you supply the argument using its name, the compiler only makes a copy of the
argument’s value and gives it to the calling method. Although the calling method receives
the argument’s value and can use it in any way, it cannot (permanently) alter it. C# allows
a calling method to modify the value of a passed argument if you find it necessary. If you
want the calling method to modify the value of a supplied argument and return the
modified value, you should pass the argument using its reference.

To pass an argument as a reference, when defining and when calling the method, precede
the argument's data type with the ref keyword. You can pass 0, one, or more arguments
as reference in the program or pass all arguments as reference. The decision as to which
argument(s) should be passed by value or by reference is based on whether or not you
want the called method to modify the argument and permanently change its value.

Another option consists of passing an argument using the out keyword. Here is an
example:
using System;

class Exercise
{
static void Initializer(out double n)
{
n = 128.44;
}

public static int Main()


{
double Number = 15.25;

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


return 0;
}
}

If you pass an argument with out, any modification made on the argument would be kept
when the method ends. When calling a method that takes an out argument, precede the
argument with the out keyword. Here is an example:
using System;

class Exercise
{
static void Initializer(out double n)
{
n = 128.44;

C# 3.0 Practical Learning 141


}

public static int Main()


{
double Number = 15.25;

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


Initializer(out Number);
Console.WriteLine("Number = {0}", Number);
return 0;
}
}

This would produce:


Number = 15.25
Number = 128.44

Practical Learning: Passing Arguments By Reference

1. To pass arguments by reference, change the Cylinder.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry1
{
class Cylinder
{
public void GetRadius(ref double rad)
{
Console.Write("Radius: ");
rad = double.Parse(Console.ReadLine());
}

public void GetHeight(out double h)


{
Console.Write("Height: ");
h = double.Parse(Console.ReadLine());
}

public double CalculateBaseArea(double rad)


{
return rad * rad * Math.PI;
}

public double CalculateLateralArea(double rad, double hgt)


{
return 2 * Math.PI * rad * hgt;
}

public double CalculateTotalArea(double rad, double hgt)


{
return 2 * Math.PI * rad * (hgt + rad);
}

C# 3.0 Practical Learning 142


public double CalculateVolume(double rad, double hgt)
{
return Math.PI * rad * rad * hgt;
}

public void Process()


{
double Radius = 0.00;
double Height = 0.00;
double BaseArea;
double LateralArea;
double TotalArea;
double Volume;

Console.WriteLine("Enter the dimensions of the cylinder");


GetRadius(ref Radius);
GetHeight(out Height);

BaseArea = CalculateBaseArea(Radius);
LateralArea = CalculateLateralArea(Radius, Height);
TotalArea = CalculateTotalArea(Radius, Height);
Volume = CalculateVolume(Radius, Height);

Console.WriteLine("\nCylinder Characteristics");
Console.WriteLine("Radius: {0}", Radius);
Console.WriteLine("Height: {0}", Height);
Console.WriteLine("Base: {0:F}", BaseArea);
Console.WriteLine("Lateral: {0:F}", LateralArea);
Console.WriteLine("Total: {0:F}", TotalArea);
Console.WriteLine("Volume: {0:F}", Volume);
}
}
}

2. Execute the application to test it. Here is an example:


 
Enter the dimensions of the cylinder
Radius: 24.55
Height: 20.85

Cylinder Characteristics
Radius: 24.55
Height: 20.85
Base: 1893.45
Lateral: 3216.16
Total: 7003.05
Volume: 39478.34

3. Close the DOS window

Method Overloading

A typical program involves a great deal of names that represent variables and methods of
various kinds. The compiler does not allow two variables to have the same name in the
same method. Although two methods should have unique names in the same program, a
class can have different methods with the same name if you follow some rules. The ability
to have various methods with the same name in the same program is referred to as
C# 3.0 Practical Learning 143
method overloading. To perform overloading, the methods must have different numbers
or different type(s) of arguments.

The moment of inertia is the ability of a beam to resist bending. It is calculated with
regard to the cross section of the beam. Because it depends on the type of section of the
beam, its calculation also depends on the type of section of the beam. In this exercise, we
will review different formulas used to calculate the moment of inertia. Since this exercise
is for demonstration purposes, you do not need to be a Science Engineering major to
understand it.

Practical Learning: Overloading a Method

1. Create a new Console Application named MomentOfInertia1


 

2. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Exercise


{
// Rectangle
static double MomentOfInertia(double b, double h)
{
return b * h * h * h / 3;
}

static int Main()


{
double Base, Height;

Console.WriteLine("Enter the dimensions of the Rectangle");


Console.Write("Base: ");
Base = double.Parse(Console.ReadLine());
Console.Write("Height: ");
Height = double.Parse(Console.ReadLine());

Console.WriteLine("\nMoment of inertia with " +


"regard to the X axis: ");

C# 3.0 Practical Learning 144


Console.WriteLine("I = {0}mm",
MomentOfInertia(Base, Height));

Console.WriteLine();
return 0;
}
}

3. Execute the application. Here is an example of running the program:


 
Enter the dimensions of the Rectangle
Base: 2.44
Height: 3.58

Moment of inertia with regard to the X axis:


I = 37.3179390933333mm

4. Close the DOS window

5. A circle, and thus a semi-circle, requires only a radius. Since the other version of
the MomentOfInertia() function requires two arguments, we can overload it by
providing only one argument, the radius.
To overload the above MomentOfInertia() method, type the following in the file:
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Exercise


{
// Rectangle
static double MomentOfInertia(double b, double h)
{
return b * h * h * h / 3;
}

// Semi-Circle
static double MomentOfInertia(double R)
{
const double PI = 3.14159;

return R * R * R * R * PI/ 8;
}

static int Main()


{
double Base, Height;
double Radius;

C# 3.0 Practical Learning 145


Console.WriteLine("Enter the dimensions of the Rectangle");
Console.Write("Base: ");
Base = double.Parse(Console.ReadLine());
Console.Write("Height: ");
Height = double.Parse(Console.ReadLine());

Console.WriteLine("\nMoment of inertia with regard to the X axis:


");
Console.WriteLine("I = {0}mm", MomentOfInertia(Base, Height));

Console.Write("\nEnter the radius: ");


Radius = double.Parse(Console.ReadLine());

Console.WriteLine("Moment of inertia of a semi-circle " +


"with regard to the X axis: ");
Console.WriteLine("I = {0}mm", MomentOfInertia(Radius));

Console.WriteLine();
return 0;
}
}

6. Execute the program. Here is an example:


 
Enter the dimensions of the Rectangle
Base: 4.25
Height: 2.55

Moment of inertia with regard to the X axis:


I = 23.49028125mm

Enter the radius: 5.35


Moment of inertia of a semi-circle with regard to the X axis:
I = 321.717471644992mm

7. Close the DOS window

8. Here are the formulas considered for a triangle:

9. As you can see, the rectangle and the triangle are using the same dimension types.
This means that we can provide only the same kinds of arguments, the base and
the height, to calculate the moment of inertia. This also means that the compiler
will not allow us to write two methods that have the same name, the same number
of arguments, and the same types of arguments because that would violate the
rule of function overloading.
10.In order to overload the MomentOfInertia() function, we will add an argument that
will never be used; this argument will serve only as a “witness” to set the difference
C# 3.0 Practical Learning 146
between both versions of the function. This “witness” argument can be anything:
an integer, a character, a string, a float, etc. For our example, we will make it a
simple integer. To use the version applied to the triangle, we will provide this
argument to overload the MomentOfInertia() function. When called with only two
arguments, the rectangle version will apply.
 
Change the file as follows:
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Exercise


{
// Rectangle
static double MomentOfInertia(double b, double h)
{
return b * h * h * h / 3;
}

// Semi-Circle
static double MomentOfInertia(double R)
{
const double PI = 3.14159;

return R * R * R * R * PI/ 8;
}

// Triangle
static double MomentOfInertia(double b, double h, int i)
{
return b * h * h * h / 12;
}

static int Main()


{
double Base = 7.74, Height = 14.38, Radius = 12.42;

Console.WriteLine(
"Rectangle - Moment of inertia with regard to the X axis: ");
Console.WriteLine("I = {0}mm", MomentOfInertia(Base, Height));

Console.WriteLine("\nSemi-Circle - Moment of inertia of a " +


"semi-circle with regard to the X axis: ");
Console.WriteLine("I = {0}mm", MomentOfInertia(Radius));

Console.WriteLine("\nEnter the dimensions of the triangle");


Console.Write("Base: ");
Base = double.Parse(Console.ReadLine());
Console.Write("Height: ");
Height = double.Parse(Console.ReadLine());

Console.WriteLine(
"\nTriangle - Moment of inertia with regard to the X axis: ");
Console.WriteLine("I = {0}mm", MomentOfInertia(Base, Height, 1));

C# 3.0 Practical Learning 147


Console.WriteLine();
return 0;
}
}

11.Execute the program. Here is an example:


 
Rectangle - Moment of inertia with regard to the X axis:
I = 7671.78395376mm

Semi-Circle - Moment of inertia of a semi-circle with regard to the X


axis:
I = 9344.28126291881mm

Enter the dimensions of the triangle


Base: 5.52
Height: 3.84

Triangle - Moment of inertia with regard to the X axis:


I = 26.04662784mm

12.Close the DOS window

Class Construction and Destruction


 

Method Initializer

Imagine you are writing a program for a business that sells flowers:

Flower

Type Daisies Lilies Roses Live Plants Orchids

Color White Mixed Red Green Pink

Arrangement Vase Vase Bouquet Basket Vase

Price 37.15 29.95 85.95 60.95 55.95

Consider the following program:


using System;

public class Flower


C# 3.0 Practical Learning 148
{
public int Type;

public int Color;

public char Arrangement;


public double UnitPrice;
}

public class Exercise


{
static int Main()
{
var flr = new Flower();

Console.WriteLine("Flower Type: {0}", flr.Type);


Console.WriteLine("Flower Color: {0}", flr.Color);
Console.WriteLine("Arrangement: {0}", flr.Arrangement);
Console.WriteLine("Price: {0:C}", flr.UnitPrice);
Console.WriteLine("");
return 0;
}
}

This would produce:


Flower Type: 0
Flower Color: 0
Arrangement:
Price: $0.00

Press any key to continue . . .

If you declare a variable of a class in your program, when the program comes up, the
compiler reserves enough memory space for each member of the class. The memory
space reserved for each member variable is filled with an initial value based on its type.
For a string object, the space would be left empty. For an integer type, the space would
be filled with 0. A better way to take care of this type is to provide a value whose role
would be to initialize the member variables with the values of your choice. A method that
initializes an object can return any value but it is preferable to be of type void because its
primary purpose is to reset the values. Since this method would give a starting value to all
member variables that need to be initialized, it should have an equivalent argument for
each of the member variables that it would initialize. Here is an example:
public class Flower
{
public int Type;
public int Color;
public char Arrangement;
public double UnitPrice;

public void Initializer(int tp, int clr, char arng, double price)
{
}
}

The method initializer does not have to initialize all members of the class. For example,
the previous execution of the program shows that the member variables that are of type

C# 3.0 Practical Learning 149


string are initialized with empty strings. In such a case, you may not have to initialize
such variables. To implement a method initializer, simply assign its argument to the
corresponding member variable of the class. Here are examples:
public class Flower
{
public int Type;
public int Color;
public char Arrangement;
public double UnitPrice;

public void Initializer(int tp, int clr, char arng, double price)
{
Type = tp;
Color = clr;
Arrangement = arng;
UnitPrice = price;
}
}

You can call a method initializer after declaring the instance of the class to give it initial
values. Here is an example:
using System;

public class Flower


{
public int Type;
public int Color;
public char Arrangement;
public double UnitPrice;

public void Initializer(int tp, int clr, char arng,


double price)
{
Type = tp;
Color = clr;
Arrangement = arng;
UnitPrice = price;
}
}

public class Exercise


{
static int Main()
{
var flr = new Flower();
flr.Initializer(3, 7, 'V', 37.15D);

Console.WriteLine("Flower Type: {0}", flr.Type);


Console.WriteLine("Flower Color: {0}", flr.Color);
Console.WriteLine("Arrangement: {0}",
flr.Arrangement);
Console.WriteLine("Price: {0:C}",
flr.UnitPrice);
Console.WriteLine("");
return 0;
}
}

C# 3.0 Practical Learning 150


This would produce:
Flower Type: 3
Flower Color: 7
Arrangement: V
Price: $37.15

Press any key to continue . . .

Using a method initializer, after initializing the object, you can use the values it holds as
you see fit.

Default Constructor

A constructor is a special method that is created when the object comes to life. This
particular method holds the same name as the class and it initializes the object whenever
that object is created. When you create a class, if you don't declare a constructor, the
compiler creates one for you; this is useful because it lets all other objects of the program
know that the object exists. This compiler-created constructor is called the default
constructor. If you want, you can create your own constructor.

To create a constructor, declare a method that holds the same name as the class.
Remember that the method must not return any value.

Here is an example:
namespace FlowerShop
{
public class Flower
{
Flower()
{
}
}
}

When you declare an instance of the class, whether you use that object or not, a
constructor for the object is created. When an instance of a class has been declared, the
default constructor is called, whether the object is used or not. This is illustrated in the
following program:
using System;

namespace FlowerShop
{
public class Flower
{
public int Type;
public int Color;
public char Arrangement;
public decimal UnitPrice;

public Flower()
{
Console.WriteLine("New Flower Order");
}
}

C# 3.0 Practical Learning 151


public class Exercise
{
static int Main()
{
var flr = new Flower();
return 0;
}
}
}

This would produce:


New Flower Order

Press any key to continue...

As you can see, even though the flr variable was not used, just its declaration was enough
to signal it. You might find it sometimes convenient to create your own constructor
because, whether you create an empty constructor or not, this does not negatively impact
your program.

The Constructor Initializer

A constructor can be used to initialize the member variables of a class. As such, a


constructor provides a valuable alternative to a method initializer, the type of method we
saw earlier. To use a constructor to initialize the member variables of a class, provide as
arguments the necessary variables that you intend to initialize. You don't have to initialize
all member variables in the constructor, only those that need to be initialized. In fact, you
should initialize only those members that you think the other objects would need when
using this object. This means that your object may have fields that, either the external
objects don't need to modify (or access) or the member variable(s) will be initialized later
when called from the needed object(s).

To implement a default constructor, you can just initialize the desired members of the
class. For a member variable of a numeric type, you can just assign the desired constant
to each. If the variable is a character, assign a single-quoted symbol to it. If the variable is
a string, then assign a double-quoted value to the variable. Here are examples:
using System;

namespace FlowerShop
{
public class Flower
{
public int Type;
public int Color;
public char Arrangement;
public decimal UnitPrice;

public Flower()
{
Type = 1;
Color = 1;
Arrangement = 'V';
UnitPrice = 0M;
}
C# 3.0 Practical Learning 152
}

public class Program


{
static int Main()
{
var flr = new Flower();

Console.WriteLine("Flower Type: {0}",


flr.Type);
Console.WriteLine("Flower Color: {0}",
flr.Color);
Console.WriteLine("Arrangement: {0}",
flr.Arrangement);
Console.WriteLine("Price: {0:C}",
flr.UnitPrice);
Console.WriteLine("");
return 0;
}
}
}

Constructor Overloading

The default constructor is the favorite place to provide default values to the members of a
class. Besides the default constructor, you can add as many constructors as you judge
necessary. This feature of C# allows you to create various constructors for different
reasons. This also means that the methods or constructors of a class can be overloaded.

One of the rules of method overloading consists of having methods with different types of
arguments. The most basic constructor you would create can use a single argument.
When implementing a constructor that takes one argument, you should initialize the
member that corresponds to the unique argument and initialize the other members with
default values. Here is an example:
using System;

namespace FlowerShop
{
public class Flower
{
public int Type;
public int Color;
public char Arrangement;
public decimal UnitPrice;

public Flower()
{
Type = 1;
Color = 1;
Arrangement = 'V';
UnitPrice = 0M;
}

C# 3.0 Practical Learning 153


public Flower(int tp)
{
Type = tp;
Color = 1;
Arrangement = 'V';
UnitPrice = 0M;
}
}
}

If you create a class with only one constructor as in the current example, when declaring
an instance of the class, you must use that constructor: you cannot use the default
constructor that doesn't take an argument. When declaring the variable, initialize it with a
constructor with parentheses and provide the value(s) in the parentheses of the
constructor. Here is an example:
using System;

namespace FlowerShop
{
public class Flower
{
public string Type;
public string Color;
public string Arrangement;
public double UnitPrice;

public Flower()
{
Type = "";
Color = "Red";
Arrangement = "Basket";
UnitPrice = 35.95D;
}

public Flower(string tp)


{
Type = tp;
Color = "Red";
Arrangement = "Basket";
UnitPrice = 35.95D;
}
}

public class Exercise


{
static int Main()
{
var flr = new Flower("Tulips");

Console.WriteLine("Flower Type: {0}", flr.Type);


Console.WriteLine("Flower Color: {0}", flr.Color);
Console.WriteLine("Arrangement: {0}", flr.Arrangement);
Console.WriteLine("Price: {0:C}", flr.UnitPrice);
Console.WriteLine("");
return 0;
}
}
}

C# 3.0 Practical Learning 154


This would produce:
Flower Type: Tulips
Flower Color: Red
Arrangement: Basket
Price: $35.95

Press any key to continue . . .

In the same way, you can create different constructors for different initializations,
although it would not be realistic to create a different constructor for each variable. If you
create different constructors with different arguments to initialize (remember the rules of
method overloading), when declaring the classes, make sure you initialize each instance
with the right number of arguments; otherwise, the compiler would complain.

If you create a class with only one constructor and that constructor has at least one
argument, the default constructor would not be available anymore. If you want to access
a default constructor of an object, you have two alternatives:

 If you don't create any constructor at all on a class, the default constructor would
always be available whenever you invoke that class

 If you create at least one constructor on a class and supply at least one argument
to that constructor, you must explicitly create a default constructor for your class.

The Destructor of a Class

As opposed to a constructor, a destructor is called when a program has finished using an


object. A destructor does the cleaning behind the scenes. Like the default constructor, the
compiler always creates a default destructor if you don't create one. Unlike the
constructor, the destructor cannot be overloaded. This means that, if you decide to create
a destructor, you can have only one. Like the default constructor, a destructor also has
the same name as its class. This time, the name of the destructor starts with a tilde "~".

To create a destructor, type ~ followed by the name of the class. Here is an example:

C# 3.0 Practical Learning 155


namespace FlowerShop
{
public class Flower
{
public string Type;
public string Color;
public string Arrangement;
public decimal UnitPrice;

public Flower()
{
Type = "";
Color = "Red";
Arrangement = "Basket";
UnitPrice = 35.95M;
}

public Flower(string tp)


{
Type = tp;
Color = "Red";
Arrangement = "Basket";
UnitPrice = 35.95M;
}

~Flower()
{
}
}
}

C# 3.0 Practical Learning 156


COMBINATIONS OF
CLASSES
 

Classes Combinations
 

Class Nesting

A class can be created inside of another class. A class created inside of another is referred
to as nested. To nest a class, simply create it as you would any other. Here is an example
of a class called Inside that is nested in a class called Outside:
public class Outside
{
public class Inside
{
}
}

In the same way, you can nest as many classes as you wish in another class and you can
nest as many classes inside of other nested classes if you judge it necessary. Just as you
would manage any other class so can you exercise control on a nested class. For
example, you can declare all necessary fields, properties, or methods in the nested class
or in the nesting class. When you create one class inside of another, there is no special
programmatic relationship between both classes:  just because a class is nested does not
mean that the nested class has immediate access to the members of the nesting class.
They are two different classes and they can be used separately as you judge it necessary. 

The name of a nested class is not "visible" outside of the nesting class. To access a nested
class outside of the nesting class, you must qualify the name of the nested class anywhere
you want to use it. For example, if you want to declare an Inside variable somewhere in
the program but outside of Outside, you must qualify its name. Here is an example:
using System;

public class Outside


{
public class Inside
{
public Inside()
{
Console.WriteLine(" -= Inside =-");
}
}

C# 3.0 Practical Learning 157


public Outside()
{
Console.WriteLine(" =- Outside -=");
}
}

public class Exercise


{
static int Main()
{
Outside Recto = new Outside();
Outside.Inside Ins = new Outside.Inside();

return 0;
}
}

This would produce:


=- Outside -=
-= Inside =-

Because there is no programmatically privileged relationship between a nested class and


its "container" class, if you want to access the nested class in the nesting class, you can
use its static members. In other words, if you want, you can declare static all members of
the nested class that you want to access in the nesting class. Here is an example:
using System;

public class Outside


{
public class Inside
{
public static string InMessage;

public Inside()
{
Console.WriteLine(" -= Insider =-");
InMessage = "Sitting inside while it's raining";
}

public static void Show()


{
Console.WriteLine("Show me the wonderful world of C#
Programming");
}
}

public Outside()
{
Console.WriteLine(" =- The Parent -=");
}

public void Display()


{
Console.WriteLine(Inside.InMessage);
Inside.Show();
}
}

C# 3.0 Practical Learning 158


class Exercise
{
static int Main()
{
Outside Recto = new Outside();
Outside.Inside Ins = new Outside.Inside();

Recto.Display();
return 0;
}
}

In the same way, if you want to access the nesting class in the nested class, you can go
through the static members of the nesting class. To do this, you can declare static all
members of the nesting class that you want to access in the nested class. Here is an
example:
using System;

public class Outside


{
public class Inside
{
public static string InMessage;

public Inside()
{
Console.WriteLine(" -= Insider =-");
InMessage = "Sitting inside while it's raining";
}

public static void Show()


{
Console.WriteLine("Show me the wonderful world of C#
Programming");
}

public void FieldFromOutside()


{
Console.WriteLine(Outside.OutMessage);
}
}

private static string OutMessage;

public Outside()
{
Console.WriteLine(" =- The Parent -=");
OutMessage = "Standing outside! It's cold and raining!!";
}

public void Display()


{
Console.WriteLine(Inside.InMessage);
Inside.Show();
}
}

public class Exercise

C# 3.0 Practical Learning 159


{
static int Main()
{
Outside Recto = new Outside();
Outside.Inside Ins = new Outside.Inside();

Recto.Display();
Console.WriteLine();
Ins.FieldFromOutside();
return 0;
}
}

This would produce:


=- The Parent -=
-= Insider =-
Sitting inside while it's raining
Show me the wonderful world of C# Programming

Standing outside! It's cold and raining!!

Instead of static members, if you want to access members of a nested class in the nesting
class, you can first declare a variable of the nested class in the nesting class. In the same
way, if you want to access members of a nesting class in the nested class, you can first
declare a variable of the nesting class in the nested class. Here is an example:
using System;

public class Outside


{
// A member of the nesting class
private string OutMessage;

// The nested class


public class Inside
{
// A field in the nested class
public string InMessage;

// A constructor of the nested class


public Inside()
{
Console.WriteLine(" -= Insider =-");
this.InMessage = "Sitting inside while it's
raining";
}

// A method of the nested class


public void Show()
{
// Declare a variable to access the nesting class
Outside outsider = new Outside();
Console.WriteLine(outsider.OutMessage);
}
} // End of the nested class

// A constructor of the nesting class


public Outside()
{
C# 3.0 Practical Learning 160
this.OutMessage = "Standing outside! It's cold and
raining!!";

Console.WriteLine(" =- The Parent -=");


}

// A method of the nesting class


public void Display()
{
Console.WriteLine(insider.InMessage);
}

// Declare a variable to access the nested class


Inside insider = new Inside();
}

public class Exercise


{
static int Main()
{
Outside Recto = new Outside();
Outside.Inside Ins = new Outside.Inside();

Ins.Show();
Recto.Display();
return 0;
}
}

This would produce:


-= Insider =-
=- The Parent -=
-= Insider =-
-= Insider =-
=- The Parent -=
Standing outside! It's cold and raining!!
Sitting inside while it's raining

A Class as a Field

Just like any of the variables we have used so far, you can make a class or a structure a
member variable of another class. To use a class in your own class, of course you must
have that class. You can use one of the classes already available in C# or you can first
create your own class. Here is an example of a class:
public class Point
{
internal short x;
internal short y;
}

A field is a member variable created from another class instead of a primitive type. To use
one class as a member variable of another class, simply declare its variable as you would
proceed with any of the member variables we have declared so far. Here is an example:
public class Point
{

C# 3.0 Practical Learning 161


internal short x;
internal short y;
}

public class CoordinateSystem


{
public Point Start;
}

After a class has been declared as a member variable of another class, it can be used
regularly. Because the member is a class, declared as a reference, there are some rules
you must follow to use it. After declaring the member variable, you must make sure you
have allocated memory for it. You must also make sure that the variable is initialized
appropriately before it can be used; otherwise you would receive an error when compiling
the program.

Practical Learning: Using a Class as a Field

1. Start a new Console Application and name it ElectonicStore1

2. To create a new class, in the Solution Explorer, right-click the name of the project,
position the mouse on Add and click Class...

3. Set the Name to StoreItem and click Add

4. Complete the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElectronicStore1
{
public class StoreItem
{
private long nbr;
private char cat;
private string mk;
private string mdl;
private double price;

public long GetItemNumber()


{
return nbr;
}

public void SetItemNumber(long number)


{
this.nbr = number;
}

public char GetCategory()


{
return cat;
}

C# 3.0 Practical Learning 162


public void SetCategory(char category)
{
this.cat = category;
}

public string GetMake()


{
return mk;
}

public void SetMake(string make)


{
this.mk = make;
}

public string GetModel()


{
return mdl;
}

public void SetModel(string model)


{
this.mdl = model;
}

public double GetUnitPrice()


{
return price;
}

public void SetUnitPrice(double unitPrice)


{
this.price = unitPrice;
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElectronicStore1
{
class Program
{
static void Main()
{
string strTitle1 = "=-= Nearson Electonics =-=\n";
string strTitle2 = "******* Store Items ******";

Console.WriteLine();
}
}
}

6. Save all
C# 3.0 Practical Learning 163
Returning a Class or Passing a Class
 

Returning a Class From a Method

Like a value from a regular type, you can return a class value from a method of a class. To
do this, you can first declare the method and specify the class as the return type. Here is
an example:
public class Point
{
internal short x;
internal short y;
}

public class CoordinateSystem


{
private Point Start;
private Point End;

public Point GetThePoint()


{
}
}

After implementing the method, you must return a value that is conform to the class,
otherwise you would receive an error when compiling the application. You can proceed by
declaring a variable of the class in the body of the method, initializing the variable, and
then returning it. Here is an example:
public class Point
{
internal short x;
internal short y;
}

public class CoordinateSystem


{
private Point Start;
private Point End;

public Point GetThePoint()


{
Point pt = new Point();

Console.Write("Enter the x coordinate of the point: ");


pt.x = short.Parse(Console.ReadLine());
Console.Write("Enter the y coordinate of the point: ");
pt.y = short.Parse(Console.ReadLine());
return pt;
}
}

Once a method has returned a value of a class, the value can be used as normally as
possible.

C# 3.0 Practical Learning 164


Passing a Class as Argument

Once a class has been created, it can be used like any other variable. For example, its
variable can be passed as argument to a method of another class. When a class is passed
as argument, its public members are available to the method that uses it. As done for the
arguments of primitive types, you can pass more than one class as argument to a method.
Here are different examples:
using System;

namespace Geometry
{
public class Point
{
internal short x;
internal short y;
}

public class CoordinateSystem


{
public Point Start;
public Point End;

public Point GetThePoint()


{
Point pt = new Point();

Console.Write("Enter the x coordinate of the point: ");


pt.x = short.Parse(Console.ReadLine());
Console.Write("Enter the y coordinate of the point: ");
pt.y = short.Parse(Console.ReadLine());
return pt;
}

public double DistanceFromOrigin(Point pt)


{
double sqr1 = Math.Pow(pt.x, 2);
double sqr2 = Math.Pow(pt.y, 2);
double distance = Math.Sqrt(sqr1 + sqr2);
return distance;
}

public double DistanceBetween2Points(Point pt1, Point pt2)


{
double sqr1 = Math.Pow(pt2.x - pt1.x, 2);
double sqr2 = Math.Pow(pt2.y - pt1.y, 2);
double distance = Math.Sqrt(sqr1 + sqr2);
return distance;
}
}

public class Program


{
private static CoordinateSystem IdentifyCoordinates()
{
CoordinateSystem coord = new CoordinateSystem();

Console.WriteLine("Start Point");
C# 3.0 Practical Learning 165
coord.Start = coord.GetThePoint();
Console.WriteLine("End Point");
coord.End = coord.GetThePoint();

return coord;
}

private static void Show(CoordinateSystem c)


{
Console.WriteLine("Coordinate System");
Console.WriteLine("Starting Point: P({0}, {1})", c.Start.x,
c.Start.y);
Console.WriteLine("Ending Point: Q({0}, {1})", c.End.x,
c.End.y);
Console.WriteLine("Distance Between Both Points: {0:F}",
c.DistanceBetween2Points(c.Start, c.End));
}

static int Main()


{
CoordinateSystem coord = IdentifyCoordinates();

Console.WriteLine();
Show(coord);
return 0;
}
}
}

Here is an example of running the program:


Start Point
Enter the x coordinate of the point: -2
Enter the y coordinate of the point: 2
End Point
Enter the x coordinate of the point: 3
Enter the y coordinate of the point: -6

Coordinate System
Starting Point: P(-2, 2)
Ending Point: Q(3, -6)
Distance Between Both Points: 9.43
Press any key to continue . . .

Because classes are always used as references, when passing a class as argument, it is
implied to be passed by reference. To reinforce this, you can type the ref keyword to the
left of the argument. Here is an example:
using System;

namespace ConsoleApplication1
{
public class Point
{
internal short x;
internal short y;
}

public class CoordinateSystem


{
C# 3.0 Practical Learning 166
public Point Start;
public Point End;

public Point GetThePoint()


{
Point pt = new Point();

Console.Write("Enter the x coordinate of the point: ");


pt.x = short.Parse(Console.ReadLine());
Console.Write("Enter the y coordinate of the point: ");
pt.y = short.Parse(Console.ReadLine());
return pt;
}

public double DistanceFromOrigin(ref Point pt)


{
double sqr1 = Math.Pow(pt.x, 2);
double sqr2 = Math.Pow(pt.y, 2);
double distance = Math.Sqrt(sqr1 + sqr2);
return distance;
}

public double DistanceBetween2Points(ref Point pt1, ref Point


pt2)
{
double sqr1 = Math.Pow(pt2.x - pt1.x, 2);
double sqr2 = Math.Pow(pt2.y - pt1.y, 2);
double distance = Math.Sqrt(sqr1 + sqr2);
return distance;
}
}

public class Program


{
private static CoordinateSystem IdentifyCoordinates()
{
CoordinateSystem coord = new CoordinateSystem();

Console.WriteLine("Start Point");
coord.Start = coord.GetThePoint();
Console.WriteLine("End Point");
coord.End = coord.GetThePoint();

return coord;
}

private static void Show(CoordinateSystem c)


{
Console.WriteLine("Coordinate System");
Console.WriteLine("Starting Point: P({0}, {1})", c.Start.x,
c.Start.y);
Console.WriteLine("Ending Point: Q({0}, {1})", c.End.x,
c.End.y);
Console.WriteLine("Distance Between Both Points: {0:F}",
c.DistanceBetween2Points(ref c.Start, ref
c.End));
}

static int Main()


{
C# 3.0 Practical Learning 167
CoordinateSystem coord = IdentifyCoordinates();

Console.WriteLine();
Show(coord);
return 0;
}
}
}

Practical Learning: Return a Class or Passing One as Argument

1. To return a class or pass it as argument, change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElectronicStore1
{
public class SaleItem
{
double DiscountAmount;
double NetPrice;
int Quantity;
double SaleTotal;

public double GetDiscountRate()


{
Console.Write(
"Discount Applied (Enter 0 to 100, 0 if no discount): ");
double discount = double.Parse(Console.ReadLine());
return discount;
}

public int GetQuantity()


{
Console.Write("Enter Quantity: ");
int q = int.Parse(Console.ReadLine());
return q;
}

public StoreItem Create()


{
long itemNumber;
char category;
string make;
string model;
double discount;
double price;
StoreItem saleItem = new StoreItem();

Console.Write("Enter the Item #: ");


itemNumber = long.Parse(Console.ReadLine());
Console.WriteLine("Category");
Console.WriteLine("A - Audio Cables");
Console.WriteLine("B - Instructional and Tutorials (Books)");
Console.WriteLine("C - Cell Phones and Accessories");
C# 3.0 Practical Learning 168
Console.WriteLine("D - Bags and Cases");
Console.WriteLine("E - Headphones");
Console.WriteLine("F - Instructional and Tutorials (VHS &
DVD)");
Console.WriteLine("G - Digital Cameras");
Console.WriteLine("H - Cables and Connectors");
Console.WriteLine("I - PDAs and Accessories");
Console.WriteLine("J - Telephones and Accessories");
Console.WriteLine("K - Surge Protector");
Console.WriteLine("L - TVs and Videos");
Console.WriteLine("U - Unknown");
Console.Write("Your Choice? ");
category = char.Parse(Console.ReadLine());
Console.Write("Make: ");
make = Console.ReadLine();
Console.Write("Model: ");
model = Console.ReadLine();
Console.Write("Unit Price: ");
price = double.Parse(Console.ReadLine());

saleItem.SetItemNumber(itemNumber);
saleItem.SetCategory(category);
saleItem.SetMake(make);
saleItem.SetModel(model);
saleItem.SetUnitPrice(price);

return saleItem;
}

public void ShowSaleItem(StoreItem item)


{
double discountRate = GetDiscountRate();
int quantity = GetQuantity();
DiscountAmount = item.GetUnitPrice() * discountRate / 100;
NetPrice = item.GetUnitPrice() - DiscountAmount;
SaleTotal = NetPrice * quantity;

Console.WriteLine("\nStore Item Description");


Console.WriteLine("Item Number: {0}",
item.GetItemNumber());
Console.WriteLine("Category: {0}",
item.GetCategory());
Console.WriteLine("Make {0}", item.GetMake());
Console.WriteLine("Model: {0}", item.GetModel());
Console.WriteLine("Unit Price: {0:C}",
item.GetUnitPrice());
Console.WriteLine("Discount Rate: {0:P}",
discountRate/100);
Console.WriteLine("Discount Amount: {0:C}", DiscountAmount);
Console.WriteLine("Price/Item: {0:C}", NetPrice);
Console.WriteLine("Quantity: {0}", quantity);
Console.WriteLine("Sale Total: {0:C}", SaleTotal);
}
}

public class Program


{
static void Main()
{
StoreItem item = new StoreItem();
C# 3.0 Practical Learning 169
SaleItem sale = new SaleItem();
string strTitle1 = "=-= Nearson Electonics =-=\n";
string strTitle2 = "******* Store Items ******";

Console.WriteLine(strTitle1);
Console.WriteLine(strTitle2);

item = sale.Create();
sale.ShowSaleItem(item);

Console.WriteLine();
}
}
}

2. Execute the application. Here is an example:


 
=-= Nearson Electonics =-=

******* Store Items ******


Enter the Item #: 927374
Category
A - Audio Cables
B - Instructional and Tutorials (Books)
C - Cell Phones and Accessories
D - Bags and Cases
E - Headphones
F - Instructional and Tutorials (VHS &
DVD)
G - Digital Cameras
H - Cables and Connectors
I - PDAs and Accessories
J - Telephones and Accessories
K - Surge Protector
L - TVs and Videos
U - Unknown
Your Choice? L
Make: NEC
Model: VT48 Video Projector
Unit Price: 705.95
Discount Applied (Enter 0 to 100, 0 if no
discount): 15
Enter Quantity: 1

Store Item Description


Item Number: 927374
Category: L
Make NEC
Model: VT48 Video Projector
Unit Price: $705.95
Discount Rate: 15.00 %
Discount Amount: $105.89
Price/Item: $600.06
Quantity: 1
Sale Total: $600.06

Press any key to continue . . .

3. Return to your programming environment


C# 3.0 Practical Learning 170
Involving a Class and its Own Methods
 

Passing a Class as its Own Argument

An instance of a class can be passed as an argument to one of its own methods (if you
have programmed in C++, an example of this implementation is the copy constructor;
although you can legitimately create a copy constructor in C#, it does not have the exact
same concept as in C++, probably because C# has the Equals() method, which is
actually a concept of the .NET Framework). To do this, you primarily pass the argument as
if it were any class. Here is an example:
public class Point
{
internal int x;
internal int y;

public void Equivalent(Point Same)


{
}
}

Then, in the body of the method, do whatever you want. You can, or you may not, use
the argument. Still, if you decide to use the argument, know that all of the other members
of the class are available through the argument. Probably the simplest way to use the
argument is the assign each of of its values to the equivalent member of the class. Here is
an example:
public class Point
{
internal int x;
internal int y;

public void Equivalent(Point Same)


{
this.x = Same.x;
this.y = Same.y;
}
}

When calling the method, make sure you pass an instance of the class to it. You can first
create and define the class, then pass it. Here is an example:
using System;

public class Point


{
internal int x;
internal int y;

public void Equivalent(Point Same)


{
this.x = Same.x;
this.y = Same.y;
}
}
C# 3.0 Practical Learning 171
public class Program
{
private static void ShowPoint(Point pt)
{
Console.Write("Point Coordinates: ");
Console.WriteLine("A({0}, {1})", pt.x, pt.y);
}

static int Main(string[] args)


{
Point pt = new Point();

pt.x = 4;
pt.y = 6;
ShowPoint(pt);

Point One = new Point();


One.Equivalent(pt);
ShowPoint(One);

return 0;
}
}

This would produce:


Point Coordinates: A(4, 6)
Point Coordinates: A(4, 6)
Press any key to continue . . .

Instead of first declaring a variable of the class and initializing it, you can create an
instance of the class in the parentheses of the calling method. To do this, you may need a
constructor that can specify the values of the fields of the class so the argument can be
rightfully initialized. Here is an example:  
using System;

public class Point


{
internal int x;
internal int y;

public Point()
{
}

public Point(int XCoord, int YCoord)


{
this.x = XCoord;
this.y = YCoord;
}

public void Equivalent(Point Same)


{
this.x = Same.x;
this.y = Same.y;
}
}

C# 3.0 Practical Learning 172


public class Program
{
private static void ShowPoint(Point pt)
{
Console.Write("Point Coordinates: ");
Console.WriteLine("A({0}, {1})", pt.x, pt.y);
}

static int Main(string[] args)


{
Point pt = new Point();

pt.x = 4;
pt.y = 6;
ShowPoint(pt);

Point One = new Point();


One.Equivalent(new Point(-3, 2));
ShowPoint(One);

return 0;
}
}

Instead of a formal method, you can use a constructor of the class to pass an instance of
the same class. Then, in the constructor, use the argument as you see fit, knowing that all
the members of the class are available. Here is an example:
public class Point
{
internal int x;
internal int y;

public Point()
{
}

public Point(int XCoord, int YCoord)


{
this.x = XCoord;
this.y = YCoord;
}

public Point(Point Same)


{
this.x = Same.x;
this.y = Same.y;
}
}

Obviously the purpose of passing a class to one of its own methods is not to find its
equivalent. The C# language (actually the .NET Framework) can also take care of that
(through the Equals() built-in method). Instead, you can create a method that takes an
instance of the same class but modifies that instance. For example, for our Point class, we
may want to create a new point that is distanced by one unit from the current Point
object. Here is an example of doing that:
using System;

C# 3.0 Practical Learning 173


public class Point
{
internal int x;
internal int y;

public Point()
{
}

public Point(int XCoord, int YCoord)


{
this.x = XCoord;
this.y = YCoord;
}

public void Equivalent(Point Same)


{
this.x = Same.x;
this.y = Same.y;
}

public void CreatePointOneUnitAway(Point AddUnit)


{
this.x = AddUnit.x + 1;
this.y = AddUnit.y + 1;
}
}

public class Program


{
private static void ShowPoint(Point pt)
{
Console.Write("Point Coordinates: ");
Console.WriteLine("A({0}, {1})", pt.x, pt.y);
}

static int Main(string[] args)


{
Point pt = new Point();

pt.x = 4;
pt.y = 6;
ShowPoint(pt);

Point One = new Point();


One.CreatePointOneUnitAway(pt);
ShowPoint(One);
One.CreatePointOneUnitAway(new Point(-8, -3));
ShowPoint(One);

return 0;
}
}

This would produce:


Point Coordinates: A(4, 6)
Point Coordinates: A(5, 7)
Point Coordinates: A(-7, -2)
Press any key to continue . . .
C# 3.0 Practical Learning 174
Returning a Class From its Own Method

You can create a method in a class that returns an instance of the class. To start, on the
left side of the method, enter the name of the class. Here is an example:
public class Point
{
public Point MethodName()
{
}
}

There are various ways you can deal with the method. If you want to return a new value
of the class, you can declare an instance of the class, initialize it, and then return it. Here
is an example:
using System;

public class Point


{
internal int x;
internal int y;

public Point()
{
}

public Point(int XCoord, int YCoord)


{
this.x = XCoord;
this.y = YCoord;
}

public Point(Point Same)


{
this.x = Same.x;
this.x = Same.x;
}

public Point AdvanceBy5()


{
Point Some = new Point();
Some.x = 5;
Some.y = 5;
return Some;
}
}

public class Program


{
private static void ShowPoint(Point pt)
{
Console.Write("Point Coordinates: ");
Console.WriteLine("A({0}, {1})", pt.x, pt.y);
}

static int Main(string[] args)


{

C# 3.0 Practical Learning 175


Point pt = new Point();

pt.x = 4;
pt.y = 6;
ShowPoint(pt);

Point Away5 = pt.AdvanceBy5();


ShowPoint(Away5);

return 0;
}
}

This would produce:


Point Coordinates: A(4, 6)
Point Coordinates: A(5, 5)
Press any key to continue . . .

Alternatively, you can declare an instance of the class, use the current values of the class
combined with the those of the instance to get new values, and then return the instance.
Here is an example:
using System;

public class Point


{
internal int x;
internal int y;

public Point()
{
}

public Point(int XCoord, int YCoord)


{
this.x = XCoord;
this.y = YCoord;
}

public Point(Point Same)


{
this.x = Same.x;
this.x = Same.x;
}

public Point AdvanceBy5()


{
Point Some = new Point();
Some.x = this.x + 5;
Some.y = this.y + 5;
return Some;
}
}

public class Program


{
private static void ShowPoint(Point pt)
{
Console.Write("Point Coordinates: ");
C# 3.0 Practical Learning 176
Console.WriteLine("A({0}, {1})", pt.x, pt.y);
}

static int Main(string[] args)


{
Point pt = new Point();

pt.x = 4;
pt.y = 6;
ShowPoint(pt);

Point Away5 = pt.AdvanceBy5();


ShowPoint(Away5);

return 0;
}
}

This would produce:


Point Coordinates: A(4, 6)
Point Coordinates: A(9, 11)
Press any key to continue . . .

Remember that, to call the method, if it is not static, you will need to declare an instance
of the class from where you are calling the method. The second type of implementation
consists of modifying the instance of the class that is calling the method. For example, you
can add values to its fields or you can perform any other operation you want on the
members of the calling instance. is an example:
using System;

public class Point


{
internal int x;
internal int y;

public Point()
{
}

public Point(int XCoord, int YCoord)


{
this.x = XCoord;
this.y = YCoord;
}

public Point(Point Same)


{
this.x = Same.x;
this.x = Same.x;
}

// This method adds 1 to each field of the class


// to get a new point away North-East of the current point
public Point CreatePointOneUnitAway()
{
this.x = this.x + 1;
this.y = this.y + 1;

C# 3.0 Practical Learning 177


return this;
}
}

public class Program


{
private static void ShowPoint(Point pt)
{
Console.Write("Point Coordinates: ");
Console.WriteLine("A({0}, {1})", pt.x, pt.y);
}

static int Main(string[] args)


{
Point pt = new Point();

pt.x = 4;
pt.y = 6;
ShowPoint(pt);

Point One = new Point(-8, 5);


Point Another = One.CreatePointOneUnitAway();
ShowPoint(Another);

return 0;
}
}

This would produce:


Point Coordinates: A(4, 6)
Point Coordinates: A(-7, 6)
Press any key to continue . . .

As we have learned now, you can create a method that takes an argument that is the
same type as its parent class. In the method, you can access any member of the class,
including calling the other methods of the class.

C# 3.0 Practical Learning 178


INTRODUCTION TO
CONDITIONS
 

Boolean Variables
 

Introduction

When interacting with a computer, a user submits values to a running application. Some
of these values are valid. Some other values must be rejected or changed. To take care of
these, the values must be checked, examined, re-examined, etc. The validity of a value is
checked against its type. For example, a number can be checked as being equal to
another. A condition can be checked as being true. A measure can be checked as to
whether it is higher than a certain threshold.

To perform the necessary validations of values, the C# language provides some symbols,
referred to as Boolean operators.

Practical Learning: Introducing Boolean Variables

1. Start Microsoft Visual C#

2. Create a new Console Application named FlowerShop1

3. To create a new class, on the main menu, click Project -> Add Class...

4. Set the Name of the class to Flower and click Add

5. Complete the Flower.cs file as follows:


 

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop1
{
public class Flower
{
public int Type;

public int Color;

public char Arrangement;

C# 3.0 Practical Learning 179


public decimal UnitPrice;

public Flower()
{
Type = 0;
Color = 0;
Arrangement = 'B';
UnitPrice = 0.00M;
}

public Flower(int type)


{
Type = type;
Color = 0;
Arrangement = 'B';
UnitPrice = 0.00M;
}

public Flower(int type, int


color,
char argn, decimal price)
{
Type = type;
Color = color;
Arrangement = argn;
UnitPrice = price;
}
}
}

6. To create a new class, in the Solution Explorer, right-click the project name,
position the mouse on Add and click Class...

7. Set the Name of the class to OrderProcessing and click Add

8. Complete the OrderProcessing.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop1
{
public class OrderProcessing
{
public OrderProcessing()
{
FlowerOrder = new Flower();
}

public Flower FlowerOrder;


public int Quantity;

public decimal GetTotalPrice()


{
return Quantity * FlowerOrder.UnitPrice;
}
}
C# 3.0 Practical Learning 180
}

9. Access the Program.cs file and complete it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop1
{
public class Program
{
private static OrderProcessing CreateFlowerOrder()
{
OrderProcessing order = new OrderProcessing();
int type, color, qty;
char arrangement;
decimal price;

Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");

Console.WriteLine("Enter the Type of Flower Order");


Console.WriteLine("1. Roses");
Console.WriteLine("2. Lilies");
Console.WriteLine("3. Daisies");
Console.WriteLine("4. Carnations");
Console.WriteLine("5. Live Plant");
Console.WriteLine("6. Mixed");
Console.Write("Your Choice: ");
type = int.Parse(Console.ReadLine());

Console.WriteLine("Enter the Color");


Console.WriteLine("1. Red");
Console.WriteLine("2. White");
Console.WriteLine("3. Yellow");
Console.WriteLine("4. Pink");
Console.WriteLine("5. Orange");
Console.WriteLine("6. Blue");
Console.WriteLine("7. Lavender");
Console.WriteLine("8. Mixed");
Console.Write("Your Choice: ");
color = int.Parse(Console.ReadLine());

Console.WriteLine("Enter the Type of Arrangement");


Console.WriteLine("U. Bouquet");
Console.WriteLine("V. Vase");
Console.WriteLine("B. Basket");
Console.WriteLine("M. Mixed");
Console.Write("Your Choice: ");
arrangement = char.Parse(Console.ReadLine());

Console.Write("Enter the Unit Price: ");


price = decimal.Parse(Console.ReadLine());

Console.Write("Enter Quantity: ");


qty = int.Parse(Console.ReadLine());
C# 3.0 Practical Learning 181
Flower flr = new Flower(type, color, arrangement, price);
order.FlowerOrder = flr;
order.Quantity = qty;

return order;
}

private static void ShowFlowerOrder(OrderProcessing order)


{
Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");
Console.WriteLine("Flower Type: {0}",
order.FlowerOrder.Type);
Console.WriteLine("Flower Color: {0}",
order.FlowerOrder.Color);
Console.WriteLine("Arrangement: {0}",
order.FlowerOrder.Arrangement);
Console.WriteLine("Price: {0:C}",
order.FlowerOrder.UnitPrice);
Console.WriteLine("Quantity: {0}", order.Quantity);
Console.WriteLine("Total Price: {0:C}",
order.GetTotalPrice());
Console.WriteLine("=======================");
}

static void Main(string[] args)


{
OrderProcessing flower = CreateFlowerOrder();
Console.WriteLine();

ShowFlowerOrder(flower);
Console.WriteLine();
}
}
}

10.Execute the application and test it. Here is an example:


 
=======================
==-=-=Flower Shop=-=-==
-----------------------
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 4
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
C# 3.0 Practical Learning 182
8. Mixed
Your Choice: 6
Enter the Type of Arrangement
U. Bouquet
V. Vase
B. Basket
M. Mixed
Your Choice: V
Enter the Unit Price: 37.95
Enter Quantity: 2

=======================
==-=-=Flower Shop=-=-==
-----------------------
Flower Type: 4
Flower Color: 6
Arrangement: V
Price: $37.95
Quantity: 2
Total Price: $75.90
=======================

Press any key to continue . . .

11.Close the DOS window

Declaring a Boolean Variable

A variable is referred to as Boolean if it can hold a value that is either true or false. To
declare a Boolean variable, you can use either the var or the bool keyword. Here is an
example:
using System;

public class Exercise


{
static int Main()
{
bool DrinkingUnderAge;

return 0;
}
}

Alternatively, you can declare a Boolean variable using the Boolean data type. The
Boolean data type is part of the System namespace. Here is an example:

using System;

public class Exercise


{
static int Main()
{
bool DrinkingUnderAge;
Boolean TheFloorIsCoveredWithCarpet;

return 0
}

C# 3.0 Practical Learning 183


}

After the variable has been declared, you must initialize it with a true or a false value.
In fact, if you declare it as var, you must initialize it. Here is an example:
using System;

public class Exercise


{
static int Main()
{
var DrinkingUnderAge = true;

return 0;
}
}

To display the value of a Boolean variable on the console, you can type its name in the
parentheses of the Write() or the WriteLine() methods of the Console class. Here is
an example:
using System;

public class Exercise


{
static int Main()
{
var DrinkingUnderAge = true;

Console.WriteLine("Drinking Under Age: {0}", DrinkingUnderAge);


return 0;
}
}

This would produce:


Drinking Under Age: True
Press any key to continue . . .

At any time and when you judge it necessary, you can change the value of the Boolean
variable by assigning it a true or false value. Here is an example:
using System;

public class Exercise


{
static int Main()
{
var DrinkingUnderAge = true;

Console.WriteLine("Drinking Under Age: {0}", DrinkingUnderAge);

DrinkingUnderAge = false;
Console.WriteLine("Drinking Under Age: {0}", DrinkingUnderAge);
return 0;
}
}

This would produce:

C# 3.0 Practical Learning 184


Drinking Under Age: True
Drinking Under Age: False
Press any key to continue . . .

Retrieving the Value of a Boolean Variable

As reviewed for the other data types, you can request the value of a Boolean variable
from the user. In this case, the user must type either True (or true) or False (or false)
and you can retrieve it using the Read() or the ReadLine() methods of the Console
class. Here is an example:
using System;

public class Exercise


{
static int Main()
{
var DrivingUnderAge = false;

Console.WriteLine("Were you driving under age?");


Console.Write("If Yes, enter True. Otherwise enter False: ");
DrivingUnderAge = bool.Parse(Console.ReadLine());

Console.WriteLine("\nWas Driving Under Age: {0}\n",


DrivingUnderAge);
return 0;
}
}

Here is an example of running the program:


Were you driving under age?
If Yes, enter True. Otherwise enter False: true

Was Driving Under Age: True

Press any key to continue . . .

Creating a Boolean Field

Like the other types of variables we used in previous lessons, a Boolean variable can be
made a field of a class. You declare it like any other variable, using the bool keyword or
the Boolean data type. Here is an example:

public class House

{
public char TypeOfHome;
public int Bedrooms;
public float Bathrooms;
public byte Stories;
public bool HasCarGarage;
public int YearBuilt;
public double Value;
}

C# 3.0 Practical Learning 185


When initializing an object that has a Boolean variable as a member, simply assign true
or false to the variable. In the same way, you can retrieve or check the value that a
Boolean member variable is holding by simply accessing it. Here are examples:
using System;

public class House


{
public char TypeOfHome;
public int Bedrooms;
public float Bathrooms;
public byte Stories;
public bool HasCarGarage;
public int YearBuilt;
public double Value;
}

public class Program


{
static int Main()
{
var Condominium = new
{
HasCarGarage = false,
YearBuilt = 2002,
Bathrooms = 1.5F,
Stories = 18,
Value = 155825,
Bedrooms = 2,
TypeOfHome = 'C'
};

Console.WriteLine("=//= Altair Realty =//=");


Console.WriteLine("=== Property Listing ===");
Console.WriteLine("Type of Home: {0}",
Condominium.TypeOfHome);
Console.WriteLine("Number of Bedrooms: {0}",
Condominium.Bedrooms);
Console.WriteLine("Number of Bathrooms: {0}",
Condominium.Bathrooms);
Console.WriteLine("Number of Stories: {0}",
Condominium.Stories);
Console.WriteLine("Year Built: {0}",
Condominium.YearBuilt);
Console.WriteLine("Has Car Garage: {0}",
Condominium.HasCarGarage);
Console.WriteLine("Monetary Value: {0}\n",
Condominium.Value);

return 0;
}
}

This would produce:


=//= Altair Realty =//=
=== Property Listing ===
Type of Home: C
Number of Bedrooms: 2
Number of Bathrooms: 1.5
C# 3.0 Practical Learning 186
Number of Stories: 18
Year Built: 2002
Has Car Garage: False
Monetary Value: 155825

Press any key to continue . . .

Boolean Arguments

Like parameters of the other types, you can pass an argument of type bool or Boolean to
a method. Such an argument would be treated as holding a true or false value.

Enumerations
 

Introduction

Consider that, when creating a program for a real estate company that sells houses, you
want the program to ask a customer the type of house that he or she wants to purchase
and/or the type of garage that the desired house should have. Here is an example:
using System;

public class Exercise


{
static int Main()
{
int TypeOfHouse = 0;
int TypeOfGarage = 0;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1 - Single Family");
Console.WriteLine("2 - Townhouse");
Console.WriteLine("3 - Condominium");
Console.Write("Your Choice: ");
TypeOfHouse = int.Parse(Console.ReadLine());

Console.WriteLine("Enter the type of garage you want");


Console.WriteLine("0 - Doesn't matter");
Console.WriteLine("1 - Interior");
Console.WriteLine("2 - Exterior");
Console.Write("Your Choice: ");
TypeOfGarage = int.Parse(Console.ReadLine());

Console.WriteLine("\nHouse Type: {0}", TypeOfHouse);


Console.WriteLine("Garage Type: {0}", TypeOfGarage);

return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1 - Single Family

C# 3.0 Practical Learning 187


2 - Townhouse
3 - Condominium
Your Choice: 3
Enter the type of garage you want
0 - Doesn't matter
1 - Interior
2 - Exterior
Your Choice: 1

House Type: 3
Garage Type: 1
Press any key to continue . . .

For such a program, the numbers can be vague. 1 can be considered a general number
but, in our program, it can represent a Single Family house or an Interior type of garage.
At the same time, our program uses the constant 1 in particular meaningful ways. To
make it possible to give more meaning to a constant number, when the number can be
made part of a series, C# allows you to create a type of list.

An enumeration is a series of constant integers that each has a specific position in the list
and can be recognized by a meaningful name. Based on this, instead of just remembering
that the constant 1 represents Single Family, you can create a list that has that type of
house. In another list, instead of using 1 again, you can give it a name. Consequently, in
each list, although the constant 1 would still be considered, at least it would mean
something precise.

To create an enumeration, you use the enum keyword, followed by the name of the
enumeration, followed by a name for each item of the list. The name of the enumerator
and the name of each item of the list follows the rules we reviewed for names. The
formula of creating an enumeration is:
enum Series_Name {Item1, Item2, Item_n};

Here is an example:
using System;

public class Exercise


{
enum HouseType { Unknown, SingleFamily, TownHouse, Condominium }

static int Main()


{
return 0;
}
}

Declaring an Enumeration Variable

After creating an enumeration, each member of the enumeration holds a value of a


natural number, such as 0, 4, 12, 25, etc. In C#, an enumeration cannot hold character
values (of type char). After creating an enumeration, you can declare a variable from it.
Here is an example:
using System;

public class Exercise


C# 3.0 Practical Learning 188
{
enum HouseType { Unknown, SingleFamily, TownHouse, Condominium }

static int Main()


{
HouseType propType;

return 0;
}
}

Just as done with the other types, you can use the var keyword to declare a variable of
an enumeration type.

Initializing an Enumeration Variable

After declaring a variable for an enumeration, to initialize it, specify which member of the
enumeration would be assigned to the variable. You should only assign a known member
of the enumeration. To do this, on the right side of the assignment operator, type the
name of the enumeration, followed by the period operator, and followed by the member
whose value you want to assign. Here is an example:
using System;

public class Exercise


{
enum HouseType { Unknown, SingleFamily, TownHouse, Condominium }

static int Main()


{
var propType = HouseType.SingleFamily;

return 0;
}
}

You can also find out what value the declared variable is currently holding. For example,
you can display it on the console using Write() or WriteLine(). Here is an example:
using System;

public class Exercise


{
enum HouseType { Unknown, SingleFamily, TownHouse, Condominium }

static int Main()


{
var propType = HouseType.SingleFamily;

Console.WriteLine("House Type: {0}", propType);

return 0;
}
}

This would produce:


House Type: SingleFamily

C# 3.0 Practical Learning 189


Press any key to continue . . .

An enumeration is in fact a list of numbers where each member of the list is identified with
a name. By default, the first item of the list has a value of 0, the second has a value of 1,
and so on. For example, on the HouseType enumeration, Unknown has a value of 0 while
Townhouse has a value of 2. These are the default values. If you don't want these values,
you can specify the value of one or each member of the list. Suppose you want the
Unknown member in the above enumeration to have a value of 5. To do this, use the
assignment operator "=" to give the desired value. The enumerator would be:
using System;

public class Exercise


{
enum HouseType { Unknown = 5, SingleFamily, TownHouse, Condominium }

static int Main()


{
return 0;
}
}

In this case, Unknown now would have a value of 5, SingleFamily would have a value of 6
because it follows a member whose value is 1 (thus 5 + 1 = 6). Townhouse would have a
value of 7, and Condominium would have a value of 8. You can also assign a value to
more than one member of an enumeration. Here is an example:
using System;

public class Exercise


{
enum HouseType { Unknown = 3, SingleFamily = 12, TownHouse,
Condominium = 8 }

static int Main()


{
return 0;
}
}

In this case, Townhouse would have a value of 13 because it follows SingleFamily that has
a value of 12.

Enumerations Visibility

By default, if you create an enumeration the way we have proceeded so far, it would be
available only in the project it belongs to. As done for a class, you can control an
enumeration's accessibility outside of its project. This means that you can hide or make it
visible outside of its project. To do this, you can precede it with the private or the
public keyword. Here is an example:

using System;

public class Exercise


{
public enum HouseType
{
C# 3.0 Practical Learning 190
Unknown,
SingleFamily,
TownHouse,
Condominium
}

static int Main()


{
HouseType propType = HouseType.SingleFamily;

Console.WriteLine("House Type: {0}", propType);


return 0;
}
}

An Enumeration as a Member Variable

After creating an enumeration, you can use it as a data type to declare a variable. To
create a field that is of an enumeration type, follow the same rules as done for the
primitive types: the name of the enumeration, followed by the name of the variable, and
followed by a semi-colon. Here is an example:
public enum HouseType
{
Unknown,
SingleFamily,
TownHouse,
Condominium
}

public class House


{
HouseType PropertyType;
}

In the same way, you can declare as many enumeration variables as you want. After
declaring the variable, to initialize it, assign it the desired member of the enumeration.
Here is an example:
public enum HouseType
{
Unknown,
SingleFamily,
TownHouse,
Condominium
}

public class House


{
HouseType PropertyType;

public House()
{
PropertyType = HouseType.Unknown;
}
}

C# 3.0 Practical Learning 191


Once the member variable has been initialized, you can use it as you see fit as we will
learn and practice in future sections and lessons. At a minimum, you can pass it to
Write() or WriteLine() to display its value. Here is an example:

using System;

public enum HouseType


{
Unknown,
SingleFamily,
TownHouse,
Condominium
}

public class House


{
public HouseType PropertyType;

public House()
{
PropertyType = HouseType.Unknown;
}

public void Display()


{
Console.WriteLine("Property Type: {0}", PropertyType);
}
}

public class Exercise


{
static int Main()
{
var propType = new House();
propType.Display();
Console.WriteLine();

propType.PropertyType = HouseType.SingleFamily;
propType.Display();
Console.WriteLine();

return 0;
}
}

This would produce:


Property Type: Unknown

Property Type: SingleFamily

Press any key to continue . . .

Using it as normal data type, you can create a method that returns an enumeration. You
can also pass an enumeration to a method as argument.

Practical Learning: Creating and Using Enumerations

C# 3.0 Practical Learning 192


1. Access the Flower.cs file

2. To create some enumerations, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop1
{
public enum FlowerType
{
Roses = 1,
Lilies,
Daisies,
Carnations,
LivePlant,
Mixed
}

public enum FlowerColor


{
Red = 1,
White,
Yellow,
Pink,
Orange,
Blue,
Lavender,
Mixed
}

public enum FlowerArrangement


{
Bouquet = 1,
Vase,
Basket,
Mixed
}

public class Flower


{
public FlowerType Type;
public FlowerColor Color;
public FlowerArrangement Arrangement;
public decimal UnitPrice;

public Flower()
{
Type = FlowerType.Mixed;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
UnitPrice = 0.00M;
}
public Flower(FlowerType type)
{
Type = type;
Color = FlowerColor.Mixed;
C# 3.0 Practical Learning 193
Arrangement = FlowerArrangement.Vase;
UnitPrice = 0.00M;
}
public Flower(FlowerType type, FlowerColor color,
FlowerArrangement argn, decimal price)
{
Type = type;
Color = color;
Arrangement = argn;
UnitPrice = price;
}
}
}

3. Access the Program.cs file

4. To use the enumerations, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop1
{
public class Program
{
private static OrderProcessing CreateFlowerOrder()
{
OrderProcessing order = new OrderProcessing();
int type, color, qty;
int arrangement;
decimal price;

Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");

Console.WriteLine("Enter the Type of Flower Order");


Console.WriteLine("1. Roses");
Console.WriteLine("2. Lilies");
Console.WriteLine("3. Daisies");
Console.WriteLine("4. Carnations");
Console.WriteLine("5. Live Plant");
Console.WriteLine("6. Mixed");
Console.Write("Your Choice: ");
type = int.Parse(Console.ReadLine());

Console.WriteLine("Enter the Color");


Console.WriteLine("1. Red");
Console.WriteLine("2. White");
Console.WriteLine("3. Yellow");
Console.WriteLine("4. Pink");
Console.WriteLine("5. Orange");
Console.WriteLine("6. Blue");
Console.WriteLine("7. Lavender");
Console.WriteLine("8. Mixed");
Console.Write("Your Choice: ");
color = int.Parse(Console.ReadLine());
C# 3.0 Practical Learning 194
Console.WriteLine("Enter the Type of Arrangement");
Console.WriteLine("1. Bouquet");
Console.WriteLine("2. Vase");
Console.WriteLine("3. Basket");
Console.WriteLine("4. Mixed");
Console.Write("Your Choice: ");
arrangement = int.Parse(Console.ReadLine());

Console.Write("Enter the Unit Price: ");


price = decimal.Parse(Console.ReadLine());

Console.Write("Enter Quantity: ");


qty = int.Parse(Console.ReadLine());

Flower flr = new Flower((FlowerType)type,


(FlowerColor)color,
(FlowerArrangement)arrangement,
price);
order.FlowerOrder = flr;
order.Quantity = qty;

return order;
}

private static void ShowFlowerOrder(OrderProcessing order)


{
Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");
Console.WriteLine("Flower Type: {0}",
order.FlowerOrder.Type);
Console.WriteLine("Flower Color: {0}",
order.FlowerOrder.Color);
Console.WriteLine("Arrangement: {0}",
order.FlowerOrder.Arrangement);
Console.WriteLine("Price: {0:C}",
order.FlowerOrder.UnitPrice);
Console.WriteLine("Quantity: {0}", order.Quantity);
Console.WriteLine("Total Price: {0:C}",
order.GetTotalPrice());
Console.WriteLine("=======================");
}

static void Main(string[] args)


{
OrderProcessing flower = CreateFlowerOrder();
Console.WriteLine();

ShowFlowerOrder(flower);
Console.WriteLine();
}
}
}

5. Execute the application and process an order. Here is an example:


 
=======================
==-=-=Flower Shop=-=-==
C# 3.0 Practical Learning 195
-----------------------
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 5
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 7
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 3
Enter the Unit Price: 35.95
Enter Quantity: 4

=======================
==-=-=Flower Shop=-=-==
-----------------------
Flower Type: LivePlant
Flower Color: Lavender
Arrangement: Basket
Price: $35.95
Quantity: 4
Total Price: $143.80
=======================

Press any key to continue . . .

6. Close the DOS window

Logical Operators
 

Introduction

A program is a series of instructions that ask the computer (actually the compiler) to
check some situations and to act accordingly. To check such situations, the computer
spends a great deal of its time performing comparisons between values. A comparison is a
Boolean operation that produces a true or a false result, depending on the values on
which the comparison is performed.

A comparison is performed between two values of the same type; for example, you can
compare two numbers, two characters, or the names of two cities. On the other hand, a
comparison between two disparate values doesn't bear any meaning. For example, it is
C# 3.0 Practical Learning 196
difficult to compare a telephone number and somebody's age, or a music category and the
distance between two points. Like the binary arithmetic operations, the comparison
operations are performed on two values. Unlike arithmetic operations where results are
varied, a comparison produces only one of two results. The result can be a logical true or
a logical false. When a comparison is true, it has an integral value of 1 or positive; that is,
a value greater than 0. If the comparison is not true, it is considered false and carries an
integral value of 0.

The C# language is equipped with various operators used to perform any type of
comparison between similar values. The values could be numeric, strings, or objects
(operations on objects are customized in a process referred to as Operator Overloading).

There are primary assumptions you should make when writing statements used in
conditions:

 Simplicity and Clarity: A statement should be clear enough and possibly simple but
as complete as possible. When a statement becomes long, it can lead to being
segmented in short parts, which deceives its clarity and may create other issues.

 Factual: The statement must be presented as fact and not as opinion. This means
that you don't have to like the statement but the majority, including you, must
agree that it is true or it is false. In fact, the statement doesn't have to be correct
but it must be agreed upon to be true. Based on this, a statement such as "An hour
contains 45 minutes" doesn't have to fit your way of thinking but it must be
considered as true or as false. A statement such as "This job applicant is attractive"
is an opinion and therefore must not be considered in a conditional statement.

 Circumstantial Truthfulness: At the time the statement is made, it must be


considered as true or as false even if it can change at another time. For example,
suppose that, in a certain year, a statement is formulated as "This year, the month
of February has 28 days". Although allowed, you should refrain from regularly using
circumstantial truthfulness, unless you have to.

 Inverse: A statement must be able to find its reverse. This means that, when a
statement is made and decided upon to be true or false, an inverse statement must
be found to make it false or true. For example, if you have a statement such as
"This job applicant is 18 years old", you must be able to state that "This job
applicant is not 18 years old" or "This job applicant is younger than 18".

In your programs, make sure you clearly formulate your statements. This would make
your programs easy to read and troubleshoot when problems occur (not if, but when).

The Equality Operator ==

To compare two variables for equality, C# uses the == operator. The formula used is:
Value1 == Value2

The equality operation is used to find out whether two variables (or one variable and a
constant) hold the same value. From our syntax, the compiler would compare the value of
Value1 with that of Value2. If Value1 and Value2 hold the same value, the comparison
produces a true result. If they are different, the comparison renders false.

C# 3.0 Practical Learning 197


Most of the comparisons performed in C# will be applied to conditional statements. The
result of a comparison can also be assigned to a variable. To store the result of a
comparison, you should include the comparison operation between parentheses. Here is
an example:
using System;

public class Exercise


{
static int Main()
{
var Value1 = 15;
var Value2 = 24;

Console.Write("Value 1 = ");
Console.WriteLine(Value1);
Console.Write("Value 2 = ");
Console.WriteLine(Value2);
Console.Write("Comparison of Value1 == 15 produces ");
Console.WriteLine(Value1 == 15);

return 0;
}
}

This would produce:


Value 1 = 15
Value 2 = 24
Comparison of Value1 == 15 produces True

It is important to make a distinction between the assignment "=" and the logical equality
operator "==". The first is used to give a new value to a variable, as in Number = 244.
The operand on the left side of = must always be a variable and never a constant. The
== operator is never used to assign a value; this would cause an error. The == operator
is used only to compare to values. The operands on both sides of == can be variables,
constants, or one can be a variable while the other is a constant. If you use one operator
in place of the other, you would receive an error when you compile the program.

The Logical Not Operator !

C# 3.0 Practical Learning 198


When a variable is declared and receives a value (this could be done through initialization
or a change of value) in a program, it becomes alive. It can then participate in any
necessary operation. The compiler keeps track of every variable that exists in the program
being processed. When a variable is not being used or is not available for processing (in
visual programming, it would be considered as disabled) to make a variable (temporarily)
unusable, you can nullify its value. C# considers that a variable whose value is null is
stern. To render a variable unavailable during the evolution of a program, apply the logical
not operator which is !. Its syntax is:
!Value

There are two main ways you can use the logical not operator. As we will learn when
studying conditional statements, the most classic way of using the logical not operator is
to check the state of a variable.

To nullify a variable, you can write the exclamation point to its left. Here is an example:
using System;

public class Exercise


{
static int Main()
{
bool HasAirCondition = true;
bool DoesIt;

Console.Write("HasAirCondition = ");
Console.WriteLine(HasAirCondition);
DoesIt = !HasAirCondition;
Console.Write("DoesIt = ");
Console.WriteLine(DoesIt);

return 0;
}
}

This would produce:


HasAirCondition = True
DoesIt = False

When a variable holds a value, it is "alive". To make it not available, you can "not" it.
When a variable has been "notted", its logical value has changed. If the logical value was
true, which is 1, it would be changed to false, which is 0. Therefore, you can inverse the
logical value of a variable by "notting" or not "notting" it.

The Inequality Operator !=

As opposed to Equality, C# provides another operator used to compare two values for
inequality. This operation uses a combination of equality and logical not operators. It
combines the logical not ! and a simplified == to produce !=. Its syntax is:
Value1 != Value2

The != is a binary operator (like all logical operator except the logical not, which is a unary
operator) that is used to compare two values. The values can come from two variables as
in Variable1 != Variable2. Upon comparing the values, if both variables hold different
C# 3.0 Practical Learning 199
values, the comparison produces a true or positive value. Otherwise, the comparison
renders false or a null value:

Here is an example:
using System;

public class Exercise


{
static int Main()
{
var Value1 = 212;
var Value2 = -46;
var Value3 = (Value1 != Value2);

Console.Write("Value1 = ");
Console.WriteLine(Value1);
Console.Write("Value2 = ");
Console.WriteLine(Value2);
Console.Write("Value3 = ");
Console.Write(Value3);
Console.WriteLine();

return 0;
}
}

The inequality is obviously the opposite of the equality.

The Comparison for a Lower Value <

To find out whether one value is lower than another, use the < operator. Its syntax is:
Value1 < Value2

The value held by Value1 is compared to that of Value2. As it would be done with other
operations, the comparison can be made between two variables, as in Variable1 <
Variable2. If the value held by Variable1 is lower than that of Variable2, the comparison
produces a true or positive result.

C# 3.0 Practical Learning 200


Here is an example:
using System;

public class Exercise


{
static int Main()
{
var Value1 = 15;
var Value2 = (Value1 < 24);

Console.Write("Value 1 = ");
Console.WriteLine(Value1);
Console.Write("Value 2 = ");
Console.WriteLine(Value2);
Console.WriteLine();

return 0;
}
}

This would produce:


Value 1 = 15
Value 2 = True

Combining Equality and Lower Value <=

The previous two operations can be combined to compare two values. This allows you to
know if two values are the same or if the first is less than the second. The operator used
is <= and its syntax is:
Value1 <= Value2

The <= operation performs a comparison as any of the last two. If both Value1 and
VBalue2 hold the same value, result is true or positive. If the left operand, in this case
Value1, holds a value lower than the second operand, in this case Value2, the result is still
true.

C# 3.0 Practical Learning 201


Here is an example:
using System;

public class Exercise


{
static int Main()
{
var Value1 = 15;
var Value2 = (Value1 <= 24);

Console.Write("Value 1 = ");
Console.WriteLine(Value1);
Console.Write("Value 2 = ");
Console.WriteLine(Value2);
Console.WriteLine();

return 0;
}
}

This would produce:


Value 1 = 15
Value 2 = True

The Comparison for a Greater Value >

When two values of the same type are distinct, one of them is usually higher than the
other. C# provides a logical operator that allows you to find out if one of two values is
greater than the other. The operator used for this operation uses the > symbol. Its syntax
is:
Value1 > Value2

Both operands, in this case Value1 and Value2, can be variables or the left operand can be
a variable while the right operand is a constant. If the value on the left of the > operator
is greater than the value on the right side or a constant, the comparison produces a true
or positive value . Otherwise, the comparison renders false or null:

C# 3.0 Practical Learning 202


 

The Greater Than or Equal Operator >=

The greater than or the equality operators can be combined to produce an operator as
follows: >=. This is the "greater than or equal to" operator. Its syntax is:
Value1 >= Value2

A comparison is performed on both operands: Value1 and Value2. If the value of Value1
and that of Value2 are the same, the comparison produces a true or positive value. If the
value of the left operand is greater than that of the right operand,, the comparison
produces true or positive also. If the value of the left operand is strictly less than the value
of the right operand, the comparison produces a false or null result:

Here is a summary table of the logical operators we have studied:


 

Operator Meaning Example Opposite

== Equality to a == b !=

C# 3.0 Practical Learning 203


!= Not equal to 12 != 7 ==

< Less than 25 < 84 >=

Less than or equal


<= Cab <= Tab >
to

> Greater than 248 > 55 <=

Greater than or
>= Val1 >= Val2 <
equal to

Logically Incrementing or Decrementing a Value


 

Incrementing a Variable

We are used to counting numbers such as 1, 2, 3, 4, etc. In reality, when counting such
numbers, we are simply adding 1 to a number in order to get the next number in the
range. The simplest technique of incrementing a value consists of adding 1 to it. After
adding 1, the value or the variable is (permanently) modified and the variable would hold
the new value. This is illustrated in the following example:
// This program studies value incrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of incrementing a value");


Console.Write("Value = ");
Console.WriteLine(Value);

Value = Value + 1;

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:

C# 3.0 Practical Learning 204


Techniques of incrementing a value
Value = 12
Value = 13

C# provides a special operator that takes care of this operation. The operator is called the
increment operator and is represented by ++. Instead of writing Value = Value + 1, you
can write Value++ and you would get the same result. The above program can be re-
written as follows:
// This program studies value incrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of incrementing a value");


Console.Write("Value = ");
Console.WriteLine(Value);

Value++;

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

The ++ is a unary operator because it operates on only one variable. It is used to modify
the value of the variable by adding 1 to it. Every time the Value++ is executed, the
compiler takes the previous value of the variable, adds 1 to it, and the variable holds the
incremented value:
// This program studies value incrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of incrementing a value");

Value++;
Console.Write("Value = ");
Console.WriteLine(Value);

Value++;
Console.Write("Value = ");
Console.WriteLine(Value);

Value++;
Console.Write("Value = ");
Console.WriteLine(Value);

C# 3.0 Practical Learning 205


return 0;
}
}

This would produce:


Techniques of incrementing a value
Value = 13
Value = 14
Value = 15

Pre and Post-Increment

When using the ++ operator, the position of the operator with regard to the variable it is
modifying can be significant. To increment the value of the variable before re-using it, you
should position the operator on the left of the variable:
// This program studies value incrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of incrementing a value");

Console.Write("Value = ");
Console.WriteLine(Value);

Console.Write("Value = ");
Console.WriteLine(++Value);

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:


Techniques of incrementing a value
Value = 12
Value = 13
Value = 13

When writing ++Value, the value of the variable is incremented before being called. On
the other hand, if you want to first use a variable, then increment it, in other words, if you
want to increment the variable after calling it, position the increment operator on the right
side of the variable:
// This program studies value incrementing
using System;

public class Exercise


{
static int Main()
C# 3.0 Practical Learning 206
{
var Value = 12;

Console.WriteLine("Techniques of incrementing a value");

Console.Write("Value = ");
Console.WriteLine(Value);

Console.Write("Value = ");
Console.WriteLine(Value++);

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:


Techniques of incrementing a value
Value = 12
Value = 12
Value = 13

Decrementing a Value

When counting numbers backward, such as 8, 7, 6, 5, etc, we are in fact subtracting 1


from a value in order to get the lesser value. This operation is referred to as decrementing
a value. This operation works as if a value is decremented by 1, as in Value = Value – 1:
// This program studies value decrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of decrementing a value");


Console.Write("Value = ");
Console.WriteLine(Value);

Value = Value - 1;

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:


Techniques of decrementing a value
Value = 12
Value = 11

C# 3.0 Practical Learning 207


As done to increment, C# provides a quicker way of subtracting 1 from a value. This is
done using the decrement operator, that is --. To use the decrement operator, type –- on
the left or the right side of the variable when this operation is desired. Using the
decrement operator, the above program could be written:
// This program studies value decrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of decrementing a value");


Console.Write("Value = ");
Console.WriteLine(Value);

Value--;

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

Pre Decrementing a Value

Once again, the position of the operator can be important. If you want to decrement the
variable before calling it, position the decrement operator on the left side of the operand.
This is illustrated in the following program:
// This program studies value decrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of decrementing a value");


Console.Write("Value = ");
Console.WriteLine(Value);

Console.Write("Value = ");
Console.WriteLine(--Value);

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:

C# 3.0 Practical Learning 208


Techniques of decrementing a value
Value = 12
Value = 11
Value = 11

If you plan to decrement a variable only after it has been accessed, position the operator
on the right side of the variable. Here is an example:
// This program studies value decrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12;

Console.WriteLine("Techniques of decrementing a value");


Console.Write("Value = ");
Console.WriteLine(Value);

Console.Write("Value = ");
Console.WriteLine(Value--);

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:


Techniques of decrementing a value
Value = 12
Value = 12
Value = 11

Techniques of Incrementing and Decrementing a Variable

It is not unusual to add or subtract a constant value to or from a variable. All you have to
do is to declare another variable that would hold the new value. Here is an example:
// This program studies value incrementing and decrementing
using System;

public class Exercise


{
static int Main()
{
double Value = 12.75;
double NewValue;

Console.WriteLine("Techniques of incrementing and decrementing a


value");
Console.Write("Value = ");
Console.WriteLine(Value);

NewValue = Value + 2.42;


C# 3.0 Practical Learning 209
Console.Write("Value = ");
Console.WriteLine(NewValue);

return 0;
}
}

This would produce:


Techniques of incrementing and decrementing a value
Value = 12.75
Value = 15.17

The above technique requires that you use an extra variable in your application. The
advantage is that each value can hold its own value although the value of the second
variable depends on whatever would happen to the original or source variable.

Sometimes in your program you will not need to keep the original value of the source
variable. You may want to permanently modify the value that a variable is holding. In this
case you can perform the addition operation directly on the variable by adding the desired
value to the variable. This operation modifies whatever value a variable is holding and
does not need an additional variable.

To add a value to a variable and change the value that the variable is holding, you can
combine the assignment “=” and the addition “+” operators to produce a new operator as
+=

Here is an example:
// This program studies value incrementing and decrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12.75;

Console.WriteLine("Techniques of incrementing and decrementing a


value");
Console.Write("Value = ");
Console.WriteLine(Value);

Value += 2.42;

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This program produces the same result as the previous. To decrement the value of a
variable, instead of the addition, use the subtraction and apply the same technique. In the
above program, the variable can have its value decremented by combining the assignment
and the subtraction operations on the variable. This is done with the -= operator. Here is
an example:

C# 3.0 Practical Learning 210


// This program studies value incrementing and decrementing
using System;

public class Exercise


{
static int Main()
{
var Value = 12.75;

Console.WriteLine("Techniques of incrementing and decrementing a


value");
Console.Write("Value = ");
Console.WriteLine(Value);

Value -= 2.42;

Console.Write("Value = ");
Console.WriteLine(Value);

return 0;
}
}

This would produce:


Techniques of incrementing and decrementing a value
Value = 12.75
Value = 10.33

C# 3.0 Practical Learning 211


CONDITIONAL STATEMENTS
 

if a Condition is True
 

Introduction

A conditional statement is an expression that produces a true or false result. You can use
that result as you see fit. To create the expression, you use the Boolean operators we
studied in the previous lesson. In the previous lesson, we saw only how to perform the
operations and how to get the results, not how to use them. To use the result of a
Boolean operation, the C# programming language provides some specific conditional
operators.

Practical Learning: Introducing Conditional Expressions

1. Start Microsoft Visual C# and create a Console Application named


ElectronicStore2

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name of the class to StoreItem and click Add

4. Complete the StoreItem.cs file as follows:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElectronicStore2
{
public enum ItemsCategories
{
Unknown,
CablesAndConnectors,
CellPhonesAndAccessories,
Headphones,
DigitalCameras,
PDAsAndAccessories,
TelephonesAndAccessories,
TVsAndVideos,
SurgeProtectors,
Instructional
}

C# 3.0 Practical Learning 212


public class StoreItem
{
public long ItemNumber;
public ItemsCategories Category;
public string Make;
public string Model;
public string Name;
public double UnitPrice;

// An item whose characteristics are not (yet) defined


public StoreItem()
{
ItemNumber = 0;
Category = ItemsCategories.Unknown;
Make = "Unknown";
Model = "Unspecified";
Name = "N/A";
UnitPrice = 0.00D;
}
// An item that is known by its make, model, and unit price
public StoreItem(long itmNbr, String make,
String model, double price)
{
ItemNumber = itmNbr;
Category = ItemsCategories.Unknown;
Make = make;
Model = model;
Name = "N/A";
UnitPrice = price;
}
// An item that is known by its name and unit price
public StoreItem(long itmNbr, String name, double price)
{
ItemNumber = itmNbr;
Category = ItemsCategories.Unknown;
Make = "Unknown";
Model = "Unspecified";
Name = name;
UnitPrice = price;
}
// An item completely defined
public StoreItem(long itmNbr, ItemsCategories category,
String make, String model, double price)
{
ItemNumber = itmNbr;
Category = category;
Make = make;
Model = model;
UnitPrice = price;
}
}
}

5. Save the file

if

Consider the following program:

C# 3.0 Practical Learning 213


using System;

public enum HouseType


{
Unknown,
SingleFamily,
TownHouse,

Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;

Console.WriteLine("Enter the type of house you want to


purchase");

Console.WriteLine("1. Single Family");

Console.WriteLine("2. Townhouse");

Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

Console.WriteLine("\nDesired House Type: {0}", type);


return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. TownHouse
3. Condominium
You Choice? 3

Desired House Type: Unknown


Press any key to continue . . .

C# 3.0 Practical Learning 214


To check if an expression is true and use its Boolean result, you can use the if operator.
Its formula is:
if(Condition) Statement;

The Condition can be the type of Boolean operation we studied in the previous lesson.
That is, it can have the following formula:
Operand1 BooleanOperator Operand2

If the Condition produces a true result, then the compiler executes the Statement. If the
statement to execute is short, you can write it on the same line with the condition that is
being checked. Here is an example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
TownHouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1) type = HouseType.SingleFamily;

Console.WriteLine("\nDesired House Type: {0}", type);


return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1

Desired House Type: SingleFamily


Press any key to continue . . .

If the Statement is too long, you can write it on a different line than the if condition.
Here is an example:

C# 3.0 Practical Learning 215


using System;

public enum HouseType


{
Unknown,
SingleFamily,
TownHouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;

Console.WriteLine("\nDesired House Type: {0}", type);


return 0;
}
}

You can also write the Statement on its own line even if the statement is short enough to
fit on the same line with the Condition.

Although the (simple) if statement is used to check one condition, it can lead to
executing multiple dependent statements. If that is the case, enclose the group of
statements between an opening curly bracket “{“ and a closing curly bracket “}”. Here is
an example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
TownHouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;

C# 3.0 Practical Learning 216


Console.WriteLine("Enter the type of house you want to
purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
{
type = HouseType.SingleFamily;
Console.WriteLine("\nDesired House Type: {0}", type);
}
return 0;
}
}

If you omit the brackets, only the statement that immediately follows the condition would
be executed.

Just as you can write one if condition, you can write more than one. Here are examples:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.WriteLine("\nDesired House Type: {0}", type);


return 0;
}
}

Here is an example of running the program:


C# 3.0 Practical Learning 217
Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 3

Desired House Type: Condominium


Press any key to continue . . .

Practical Learning: Using the Simple if Condition

1. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElectronicStore2
{
public class Program
{
private static StoreItem CreateStoreItem()
{
StoreItem sItem = new StoreItem();
int Category;

Console.WriteLine(
"To create a store item, enter its information");
Console.Write("Item Number: ");
sItem.ItemNumber = long.Parse(Console.ReadLine());
Console.WriteLine("Category");
Console.WriteLine("1. Unknown/Miscellaneous");
Console.WriteLine("2. Cables and Connectors");
Console.WriteLine("3. Cell Phones and Accessories");
Console.WriteLine("4. Headphones");
Console.WriteLine("5. Digital Cameras");
Console.WriteLine("6. PDAs and Accessories");
Console.WriteLine("7. Telephones and Accessories");
Console.WriteLine("8. TVs and Videos - Plasma / LCD");
Console.WriteLine("9. Surge Protector");
Console.WriteLine(
"10. Instructional and Tutorials (VHS & DVD)TVs and
Videos");
Console.Write("Your Choice? ");
category = int.Parse(Console.ReadLine());

if (Category == 1)
sItem.Category = ItemsCategories.Unknown;
if (Category == 2)
sItem.Category = ItemsCategories.CablesAndConnectors;
if (Category == 3)
sItem.Category =
ItemsCategories.CellPhonesAndAccessories;
if (Category == 4)
sItem.Category = ItemsCategories.Headphones;
if (Category == 5)
sItem.Category = ItemsCategories.DigitalCameras;
C# 3.0 Practical Learning 218
if (Category == 6)
sItem.Category = ItemsCategories.PDAsAndAccessories;
if (Category == 7)
sItem.Category =
ItemsCategories.TelephonesAndAccessories;
if (Category == 8)
sItem.Category = ItemsCategories.TVsAndVideos;
if (Category == 9)
sItem.Category = ItemsCategories.SurgeProtectors;
if (Category == 10)
sItem.Category = ItemsCategories.Instructional;

Console.Write("Make: ");
sItem.Make = Console.ReadLine();
Console.Write("Model: ");
sItem.Model = Console.ReadLine();
Console.Write("Unit Price: ");
sItem.UnitPrice = decimal.Parse(Console.ReadLine());

return sItem;
}

static void DescribeStoreItem(StoreItem item)


{
Console.WriteLine("Store Item Description");
Console.WriteLine("Item Number: {0}", item.ItemNumber);
Console.WriteLine("Category: {0}", item.Category);
Console.WriteLine("Make: {0}", item.Make);
Console.WriteLine("Model: {0}", item.Model);
Console.WriteLine("Unit Price: {0:C}", item.UnitPrice);
}

static void Main()


{
string strTitle1 = "=-= Nearson Electonics =-=";
string strTitle2 = "******* Store Items ******";

StoreItem saleItem = CreateStoreItem();

Console.WriteLine("");
DescribeStoreItem(saleItem);
}
}
}

2. Execute the application to see the result. Here is an example:

To create a store item, enter its information


Item Number: 868264
Category
C# 3.0 Practical Learning 219
1. Unknown/Miscellaneous
2. Cables and Connectors
3. Cell Phones and Accessories
4. Headphones
5. Digital Cameras
6. PDAs and Accessories
7. Telephones and Accessories
8. TVs and Videos - Plasma / LCD
9. Surge Protector
10. Instructional and Tutorials (VHS & DVD)TVs and Videos
Your Choice? 1
Make: Altec Lansing
Model: VS4221 Computer Speakers
Unit Price: 85.95

Store Item Description


Item Number: 868264
Category: Unknown
Make: Altec Lansing
Model: VS4221 Computer Speakers
Unit Price: $85.95
Press any key to continue . . .

3. Close the DOS window

if…else

Here is an example of what we learned in the previous section:

using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;
C# 3.0 Practical Learning 220
Console.WriteLine("Enter the type of house you want to
purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.WriteLine("\nDesired House Type: {0}", type);

if (type == HouseType.SingleFamily)
Console.WriteLine("\nDesired House Matched");

return 0;
}
}

If you use an if condition to perform an operation and if the result is true, we saw that
you could execute the statement. As we saw in the previous section, any other result
would be ignored. To address an alternative to an if condition, you can use the else
condition. The formula to follow is:
if(Condition)
Statement1;
else
Statement2;

Once again, the Condition can be a Boolean operation like those we studied in the
previous lesson. If the Condition is true, then the compiler would execute Statement1. If
the Condition is false, then the compiler would execute Statement2. Here is an example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Program


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");

C# 3.0 Practical Learning 221


Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.WriteLine("\nDesired House Type: {0}", type);

if (type == HouseType.SingleFamily)
Console.WriteLine("Desired House Matched");
else
Console.WriteLine("No House Desired");

return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1

Desired House Type: SingleFamily


Desired House Matched
Press any key to continue . . .

Here is another example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 2

Desired House Type: Townhouse


No House Desired
Press any key to continue . . .

Practical Learning: Using the if...else Condition

1. Access the Program.cs file and, to use the if...else condition, change the file as
follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElectronicStore2
C# 3.0 Practical Learning 222
{
class Program
{
static StoreItem CreateStoreItem()
{
StoreItem sItem = new StoreItem();
int Category;
double ItemPrice = 0D;

Console.WriteLine(
"To create a store item, enter its information");
Console.Write("Item Number: ");
sItem.ItemNumber = long.Parse(Console.ReadLine());
Console.WriteLine("Category");
Console.WriteLine("1. Unknown/Miscellaneous");
Console.WriteLine("2. Cables and Connectors");
Console.WriteLine("3. Cell Phones and Accessories");
Console.WriteLine("4. Headphones");
Console.WriteLine("5. Digital Cameras");
Console.WriteLine("6. PDAs and Accessories");
Console.WriteLine("7. Telephones and Accessories");
Console.WriteLine("8. TVs and Videos - Plasma / LCD");
Console.WriteLine("9. Surge Protector");
Console.WriteLine(
"10. Instructional and Tutorials (VHS & DVD)TVs and
Videos");
Console.Write("Your Choice? ");
Category = int.Parse(Console.ReadLine());

if (Category == 1)
sItem.Category = ItemsCategories.Unknown;
if (Category == 2)
sItem.Category = ItemsCategories.CablesAndConnectors;
if (Category == 3)
sItem.Category =
ItemsCategories.CellPhonesAndAccessories;
if (Category == 4)
sItem.Category = ItemsCategories.Headphones;
if (Category == 5)
sItem.Category = ItemsCategories.DigitalCameras;
if (Category == 6)
sItem.Category = ItemsCategories.PDAsAndAccessories;
if (Category == 7)
sItem.Category =
ItemsCategories.TelephonesAndAccessories;
if (Category == 8)
sItem.Category = ItemsCategories.TVsAndVideos;
if (Category == 9)
sItem.Category = ItemsCategories.SurgeProtectors;
if (Category == 10)
sItem.Category = ItemsCategories.Instructional;

Console.Write("Make: ");
sItem.Make = Console.ReadLine();
Console.Write("Model: ");
sItem.Model = Console.ReadLine();
Console.Write("Unit Price: ");
ItemPrice = double.Parse(Console.ReadLine());
if( ItemPrice <= 0 )
sItem.UnitPrice = 0.00D;
C# 3.0 Practical Learning 223
else
sItem.UnitPrice = ItemPrice;

return sItem;
}

static string GetItemCategory(ItemsCategories cat)


{
string strCategory = "Unknown";

if (cat == ItemsCategories.CablesAndConnectors)
strCategory = "Cables & Connectors";
if (cat == ItemsCategories.CellPhonesAndAccessories)
strCategory = "Cell Phones & Accessories";
if (cat == ItemsCategories.Headphones)
strCategory = "Headphones";
if (cat == ItemsCategories.DigitalCameras)
strCategory = "Digital Cameras";
if (cat == ItemsCategories.PDAsAndAccessories)
strCategory = "PDAs & Accessories";
if (cat == ItemsCategories.TelephonesAndAccessories)
strCategory = "Telephones & Accessories";
if (cat == ItemsCategories.TVsAndVideos)
strCategory = "TVs & Videos";
if (cat == ItemsCategories.SurgeProtectors)
strCategory = "Surge Protectors";
if (cat == ItemsCategories.Instructional)
strCategory = "Instructional";

return strCategory;
}

static void DescribeStoreItem(StoreItem item)


{
string strCategory = GetItemCategory(item.Category);

Console.WriteLine("Store Item Description");


Console.WriteLine("Item Number: {0}", item.ItemNumber);
Console.WriteLine("Category: {0}", strCategory);
Console.WriteLine("Make {0}", item.Make);
Console.WriteLine("Model: {0}", item.Model);
Console.WriteLine("Unit Price: {0:C}", item.UnitPrice);
}

static void Main()


{
string strTitle1 = "=-= Nearson Electronics =-=";
string strTitle2 = "******* Store Items ******";

Console.WriteLine(strTitle1);
Console.WriteLine(strTitle2);
StoreItem saleItem = CreateStoreItem();
Console.WriteLine("");

Console.WriteLine(strTitle1);
Console.WriteLine(strTitle2);
DescribeStoreItem(saleItem);
Console.WriteLine("");
}
}
C# 3.0 Practical Learning 224
}

2. Execute the application to test it. Here is an example:

 
=-= Nearson Electronics =-=
******* Store Items ******
To create a store item, enter its information
Item Number: 937494
Category
1. Unknown/Miscellaneous
2. Cables and Connectors
3. Cell Phones and Accessories
4. Headphones
5. Digital Cameras
6. PDAs and Accessories
7. Telephones and Accessories
8. TVs and Videos - Plasma / LCD
9. Surge Protector
10. Instructional and Tutorials (VHS & DVD)TVs and Videos
Your Choice? 5
Make: Canon
Model: EOS 30D
Unit Price: 1395.95

=-= Nearson Electronics =-=


******* Store Items ******
Store Item Description
Item Number: 937494
Category: Digital Cameras
Make Canon
Model: EOS 30D
Unit Price: $1,395.95

Press any key to continue . . .

3. Close the DOS window

Logical Conjunction: AND


 

Introduction

C# 3.0 Practical Learning 225


Imagine that a real estate agent who will be using your program is meeting with a
potential buyer and asking questions from the following program:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Program


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;
var value = 0D;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.Write("Up to how much can you afford? $");


value = double.Parse(Console.ReadLine());

Console.WriteLine("\nDesired House Type: {0}", type);


Console.WriteLine("Maximum value afforded: {0:C}\n", value);

return 0;
}
}

Suppose a customer responds to these questions: she indicates that she wants single
family house but she cannot afford more than $550,000:
Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Up to how much can you afford? $550000

Desired House Type: SingleFamily


Maximum value afforded: $550,000.00

Press any key to continue . . .


C# 3.0 Practical Learning 226
When considering a house for this customer, there are two details to be validated here:
the house must be a single family home, second, it must cost less than $550,001. We
can create two statements as follows:

1. The house is single family

2. The house costs less than $550,000


From our list of real estate properties, if we find a house that is a single family home, we put
it in our list of considered properties:

Type of House House

The house is single


True
family

On the other hand, if we find a house that is less than or equal to $550,000, we retain it:

Price Range Value

$550,000 True

One of the ways you can combine two comparisons is by joining them. For our customer, we
want a house to meet BOTH criteria. If the house is a town house, based on the request of
our customer, its conditional value is false. If the house is more than $550,000, the value of
the Boolean Value is true. The Boolean operator used to join two criteria is called AND. This
can be illustrated as follows:

Type of House House Value Result

Town House $625,000 Town House AND $625,000

False False False

In C#, the Boolean AND operator is performed using the && operator. Here is an
example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{

C# 3.0 Practical Learning 227


static int Main()
{
var type = HouseType.Unknown;
var choice = 0;
var value = 0D;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

Console.Write("Up to how much can you afford? $");


value = double.Parse(Console.ReadLine());

if(choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;
Console.WriteLine("\nDesired House Type: {0}", type);
Console.WriteLine("Maximum value afforded: {0:C}", value);

if (type == HouseType.SingleFamily && value <= 550000)


Console.WriteLine("\nDesired House Matched");
return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Up to how much can you afford? $450000

Desired House Type: SingleFamily


Maximum value afforded: $450,000.00

Desired House Matched


Press any key to continue . . .

By definition, a logical conjunction combines two conditions. To make the program


easier to read, each side of the conditions can be included in parentheses. Here is an
example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}
C# 3.0 Practical Learning 228
public class Exercise
{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;
var value = 0D;

. . .

if( (type == HouseType.SingleFamily) && (value <= 550000) )


Console.WriteLine("\nDesired House Matched");
return 0;
}
}

Suppose we find a single family home. The first condition is true for our customer. With the
AND Boolean operator, if the first condition is true, then we consider the second criterion.
Suppose that the house we are considering costs $750,500: the price is out of the
customer's range. Therefore, the second condition is false. In the AND Boolean algebra, if
the second condition is false, even if the first is true, the whole condition is false. This would
produce the following table:

Type of House House Value Result

Single Family $750,500 Single Family AND $750,500

True False False

This can be illustrated by the following run of the program:


using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

class Program
{
static void Main()
{
var type = HouseType.Unknown;
int choice;
var value = 0M;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
C# 3.0 Practical Learning 229
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.Write("Up to how much can you afford? $");


value = decimal.Parse(Console.ReadLine());

Console.WriteLine("\nDesired House Type: {0}", type);


Console.WriteLine("Maximum value afforded: {0:C}", value);

if (type == HouseType.SingleFamily && value <= 550000)


Console.WriteLine("\nDesired House Matched");
else
Console.WriteLine("\nThe House Doesn't Match the Desired
Criteria");
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Up to how much can you afford? $750000

Desired House Type: SingleFamily


Maximum value afforded: $750,000.00

The House Doesn't Match the Desired Criteria


Press any key to continue . . .

Suppose we find a townhouse that costs $420,000. Although the second condition is true,
the first is false. In Boolean algebra, an AND operation is false if either condition is false:

Type of House House Value Result

Town House $420,000 Town House AND $420,000

False True False

Here is an example of running the above program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 2
Up to how much can you afford? $420000

C# 3.0 Practical Learning 230


Desired House Type: Townhouse
Maximum value afforded: $420,000.00

The House Doesn't Match the Desired Criteria


Press any key to continue . . .

If we find a single family home that costs $345,000, both conditions are true. In Boolean
algebra, an AND operation is true if BOTH conditions are true. This can be illustrated as
follows:

Type of House House Value Result

Single Family $345,000 Single Family AND $345,000

True True True

This can be revealed in the following run of the above program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Up to how much can you afford? $345000

Desired House Type: SingleFamily


Maximum value afforded: $345,000.00

Desired House Matched


Press any key to continue . . .

These four tables can be resumed as follows:

Condition1
If Condition1 If Condition2
AND
is is
Condition2

False False False

False True False

True False False

True True True

As you can see, a logical conjunction is true only of BOTH conditions are true.

Combining Conjunctions

C# 3.0 Practical Learning 231


As seen above, the logical conjunction operator is used to combine two conditions. In
some cases, you will need to combine more than two conditions. Imagine a customer
wants to purchase a single family house that costs up to $450,000 with an indoor
garage. This means that the house must fulfill these three requirements:

A. The house is a single family home

B. The house costs less than $450,001

C. The house has an indoor garage

Here the program that could be used to check these conditions:


using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;
var value = 0D;
var hasIndoorGarage = false;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.Write("Up to how much can you afford? $");


value = double.Parse(Console.ReadLine());

Console.Write("Does the house have an indoor garage (1=Yes/0=No)?


");
int ans = int.Parse(Console.ReadLine());

Console.WriteLine("\nDesired House Type: {0}", type);


Console.WriteLine("Maximum value afforded: {0:C}", value);
Console.Write("House has indoor garage: ");
if (ans == 1)
Console.WriteLine("Yes");

C# 3.0 Practical Learning 232


else
Console.WriteLine("No");

if ((type == HouseType.SingleFamily) && (value <= 550000) && (ans


== 1))
Console.WriteLine("\nDesired House Matched");
else
Console.WriteLine("\nThe House Doesn't Match the Desired
Criteria");

return 0;
}
}

We saw that when two conditions are combined, the compiler first checks the first condition,
followed by the second. In the same way, if three conditions need to be considered, the
compiler evaluates the truthfulness of the first condition:

Type of House

Town House

False

If the first condition (or any condition) is false, the whole condition is false, regardless of the
outcome of the other(s). If the first condition is true, then the second condition is evaluated
for its truthfulness:

Type of House Property Value

A B

Single Family $655,000

True False

If the second condition is false, the whole combination is considered false:

A B A && B

True False False

When evaluating three conditions, if either the first or the second is false, since the whole
condition would become false, there is no reason to evaluate the third. If both the first and

C# 3.0 Practical Learning 233


the second conditions are false, there is also no reason to evaluate the third condition. Only
if the first two conditions are true will the third condition be evaluated whether it is true:

Property Indoor
Type of House
Value Garage

A B C

Single Family $425,650 None

True True False

The combination of these conditions in a logical conjunction can be written as A && B


&& C. If the third condition is false, the whole combination is considered false:

A B A && B C A && B && C

True True True False False

To verify this, here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Up to how much can you afford? $425000
Does the house have an indoor garage (1=Yes/0=No)? 0

Desired House Type: SingleFamily


Maximum value afforded: $425,000.00
House has indoor garage: No

The House Doesn't Match the Desired Criteria


Press any key to continue . . .

From our discussion so far, the truth table of the combinations can be illustrated as follows:

A B C A && B && C

False Don't Care Don't Care False


True False Don't Care False
True True False False

The whole combination is true only if all three conditions are true. This can be illustrated as
follows:

C# 3.0 Practical Learning 234


A B C A && B && C

False False False False


False False True False
True False False False
True False True False
False True False False
False True True False
True True False False
True True True True

Logical Disjunction: OR
 

Introduction

Our real estate company has single family homes, townhouses, and condominiums. All
of the condos have only one level, also referred to as a story. Some of the single family
homes have one story, some have two and some others have three levels. All
townhouses have three levels.

Another customer wants to buy a home. The customer says that he primarily wants a
condo, but if our real estate company doesn't have a condominium, that is, if the
company has only houses, whatever it is, whether a house or a condo, it must have only
one level (story) (due to an illness, the customer would not climb the stairs). When
considering the properties of our company, we would proceed with these statements:

1. The property is a condominium

2. The property has one story


If we find a condo, since all of our condos have only one level, the criterion set by the
customer is true. Even if we were considering another (type of) property, it wouldn't matter.
This can be resumed in the following table:

Type of House House

Condominium True

The other properties would not be considered, especially if they have more than one story:

Number of Stories Value

3 False
C# 3.0 Practical Learning 235
To check for either of two conditions, in Boolean algebra, you can use an operator called OR.
We can show this operation as follows:

Condominium One Story Condominium OR 1 Story

True False True

In Boolean algebra, this type of comparison is performed using the OR operator. In C#,
the OR operator is performed using the || operator. Here is an example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
static int Main()
{
var type = HouseType.Unknown;
var choice = 0;
var stories = 1;

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
choice = int.Parse(Console.ReadLine());

if (choice == 1)
type = HouseType.SingleFamily;
if (choice == 2)
type = HouseType.Townhouse;
if (choice == 3)
type = HouseType.Condominium;

Console.Write("How many stories? ");


stories = int.Parse(Console.ReadLine());

Console.WriteLine("\nDesired House Type: {0}", type);


Console.WriteLine("Number of Stories: {0}", stories);

if ((type == HouseType.Condominium) || (stories == 1))


Console.WriteLine("\nDesired House Matched");
else
Console.WriteLine("\nThe House Doesn't Match the Desired
Criteria");

return 0;
}
}
C# 3.0 Practical Learning 236
Here is an example of running the program:
Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 3
How many stories? 6

Desired House Type: Condominium


Number of Stories: 6

Desired House Matched


Press any key to continue . . .

Suppose that, among the properties our real estate company has available, there is no
condominium. In this case, we would then consider the other properties:

Type of House House

Single Family False

If we have a few single family homes, we would look for one that has only one story. Once
we find one, our second criterion becomes true:

Type of
One Story Condominium OR 1 Story
House

False True True

This can be illustrated in the following run of the above program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
How many stories? 1

Desired House Type: SingleFamily


Number of Stories: 1

Desired House Matched


Press any key to continue . . .

If we find a condo and it is one story, both criteria are true. This can be illustrated in the
following table:

Type of
One Story Condominium OR 1 Story
House

False True True

C# 3.0 Practical Learning 237


True True True

The following run of the program demonstrates this:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 3
How many stories? 1

Desired House Type: Condominium


Number of Stories: 1

Desired House Matched


Press any key to continue . . .

A Boolean OR operation produces a false result only if BOTH conditions ARE FALSE:

If Condition1 If Condition2 Condition1 OR


is is Condition2

False True True


True False True
True True True
False False False

Here is another example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 2
How many stories? 2

Desired House Type: Townhouse


Number of Stories: 2

The House Doesn't Match the Desired Criteria


Press any key to continue . . .

Combinations of Disjunctions

As opposed to evaluating only two conditions, you may face a situation that presents
three of them and must consider a combination of more than two conditions. 

C# 3.0 Practical Learning 238


CONDITIONAL SWITCHES
 

if Switches
 

The Ternary Operator (?:)

The conditional operator behaves like a simple if…else statement. Its syntax is:
Condition ? Statement1 : Statement2;

The compiler would first test the Condition. If the Condition is true, then it would
execute Statement1, otherwise it would execute Statement2. When you request two
numbers from the user and would like to compare them, the following program would
do find out which one of both numbers is higher. The comparison is performed using the
conditional operator:

using System;

public class Exercise


{
static int Main()
{
var Number1 = 0;
var Number2 = 0;
var Maximum = 0;
var Num1 = "";
var Num2 = "";

Console.Write("Enter first numbers: ");


Num1 = Console.ReadLine();
Console.Write("Enter second numbers: ");
Num2 = Console.ReadLine();

Number1 = int.Parse(Num1);
Number2 = int.Parse(Num2);

Maximum = (Number1 < Number2) ? Number2 : Number1;

Console.Write("\nThe maximum of ");


Console.Write(Number1);
Console.Write(" and ");
Console.Write(Number2);
Console.Write(" is ");
Console.WriteLine(Maximum);

Console.WriteLine();
return 0;
C# 3.0 Practical Learning 239
}
}

Here is an example of running the program;


Enter first numbers: 244
Enter second numbers: 68

The maximum of 244 and 68 is 244

Practical Learning: Introducing Conditional Switches

1. Start Microsoft Visual C#

2. Create a new Console Application named FlowerShop2

3. To create a new class, on the main menu, click Project -> Add Class...

4. Set the Name of the class to Flower and click Add

5. Complete the Flower.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop2
{
public enum FlowerType
{
Roses = 1,
Lilies,
Daisies,
Carnations,
LivePlant,
Mixed
}

public enum FlowerColor


{
Red = 1,
White,
Yellow,
Pink,
Orange,
Blue,
Lavender,
Mixed
}

public enum FlowerArrangement


{
Bouquet = 1,
Vase,
Basket,
Any
}
C# 3.0 Practical Learning 240
public class Flower
{
public FlowerType Type;
public FlowerColor Color;
public FlowerArrangement Arrangement;
public decimal UnitPrice;

public Flower()
{
Type = FlowerType.Mixed;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
UnitPrice = 0.00M;
}
public Flower(FlowerType type)
{
Type = type;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
UnitPrice = 0.00M;
}
public Flower(FlowerType type, FlowerColor color,
FlowerArrangement argn, decimal price)
{
Type = type;
Color = color;
Arrangement = argn;
UnitPrice = price;
}
}
}

6. Save the file

if…else if and if…else if…else

If you use an if...else conditional statement, you can


process only two statements. In some cases, you may deal
with more than two conditions. In this case, you can use an
if...else if condition. Its formula is:

if(Condition1) Statement1;
else if(Condition2) Statement2;

The compiler would first check Condition1. If Condition1 is


true, then Statement1 would be executed. If Condition1 is
false, then the compiler would check Condition2. If
Condition2 is true, then the compiler would execute
Statement2. Any other result would be ignored. Here is an
example:
using System;

public enum HouseType


{
Unknown,

C# 3.0 Practical Learning 241


SingleFamily,
Townhouse,

Condominium
}

public class Exercise


{
static int Main()
{
var Type = HouseType.Unknown;
var Choice = 0;
var Garage = "";

Console.WriteLine("Enter the type of house you want to


purchase");

Console.WriteLine("1. Single Family");

Console.WriteLine("2. Townhouse");

Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

if (Choice == 1) Type = HouseType.SingleFamily;


else if (Choice == 2) Type = HouseType.Townhouse;

Console.Write("Does the house have an indoor garage (1=Yes/0=No)?


");
var Answer = int.Parse(Console.ReadLine());
if (Answer == 1)
Garage = "Yes";
else
Garage = "No";

Console.WriteLine("\nDesired House Type: {0}", Type);


Console.WriteLine("Has indoor garage? {0}", Garage);
return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Does the house have an indoor garage (1=Yes/0=No)? 1

Desired House Type: SingleFamily


Has indoor garage? Yes
Press any key to continue . . .

Here is another example of running the program:


Enter the type of house you want to purchase
1. Single Family
C# 3.0 Practical Learning 242
2. Townhouse
3. Condominium
You Choice? 2
Does the house have an indoor garage (1=Yes/0=No)? 6

Desired House Type: Townhouse


Has indoor garage? No
Press any key to continue . . .

Notice that only two conditions are evaluated. Any condition other than these two is not
considered. Because there can be other alternatives, the C# language provides an
alternate else as the last resort. Its formula is:
if(Condition1) if(Condition1)
    Statement1;     Statement1;
else if(Condition2) else if(Condition2)
    Statement2;     Statement2;
else else if(Condition3)
    Statement-n;     Statement3;
else
    Statement-n;

The compiler will check the first condition. If Condition1 is true, it executes Statement1.
If Condition1 is false, then the compiler will check the second condition. If Condition2 is
true, it will execute Statement2. When the compiler finds a Condition-n to be true, it will
execute its corresponding statement. It that Condition-n is false, the compiler will check
the subsequent condition. This means you can include as many conditions as you see fit
using the else if statement. If after examining all the known possible conditions you
still think that there might be an unexpected condition, you can use the optional single
else. Here is an example:

using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
public static int Main()
{
var Type = HouseType.Unknown;
var Choice = 0;
var Garage = "";

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

if (Choice == 1)
Type = HouseType.SingleFamily;
C# 3.0 Practical Learning 243
else if (Choice == 2)
Type = HouseType.Townhouse;
else if (Choice == 3)
Type = HouseType.Condominium;
else
Type = HouseType.Unknown;

Console.Write("Does the house have an indoor garage (1=Yes/0=No)?


");
var Answer = int.Parse(Console.ReadLine());
if (Answer == 1)
Garage = "Yes";
else
Garage = "No";

Console.WriteLine("\nDesired House Type: {0}", Type);


Console.WriteLine("Has indoor garage? {0}", Garage);

return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 3
Does the house have an indoor garage (1=Yes/0=No)? 0

Desired House Type: Condominium


Has indoor garage? No
Press any key to continue . . .

Case Switches
 

Introduction

When defining an expression whose result would lead to a specific program execution,
the switch statement considers that result and executes a statement based on the
possible outcome of that expression, this possible outcome is called a case. The different
outcomes are listed in the body of the switch statement and each case has its own
execution, if necessary. The body of a switch statement is delimited from an opening to
a closing curly brackets: “{“ to “}”. The syntax of the switch statement is:
switch(Expression)
{
    case Choice1:
        Statement1;
break;
    case Choice2:
        Statement2;
break;
    case Choice-n:
        Statement-n;

C# 3.0 Practical Learning 244


break;
}

In C++, you can omit the break keyword in a case. This creates the "fall through"
effect as follows: after code executes in a case, if nothing "stops" it, the execution
continues to the next case. This has caused problems and confusing execution in
the past in some C++ programs. To avoid it, C# requires code interruption at the
end of every case. This interruption is done using the break keyword.

The expression to examine in a case statement is an integer. Since a member of an


enumerator (enum) and the character (char) data types are just other forms of integers,
they can be used too. Here is an example of using the switch statement:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
public static int Main()
{
var Type = HouseType.Unknown;
var Choice = 0;
var Garage = "";

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

switch (Choice)
{
case 1:
Type = HouseType.SingleFamily;
break;

case 2:
Type = HouseType.Townhouse;
break;

case 3:
Type = HouseType.Condominium;
break;
}

Console.Write("Does the house have an indoor garage (1=Yes/0=No)?


");
var Answer = int.Parse(Console.ReadLine());
if (Answer == 1)
C# 3.0 Practical Learning 245
Garage = "Yes";
else
Garage = "No";

Console.WriteLine("\nDesired House Type: {0}", Type);


Console.WriteLine("Has indoor garage? {0}", Garage);

return 0;
}
}

When establishing the possible outcomes that the switch statement should consider, at
times there will be possibilities other than those listed and you will be likely to consider
them. This special case is handled by the default keyword. The default case would
be considered if none of the listed cases matches the supplied answer. The syntax of the
switch statement that considers the default case would be:

switch(Expression)
{
    case Choice1:
        Statement1;
break;
    case Choice2:
        Statement2;
break;
    case Choice-n:
        Statement-n;
break;
    default:
        Other-Possibility;
break;
}

In C++, the default section doesn't need a break keyword because it is the
last. In C#, every case and the default section must have its own exit
mechanism, which is taken care of by a break keyword.

Therefore another version of the program above would be


using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
public static int Main()
{
var Type = HouseType.Unknown;
var Choice = 0;
var Garage = "";

C# 3.0 Practical Learning 246


Console.WriteLine("Enter the type of house you want to
purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

switch (Choice)
{
case 1:
Type = HouseType.SingleFamily;
break;

case 2:
Type = HouseType.Townhouse;
break;

case 3:
Type = HouseType.Condominium;
break;

default:
Type = HouseType.Unknown;
break;
}

Console.Write("Does the house have an indoor garage (1=Yes/0=No)?


");
var Answer = int.Parse(Console.ReadLine());
if (Answer == 1)
Garage = "Yes";
else
Garage = "No";

Console.WriteLine("\nDesired House Type: {0}", Type);


Console.WriteLine("Has indoor garage? {0}", Garage);

return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 8
Does the house have an indoor garage (1=Yes/0=No)? 2

Desired House Type: Unknown


Has indoor garage? No
Press any key to continue . . .

Besides a value of an int type, you can also use another variant of integers on a
switch statement. For example, you can use letters to validate the cases. Here is an
example:
using System;
C# 3.0 Practical Learning 247
public enum HouseType
{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
public static int Main()
{
var Type = HouseType.Unknown;
var Choice = 0;
var Garage = "";

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

switch (Choice)
{
case 1:
Type = HouseType.SingleFamily;
break;

case 2:
Type = HouseType.Townhouse;
break;

case 3:
Type = HouseType.Condominium;
break;

default:
Type = HouseType.Unknown;
break;
}

Console.Write("Does the house have an indoor garage (y/n)? ");


var Answer = char.Parse(Console.ReadLine());
switch (Answer)
{
case 'y':
Garage = "Yes";
break;

case 'Y':
Garage = "Yes";
break;

case 'n':
Garage = "No";
break;

C# 3.0 Practical Learning 248


case 'N':
Garage = "No";
break;

default:
Garage = "Not Specified";
break;
}

Console.WriteLine("\nDesired House Type: {0}", Type);


Console.WriteLine("Has indoor garage? {0}", Garage);

return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 3
Does the house have an indoor garage (y/n)? y

Desired House Type: Condominium


Has indoor garage? Yes
Press any key to continue . . .

Practical Learning: Using Conditional Switches

1. To create a new class, in the Solution Explorer, right-click the project name,
position the mouse on Add and click Class...

2. Set the Name of the class to OrderProcessing and click Add

3. Complete the OrderProcessing.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop2
{
class OrderProcessing
{
public Flower FlowerOrder;
public int Quantity;

public OrderProcessing()
{
FlowerOrder = new Flower();
}

public decimal GetTotalPrice()


{
return Quantity * FlowerOrder.UnitPrice;
C# 3.0 Practical Learning 249
}

public void GetFlowerType()


{
int choice = 0;

Console.WriteLine("Enter the Type of Flower Order");


Console.WriteLine("1. Roses");
Console.WriteLine("2. Lilies");
Console.WriteLine("3. Daisies");
Console.WriteLine("4. Carnations");
Console.WriteLine("5. Live Plant");
Console.WriteLine("6. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());

switch (choice)
{
case 1:
FlowerOrder.Type = FlowerType.Roses;
break;
case 2:
FlowerOrder.Type = FlowerType.Lilies;
break;
case 3:
FlowerOrder.Type = FlowerType.Daisies;
break;
case 4:
FlowerOrder.Type = FlowerType.Carnations;
break;
case 5:
FlowerOrder.Type = FlowerType.LivePlant;
break;
default:
FlowerOrder.Type = FlowerType.Mixed;
break;
}
}

public void GetFlowerColor()


{
int choice = 0;

Console.WriteLine("Enter the Color");


Console.WriteLine("1. Red");
Console.WriteLine("2. White");
Console.WriteLine("3. Yellow");
Console.WriteLine("4. Pink");
Console.WriteLine("5. Orange");
Console.WriteLine("6. Blue");
Console.WriteLine("7. Lavender");
Console.WriteLine("8. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());

switch (choice)
{
case 1:
FlowerOrder.Color = FlowerColor.Red;
break;
C# 3.0 Practical Learning 250
case 2:
FlowerOrder.Color = FlowerColor.White;
break;
case 3:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 4:
FlowerOrder.Color = FlowerColor.Pink;
break;
case 5:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 6:
FlowerOrder.Color = FlowerColor.Blue;
break;
case 7:
FlowerOrder.Color = FlowerColor.Lavender;
break;
default:
FlowerOrder.Color = FlowerColor.Mixed;
break;
}
}

public void GetFlowerArrangement()


{
int choice = 0;

Console.WriteLine("Enter the Type of Arrangement");


Console.WriteLine("1. Bouquet");
Console.WriteLine("2. Vase");
Console.WriteLine("3. Basket");
Console.WriteLine("4. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());

switch (choice)
{
case 1:
FlowerOrder.Arrangement = FlowerArrangement.Bouquet;
break;
case 2:
FlowerOrder.Arrangement = FlowerArrangement.Vase;
break;
case 3:
FlowerOrder.Arrangement = FlowerArrangement.Basket;
break;
default:
FlowerOrder.Arrangement = FlowerArrangement.Any;
break;
}
}

public void ProcessOrder()


{
GetFlowerType();
GetFlowerColor();
GetFlowerArrangement();

Console.Write("Enter the Unit Price: ");


C# 3.0 Practical Learning 251
FlowerOrder.UnitPrice = decimal.Parse(Console.ReadLine());

Console.Write("Enter Quantity: ");


Quantity = int.Parse(Console.ReadLine());
}

public void ShowOrder()


{
Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");
Console.WriteLine("Flower Type: {0}", FlowerOrder.Type);
Console.WriteLine("Flower Color: {0}", FlowerOrder.Color);
Console.WriteLine("Arrangement: {0}",
FlowerOrder.Arrangement);
Console.WriteLine("Price: {0:C}",
FlowerOrder.UnitPrice);
Console.WriteLine("Quantity: {0}", Quantity);
Console.WriteLine("Total Price: {0:C}", GetTotalPrice());
Console.WriteLine("=======================");
}
}
}

4. Access the Program.cs file and complete it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop2
{
class Program
{
static void Main()
{
OrderProcessing order = new OrderProcessing();

order.ProcessOrder();
Console.WriteLine();

order.ShowOrder();
Console.WriteLine();
}
}
}

5. Execute the application and test it. Here is an example:


 
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 4
C# 3.0 Practical Learning 252
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 7
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 3
Enter the Unit Price: 45.85
Enter Quantity: 3

=======================
==-=-=Flower Shop=-=-==
-----------------------
Flower Type: Carnations
Flower Color: Lavender
Arrangement: Basket
Price: $45.85
Quantity: 3
Total Price: $137.55
=======================

Press any key to continue . . .

6. Close the DOS window

Combining Cases

Each of the cases we have used so far examined only one possibility before executing
the corresponding statement. You can combine cases to execute the same statement.
To do this, type a case, its value, and the semi-colon. Type another case using the same
formula. When the cases are ready, you can then execute the desired statement. Here is
an example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
public static int Main()
{
var Type = HouseType.Unknown;
var Choice = 0;

C# 3.0 Practical Learning 253


var Garage = "";

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

switch (Choice)
{
case 1:
Type = HouseType.SingleFamily;
break;

case 2:
Type = HouseType.Townhouse;
break;

case 3:
Type = HouseType.Condominium;
break;

default:
Type = HouseType.Unknown;
break;
}

Console.Write("Does the house have an indoor garage (y/n)? ");


var Answer = char.Parse(Console.ReadLine());
switch (Answer)
{
case 'y':
case 'Y':
Garage = "Yes";
break;

case 'n':
case 'N':
Garage = "No";
break;

default:
Garage = "Not Specified";
break;
}

Console.WriteLine("\nDesired House Type: {0}", Type);


Console.WriteLine("Has indoor garage? {0}", Garage);

return 0;
}
}

This would produce:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
C# 3.0 Practical Learning 254
3. Condominium
You Choice? 3
Does the house have an indoor garage (y/n)? Y

Desired House Type: Condominium


Has indoor garage? Yes
Press any key to continue . . .

Using Enumerations

One of the most fundamental uses of enumerations is to process them in a switch


statement. To do this, you pass the value of an enumeration to a switch. The values of
the enumerations are then processed in the case statements. Here is an example:
using System;

public enum HouseType


{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class Exercise


{
public static int Main()
{
var PropertyType = "";
var Choice = 0;
var Garage = "";

Console.WriteLine("Enter the type of house you want to


purchase");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.Write("You Choice? ");
Choice = int.Parse(Console.ReadLine());

switch ((HouseType)Choice)
{
case HouseType.SingleFamily:
PropertyType = "Single Family";
break;

case HouseType.Townhouse:
PropertyType = "Townhouse";
break;

case HouseType.Condominium:
PropertyType = "Condominium";
break;

default:
PropertyType = "Unknown";
break;
}

C# 3.0 Practical Learning 255


Console.Write("Does the house have an indoor garage (y/n)? ");
var Answer = char.Parse(Console.ReadLine());
switch (Answer)
{
case 'y':
case 'Y':
Garage = "Yes";
break;

case 'n':
case 'N':
Garage = "No";
break;

default:
Garage = "Not Specified";
break;
}

Console.WriteLine("\nDesired House Type: {0}", PropertyType);


Console.WriteLine("Has indoor garage? {0}", Garage);

return 0;
}
}

Here is an example of running the program:


Enter the type of house you want to purchase
1. Single Family
2. Townhouse
3. Condominium
You Choice? 1
Does the house have an indoor garage (y/n)? N

Desired House Type: Single Family


Has indoor garage? No
Press any key to continue . . .

C# 3.0 Practical Learning 256


COUNTING AND LOOPING
 

Conditional Looping
 

Introduction

A loop is a type of conditional statement that keeps checking a condition and executing
a statement until the condition is false.

while a Condition is True

One of the operators used to perform a loop is called while. Its formula is:
while(Condition) Statement;

To execute this expression, the compiler first examines the Condition. If the Condition is
true, then it executes the Statement. After executing the Statement, the Condition is
checked again. AS LONG AS the Condition is true, it will keep executing the Statement.
When or once the Condition becomes false, it exits the loop:

Here is an example:
using System;

public class Exercise


{
C# 3.0 Practical Learning 257
public static int Main()
{
var Stories = 0;

while( Stories <= 4 )


{
Console.WriteLine("Number {0}", Stories);
Stories++;
}

Console.WriteLine();
return 0;
}
}

This would produce:


Number 0
Number 1
Number 2
Number 3
Number 4

Press any key to continue . . .

To effectively execute a while condition, you should make sure you provide a
mechanism for the compiler to use or get a reference value for the condition, variable,
or expression being checked. This is sometimes in the form of a variable being initialized
although it could be some other expression. Such a while condition could be illustrated
as follows:

do This while a Condition is True

The while loop is used first check a condition and then execute a statement. If the
condition is false, the statement would never execute. Consider the following program:
using System;
C# 3.0 Practical Learning 258
public class Exercise
{
public static int Main()
{
var Stories = 5;

while (Stories <= 4)


{
Console.WriteLine("Number {0}", Stories);
Stories++;
}

Console.WriteLine();
return 0;
}
}

When this program executes, nothing from the while loop would execute because, as
the condition is checked in the beginning, it is false and the compiler would not get to
the Statement. In some cases, you may want to execute a statement before checking
the condition for the first time. This can be done using the do…while statement. Its
formula is:
do Statement while (Condition);

The do…while condition executes a Statement first. After the first execution of the
Statement, it examines the Condition. If the Condition is true, then it executes the
Statement again. It will keep executing the Statement AS LONG AS the Condition is true.
Once the Condition becomes false, the looping (the execution of the Statement) would
stop.

If the Statement is a short one, such as made of one line, simply write it after the do
keyword. Like the if and the while statements, the Condition being checked must be
included between parentheses. The whole do…while statement must end with a
semicolon.

Another version of the counting program seen previously would be:


using System;

C# 3.0 Practical Learning 259


public class Exercise
{
public static int Main()
{
var Stories = 0;

do
Console.WriteLine("Number {0}", Stories++);
while (Stories <= 4);

Console.WriteLine();
return 0;
}
}

This would produce:


Number 0
Number 1
Number 2
Number 3
Number 4

Press any key to continue . . .

If the Statement is long and should span more than one line, start it with an opening
curly bracket "{" and end it with a closing curly bracket "}".

Practical Learning: Introducing Counting and Looping

1. Start Microsoft Visual C#

2. Create a new Console Application named FlowerShop3

3. To create a new class, in the Class View, right-click the project name -> Add ->
Class...

4. Set the Name of the class to Flower and click Add

5. Complete the Flower.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop3
{
public enum FlowerType
{
Roses = 1,
Lilies,
Daisies,
Carnations,
LivePlant,
Mixed
}

C# 3.0 Practical Learning 260


public enum FlowerColor
{
Red = 1,
White,
Yellow,
Pink,
Orange,
Blue,
Lavender,
Mixed
}

public enum FlowerArrangement


{
Bouquet = 1,
Vase,
Basket,
Any
}

class Flower
{
public FlowerType Type;
public FlowerColor Color;
public FlowerArrangement Arrangement;
public decimal UnitPrice;

public Flower()
{
Type = FlowerType.Mixed;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
UnitPrice = 0.00M;
}
public Flower(FlowerType type)
{
Type = type;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
UnitPrice = 0.00M;
}
public Flower(FlowerType type, FlowerColor color,
FlowerArrangement argn, decimal price)
{
Type = type;
Color = color;
Arrangement = argn;
UnitPrice = price;
}
}
}

6. To create a new class, in the Solution Explorer, right-click the project name,
position the mouse on Add and click Class...

7. Set the Name of the class to OrderProcessing and click Add

8. Complete the OrderProcessing.cs file as follows:


 

C# 3.0 Practical Learning 261


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop3
{
class OrderProcessing
{
public Flower FlowerOrder;
public int Quantity;

public OrderProcessing()
{
FlowerOrder = new Flower();
}

public decimal GetTotalPrice()


{
return Quantity * FlowerOrder.UnitPrice;
}

public void GetFlowerType()


{
int choice = 0;

do
{
Console.WriteLine("Enter the Type of Flower Order");
Console.WriteLine("1. Roses");
Console.WriteLine("2. Lilies");
Console.WriteLine("3. Daisies");
Console.WriteLine("4. Carnations");
Console.WriteLine("5. Live Plant");
Console.WriteLine("6. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());
} while ((choice < 1) || (choice > 6));

switch (choice)
{
case 1:
FlowerOrder.Type = FlowerType.Roses;
break;
case 2:
FlowerOrder.Type = FlowerType.Lilies;
break;
case 3:
FlowerOrder.Type = FlowerType.Daisies;
break;
case 4:
FlowerOrder.Type = FlowerType.Carnations;
break;
case 5:
FlowerOrder.Type = FlowerType.LivePlant;
break;
default:
FlowerOrder.Type = FlowerType.Mixed;
break;
}
C# 3.0 Practical Learning 262
}

public void GetFlowerColor()


{
int choice = 0;

do
{
Console.WriteLine("Enter the Color");
Console.WriteLine("1. Red");
Console.WriteLine("2. White");
Console.WriteLine("3. Yellow");
Console.WriteLine("4. Pink");
Console.WriteLine("5. Orange");
Console.WriteLine("6. Blue");
Console.WriteLine("7. Lavender");
Console.WriteLine("8. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());
} while ((choice < 1) || (choice > 8));

switch (choice)
{
case 1:
FlowerOrder.Color = FlowerColor.Red;
break;
case 2:
FlowerOrder.Color = FlowerColor.White;
break;
case 3:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 4:
FlowerOrder.Color = FlowerColor.Pink;
break;
case 5:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 6:
FlowerOrder.Color = FlowerColor.Blue;
break;
case 7:
FlowerOrder.Color = FlowerColor.Lavender;
break;
default:
FlowerOrder.Color = FlowerColor.Mixed;
break;
}
}

public void GetFlowerArrangement()


{
int choice = 0;

do
{
Console.WriteLine("Enter the Type of Arrangement");
Console.WriteLine("1. Bouquet");
Console.WriteLine("2. Vase");
Console.WriteLine("3. Basket");
C# 3.0 Practical Learning 263
Console.WriteLine("4. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());
} while ((choice < 1) || (choice > 4));

switch (choice)
{
case 1:
FlowerOrder.Arrangement = FlowerArrangement.Bouquet;
break;
case 2:
FlowerOrder.Arrangement = FlowerArrangement.Vase;
break;
case 3:
FlowerOrder.Arrangement = FlowerArrangement.Basket;
break;
default:
FlowerOrder.Arrangement = FlowerArrangement.Any;
break;
}
}

public void ProcessOrder()


{
GetFlowerType();
GetFlowerColor();
GetFlowerArrangement();

Console.Write("Enter the Unit Price: ");


FlowerOrder.UnitPrice = decimal.Parse(Console.ReadLine());

Console.Write("Enter Quantity: ");


Quantity = int.Parse(Console.ReadLine());
}

public void ShowOrder()


{
Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");
Console.WriteLine("Flower Type: {0}", FlowerOrder.Type);
Console.WriteLine("Flower Color: {0}", FlowerOrder.Color);
Console.WriteLine("Arrangement: {0}",
FlowerOrder.Arrangement);
Console.WriteLine("Price: {0:C}",
FlowerOrder.UnitPrice);
Console.WriteLine("Quantity: {0}", Quantity);
Console.WriteLine("Total Price: {0:C}", GetTotalPrice());
Console.WriteLine("=======================");
}
}
}

9. Access the Program.cs file and complete it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
C# 3.0 Practical Learning 264
namespace FlowerShop3
{
class Program
{
static void Main()
{
OrderProcessing order = new OrderProcessing();

order.ProcessOrder();
Console.WriteLine();

order.ShowOrder();
Console.WriteLine();
}
}
}

10.Execute the application and test it. Here is an example:


 
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 8
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 2
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 9
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 0
Enter the Color
1. Red
2. White
C# 3.0 Practical Learning 265
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 7
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 8
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 5
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 2
Enter the Unit Price: 42.85
Enter Quantity: 2

=======================
==-=-=Flower Shop=-=-==
-----------------------
Flower Type: Lilies
Flower Color: Lavender
Arrangement: Vase
Price: $42.85
Quantity: 2
Total Price: $85.70
=======================

Press any key to continue . . .

11.Close the DOS window

for

The for statement is typically used to count a number of items. At its regular structure,
it is divided in three parts. The first section specifies the starting point for the count. The
second section sets the counting limit. The last section determines the counting
frequency. The syntax of the for statement is:
for(Start; End; Frequency) Statement;

The Start expression is a variable assigned the starting value. This could be Count = 0;

The End expression sets the criteria for ending the counting. An example would be
Count < 24; this means the counting would continue as long as the Count variable is
less than 24. When the count is about to rich 24, because in this case 24 is excluded,

C# 3.0 Practical Learning 266


the counting would stop. To include the counting limit, use the <= or >= comparison
operators depending on how you are counting.

The Frequency expression would let the compiler know how many numbers to add or
subtract before continuing with the loop. This expression could be an increment
operation such as ++Count.

Here is an example that applies the for statement:


using System;

public class Exercise


{
public static int Main()
{
for (var Stories = 0; Stories <= 4; Stories++)
Console.WriteLine("Number {0}", Stories);

Console.WriteLine();
return 0;
}
}

This would produce:


Number 1
Number 2
Number 3
Number 4

Press any key to continue . . .

Controlling the Conditional Statements


 

Nesting a Conditional Statement

Consider the following program:


using System;

public class Exercise


{
public static int Main()
{
var TypeOfHome = 0;

do
{
Console.WriteLine("What Type of House Would you Like to
Purchase?");
Console.WriteLine("1 - Single Family");
Console.WriteLine("2 - Town House");
Console.WriteLine("3 - Condominium");
Console.Write("Your Choice? ");
TypeOfHome = int.Parse(Console.ReadLine());

C# 3.0 Practical Learning 267


} while ((TypeOfHome < 1) || (TypeOfHome > 3));

if (TypeOfHome == 1)
Console.WriteLine("\nType of Home: Single Family");
else if (TypeOfHome == 2)
Console.WriteLine("\nType of Home: Town House");
else if (TypeOfHome == 3)
Console.WriteLine("\nType of Home: Condominium");

Console.WriteLine();
return 0;
}
}

This is used to request one of the numbers 1, 2, or 3 from the user. Any number below
1 or above 3 is not accepted. Here is an example of running the program:
What Type of House Would you Like to Purchase?
1 - Single Family
2 - Town House
3 - Condominium
Your Choice? 8
What Type of House Would you Like to Purchase?
1 - Single Family
2 - Town House
3 - Condominium
Your Choice? 6
What Type of House Would you Like to Purchase?
1 - Single Family
2 - Town House
3 - Condominium
Your Choice? 3

Type of Home: Condominium

Press any key to continue . . .

If the user enters an invalid value, the question is simply being asked again. It would be
professional to let the user know why the request came back even though what appears
as a normal number was entered. To solve this and other types of problems, you can
write one conditional statement inside of another. This is referred to as nesting. To
create a conditional statement inside of another, simply proceed as we have done so far
to create them. Here is an example:
using System;

public class Exercise


{
public static int Main()
{
var TypeOfHome = 0;

do
{
Console.WriteLine("What Type of House Would you Like to
Purchase?");
Console.WriteLine("1 - Single Family");
Console.WriteLine("2 - Townhouse");
Console.WriteLine("3 - Condominium");

C# 3.0 Practical Learning 268


Console.Write("Your Choice? ");
TypeOfHome = int.Parse(Console.ReadLine());

if ((TypeOfHome < 1) || (TypeOfHome > 3))


Console.WriteLine("Invalid Choice: Please try again");
} while ((TypeOfHome < 1) || (TypeOfHome > 3));

if (TypeOfHome == 1)
Console.WriteLine("\nType of Home: Single Family");
else if (TypeOfHome == 2)
Console.WriteLine("\nType of Home: Townhouse");
else if (TypeOfHome == 3)
Console.WriteLine("\nType of Home: Condominium");

Console.WriteLine();
return 0;
}
}

Here is another example of running the program:


What Type of House Would you Like to Purchase?
1 - Single Family
2 - Town House
3 - Condominium
Your Choice? 0
Invalid Choice: Please try again
What Type of House Would you Like to Purchase?
1 - Single Family
2 - Town House
3 - Condominium
Your Choice? 6
Invalid Choice: Please try againe
What Type of House Would you Like to Purchase?
1 - Single Family
2 - Town House
3 - Condominium
Your Choice? 2

Type of Home: Town House

Press any key to continue . . .

Practical Learning: Nesting Conditions

1. Access the OrderProcessing.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop3
{
class OrderProcessing
{
public Flower FlowerOrder;
public int Quantity;
C# 3.0 Practical Learning 269
public OrderProcessing()
{
FlowerOrder = new Flower();
}

public decimal GetTotalPrice()


{
return Quantity * FlowerOrder.UnitPrice;
}

public void GetFlowerType()


{
int choice = 0;

do
{
Console.WriteLine("Enter the Type of Flower Order");
Console.WriteLine("1. Roses");
Console.WriteLine("2. Lilies");
Console.WriteLine("3. Daisies");
Console.WriteLine("4. Carnations");
Console.WriteLine("5. Live Plant");
Console.WriteLine("6. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());

if ((choice < 1) || (choice > 6))


Console.WriteLine(
"Invalid Value: Please enter a value between 1 and
6");
} while ((choice < 1) || (choice > 6));

switch (choice)
{
case 1:
FlowerOrder.Type = FlowerType.Roses;
break;
case 2:
FlowerOrder.Type = FlowerType.Lilies;
break;
case 3:
FlowerOrder.Type = FlowerType.Daisies;
break;
case 4:
FlowerOrder.Type = FlowerType.Carnations;
break;
case 5:
FlowerOrder.Type = FlowerType.LivePlant;
break;
default:
FlowerOrder.Type = FlowerType.Mixed;
break;
}
}

public void GetFlowerColor()


{
int choice = 0;

C# 3.0 Practical Learning 270


do
{
Console.WriteLine("Enter the Color");
Console.WriteLine("1. Red");
Console.WriteLine("2. White");
Console.WriteLine("3. Yellow");
Console.WriteLine("4. Pink");
Console.WriteLine("5. Orange");
Console.WriteLine("6. Blue");
Console.WriteLine("7. Lavender");
Console.WriteLine("8. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());

if ((choice < 1) || (choice > 8))


Console.WriteLine(
"Invalid Value: Please enter a value between 1 and
8");
} while ((choice < 1) || (choice > 8));

switch (choice)
{
case 1:
FlowerOrder.Color = FlowerColor.Red;
break;
case 2:
FlowerOrder.Color = FlowerColor.White;
break;
case 3:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 4:
FlowerOrder.Color = FlowerColor.Pink;
break;
case 5:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 6:
FlowerOrder.Color = FlowerColor.Blue;
break;
case 7:
FlowerOrder.Color = FlowerColor.Lavender;
break;
default:
FlowerOrder.Color = FlowerColor.Mixed;
break;
}
}

public void GetFlowerArrangement()


{
int choice = 0;

do
{
Console.WriteLine("Enter the Type of Arrangement");
Console.WriteLine("1. Bouquet");
Console.WriteLine("2. Vase");
Console.WriteLine("3. Basket");
Console.WriteLine("4. Mixed");
C# 3.0 Practical Learning 271
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());

if ((choice < 1) || (choice > 4))


Console.WriteLine(
"Invalid Value: Please enter a value between 1 and
4");
} while ((choice < 1) || (choice > 4));

switch (choice)
{
case 1:
FlowerOrder.Arrangement = FlowerArrangement.Bouquet;
break;
case 2:
FlowerOrder.Arrangement = FlowerArrangement.Vase;
break;
case 3:
FlowerOrder.Arrangement = FlowerArrangement.Basket;
break;
default:
FlowerOrder.Arrangement = FlowerArrangement.Any;
break;
}
}

public void ProcessOrder()


{
GetFlowerType();
GetFlowerColor();
GetFlowerArrangement();

Console.Write("Enter the Unit Price: ");


FlowerOrder.UnitPrice = decimal.Parse(Console.ReadLine());

Console.Write("Enter Quantity: ");


Quantity = int.Parse(Console.ReadLine());
}

public void ShowOrder()


{
Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");
Console.WriteLine("Flower Type: {0}", FlowerOrder.Type);
Console.WriteLine("Flower Color: {0}", FlowerOrder.Color);
Console.WriteLine("Arrangement: {0}",
FlowerOrder.Arrangement);
Console.WriteLine("Price: {0:C}",
FlowerOrder.UnitPrice);
Console.WriteLine("Quantity: {0}", Quantity);
Console.WriteLine("Total Price: {0:C}", GetTotalPrice());
Console.WriteLine("=======================");
}
}
}

2. Execute the application and test it. Here is an example:


 

C# 3.0 Practical Learning 272


Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 8
Invalid Value: Please enter a value between 1 and 6
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 0
Invalid Value: Please enter a value between 1 and 6
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 4
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 9
Invalid Value: Please enter a value between 1 and 8
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 3
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 9
Invalid Value: Please enter a value between 1 and 4
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 5
C# 3.0 Practical Learning 273
Invalid Value: Please enter a value between 1 and 4
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
Your Choice: 3
Enter the Unit Price: 54.95
Enter Quantity: 1

=======================
==-=-=Flower Shop=-=-==
-----------------------
Flower Type: Carnations
Flower Color: Yellow
Arrangement: Basket
Price: $54.95
Quantity: 1
Total Price: $54.95
=======================

Press any key to continue . . .

3. Close the DOS window

Breaking the Flow of a Conditional Statement

The break statement is used to stop a loop for any reason or condition when necessary.
The formula of the break statement is:
break;

Although made of only one word, the break statement is a complete statement;
therefore, it can (and should always) stay on its own line (this makes the program easy
to read).

The break statement applies to the most previous conditional statement to it; provided
that previous statement is applicable. The break statement can be used in a while
condition, in a do…while or a for loops to stop an ongoing action. Here is an example
that is used to count the levels of a house from 1 to 12 but it is asked to stop at 3:
using System;

public class Exercise


{
public static int Main()
{
for (var Stories = 1; Stories <= 12; Stories++)
{
Console.WriteLine("Story {0}", Stories);
if (Stories == 3)
break;
}

Console.WriteLine();
return 0;
}
}
C# 3.0 Practical Learning 274
This would produce: 
Story 1
Story 2
Story 3

Press any key to continue . . .

Continuing a Conditional Statement

The continue statement uses the following formula:


continue;

When processing a loop, if the statement finds a false value, you can use the continue
statement inside of a while, a do…while or a for conditional statements to ignore the
subsequent statement or to jump from a false Boolean value to the subsequent valid
value, unlike the break statement that would exit the loop. Like the break statement,
the continue keyword applies to the most previous conditional statement and should
stay on its own line. Here is an example when a program is supposed to count the levels
of a house from 1 to 6:
using System;

public class Exercise


{
public static int Main()
{
for (var Stories = 1; Stories <= 6; Stories++)
{
if (Stories == 3)
continue;
Console.WriteLine("Story {0}", Stories);
}

Console.WriteLine();
return 0;
}
}

This would produce:


Story 1
Story 2
Story 4
Story 5
Story 6

Press any key to continue . . .

Notice that, when the compiler gets to 3, it ignores it.

Going to a Designated Label

The goto statement allows a program execution to jump to another section of the
function in which it is being used. In order to use the goto statement, insert a name on

C# 3.0 Practical Learning 275


a particular section of your function so you can refer to that name. The name, also
called a label, is made of one word and follows the rules we have learned about C++
names (the name can be anything), then followed by a colon. Here is an example where
the program is supposed to count the levels of a 14 story building:
using System;

public class Exercise


{
public static int Main()
{
for (var Stories = 1; Stories <= 14; Stories++)
{
if (Stories == 4)
goto CountUpTo3;
Console.WriteLine("Story {0}", Stories);
}

CountUpTo3:
Console.WriteLine("Our homes have only up to 3 levels\n");

return 0;
}
}

This would produce:


Story 1
Story 2
Story 3
Our homes have only up to 3 levels

Press any key to continue . . .

Conditional Return

Some functions are meant to return a value that is conditional of their processing. The
fact that a function indicates the type of value it would return may not be clear at the
time the function is closed but a function defined other than void must always return a
value. You can write a conditional statement, such as if, inside of a function and return a
value from that condition. Here is an example:
using System;

public class Program


{
enum HouseType { Unknown, SingleFamily, Townhouse, Condominium };

public static int Main()


{
var Type = GetHouseType();

switch (Type)
{
case HouseType.SingleFamily:
Console.WriteLine("\nType of Home: Single Family");
break;
case HouseType.Townhouse:
C# 3.0 Practical Learning 276
Console.WriteLine("\nType of Home: Townhouse");
break;
case HouseType.Condominium:
Console.WriteLine("\nType of Home: Condominium");
break;
case HouseType.Unknown:
Console.WriteLine("\nType of Home. Unknown");
break;
}

return 0;
}

private static HouseType GetHouseType()


{
var Type = 0;

Console.WriteLine("What Type of House Would you Like to


Purchase?");
Console.WriteLine("1 - Single Family");
Console.WriteLine("2 - Townhouse");
Console.WriteLine("3 - Condominium");
Console.Write("Your Choice? ");
Type = int.Parse(Console.ReadLine());

if (Type == 1)
return HouseType.SingleFamily;
else if (Type == 2)
return HouseType.Townhouse;
else if (Type == 3)
return HouseType.Condominium;
}
}

This GetHouseType() method indicates when one of three values is returned. In reality,
this method could get a value other than the three that are considered. If the user
enters such a value, the current version of the method would not know what to do. For
this reason, the program will not compile. In Microsoft Visual C#, you would receive the
following error:
'Program.GetHouseType()': not all code paths return a value

To solve this problem, you must provide a statement that would include any value other
than those considered. You can do this by writing a final return that has its own value.
Here is an example:
using System;

public class Program


{
enum HouseType { Unknown, SingleFamily, Townhouse, Condominium };

public static int Main()


{
var Type = GetHouseType();

switch (Type)
{
case HouseType.SingleFamily:

C# 3.0 Practical Learning 277


Console.WriteLine("\nType of Home: Single Family");
break;
case HouseType.Townhouse:
Console.WriteLine("\nType of Home: Townhouse");
break;
case HouseType.Condominium:
Console.WriteLine("\nType of Home: Condominium");
break;
case HouseType.Unknown:
Console.WriteLine("\nType of Home. Unknown");
break;
}

return 0;
}

private static HouseType GetHouseType()


{
var Type = 0;

Console.WriteLine("What Type of House Would you Like to


Purchase?");
Console.WriteLine("1 - Single Family");
Console.WriteLine("2 - Townhouse");
Console.WriteLine("3 - Condominium");
Console.Write("Your Choice? ");
Type = int.Parse(Console.ReadLine());

if (Type == 1)
return HouseType.SingleFamily;
else if (Type == 2)
return HouseType.Townhouse;
else if (Type == 3)
return HouseType.Condominium;
else
return HouseType.Unknown;
}
}

Recursion
 

Introduction

Imagine that you want to count the positive odd numbers from a certain maximum to a
certain minimum. For example, to count the odd numbers from 1 to 9, you would use:

9, 7, 5, 3, and 1

Notice that, to perform this operation, you consider the highest. Then you subtract 2 to
get the previous. Again, you subtract 2 from the number to get the previous. What you
are simply doing is to subtract a constant to what you already have and you invent very
little. In computer programming, you can solve this type of problem by first writing a
function, and then have the function call itself. This is the basis for recursion.

Creating a Recursive Methods

C# 3.0 Practical Learning 278


 A type of formula to create a recursive method is:
ReturnValue Function(Arguments, if any)
{
Optional Action . . .
Function();
Optionan Action . . .
}

A recursive method starts with a return value. If it would not return a value, you can
define it with void. After its name, the method can take one or more arguments. Most
of the time, a recursive method takes at least one argument that it would then modify.
In the body of the method, you can take the necessary actions. There are no particular
steps to follow when implementing a recursive method but there are two main rules to
observe:

 In its body, the method must call itself

 Before or after calling itself, the method must check a condition that would allow it
to stop, otherwise, it might run continuously

For our example of counting decrementing odd numbers, you could start by creating a
method that takes an integer as argument. To exercise some control on the lowest
possible values, we will consider only positive numbers. In the body of the method, we
will display the current value of the argument, subtract 2, and recall the method itself.
Here is our function:
using System;

public class Exercise


{
static void OddNumbers(int a)
{
if (a >= 1)
{
Console.Write("{0}, ", a);
a -= 2;
OddNumbers(a);
}
}

public static int Main()


{
const int Number = 9;

Console.WriteLine("Odd Numbers");
OddNumbers(Number);

Console.WriteLine();
return 0;
}
}

Notice that the method calls itself in its body. This would produce:
Odd Numbers
9, 7, 5, 3, 1,
Press any key to continue . . .

C# 3.0 Practical Learning 279


Using Recursive Methods

Recursive methods provide a valuable mechanism for building lists or series, which are value
that are either increment or decrement but follow a pattern. Imagine that, instead of simply
displaying odd numbers as we did above, you want to add them incrementally. If you have
1, it would also produce 1. If you have 5, you would like to add 1 to 3, then the result to 5,
and so on. This can be illustrated as follows:

1
= 1
1 + 3
= 4
1 + 3 + 5
= 9
1 + 3 + 5 + 7
= 16
1 + 3 + 5 + 7 + 9
= 25

To perform this operation, you would consider 1. If the number is less than or equal to
1, the method should return 1. Otherwise, add 2 to 1, then add 2 to the new result.
Continue this until you get to the value of the argument. The method can be
implemented as follows:
using System;

public class Exercise


{
static int AdditionalOdd(int a)
{
if (a <= 1)
return 1;
return a + AdditionalOdd(a - 2);
}

static void OddNumbers(int a)


{
if (a >= 1)
{
Console.Write("{0}, ", a);
a -= 2;
OddNumbers(a);
}
}

public static int Main()


{
const int Number = 9;

Console.WriteLine("Odd Numbers");
OddNumbers(Number);

Console.WriteLine();
Console.WriteLine("Sum of Odds: {0}\n", AdditionalOdd(Number));

return 0;
}
}

C# 3.0 Practical Learning 280


This would produce:
Odd Numbers
9, 7, 5, 3, 1,
Sum of Odds: 25

Press any key to continue . . .

C# 3.0 Practical Learning 281


THE PROPERTIES OF A
CLASS
 

Overview of Properties
 

Introduction

In C++ and Java, when creating the member variables of a class, programmers usually
"hide" these members in private sections (C++) or create them as private (Java). This
technique makes sure that a member variable is not accessible outside of the class so
that the clients of the class cannot directly influence the value of the member variable. If
you create a member variable as private but still want other classes to access or get
the value of such a field, you must then create one or two "accessories", like a door in
which the external classes must pass through to access the field.

  

Accessories for Properties

A property is a member of a class that plays an intermediary role to a field of the class.
For example, if you have a field of class and that member represents the salary of an
employee, a property can be the "door" that other classes that need the salary must
present their requests to. As such, these external classes cannot just change the salary
or retrieve it as they wish. A property can be used to validate their request, to reject or
to accept them.

A property is used to "filter" access to a field of a class. Therefore, you start by declaring
a (private (if you don't make it private, you may be deceiving the purpose of creating a
property)) field. Here is an example:

using System;

public class Square


{
private double _side;
}

public class Exercise

{
public static int Main()
{
return 0;

C# 3.0 Practical Learning 282


}
}

Obviously this private field cannot be accessed by an outside class. To let the outside
classes access this variable, you would/can create a property. To indicate that you are
creating a property, there is a syntax you must follow. To start, you must create a
member whose formula resembles a method without the parentheses. Since or if the
property will be accessed by only by objects of the same program, you can mark it with
the internal keyword. If the property will be accessed by objects of this and other
programs, you should mark it as public. Therefore, you would start a property as
follows:
public class Square
{
private double _side;

// This is a new property


public double Side
{
}
}

With regards to their role, there are two types of properties.

Practical Learning: Introducing Properties

1. Start Microsoft Visual C# and create a Console Application named


DepartmentStore2

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to ShoppingItem and press Enter

4. Change the content of the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class DepartmentStore
{
private long itemNo;
private string nm;
private string sz;
private decimal price;
}
}

5. To create a property for each member variable, change the ShoppingItem class as
follows:
 
using System;

C# 3.0 Practical Learning 283


using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class ShoppingItem
{
private string itemNo;
private string nm;
private string sze;
private decimal price;

// A property for the stock number of an item


public string ItemNumber
{
}

// A property for the name of an item


public string Name
{
}

// A property for size of a merchandise


public string Size
{
}

// A property for the marked price of an item


public decimal UnitPrice
{
}
}
}

6. Save the file

Types of Properties
 

Property Readers

A property is referred to as read if its role is only to make available the value of the
member variable it represents. To create a read property, in the body of the property,
type the get keyword and create a body for the keyword, using the traditional curly
brackets that delimit a section of code. Here is an example:
public class Square
{
private double _side;

// This is a new property


public double Side
{
get
{

C# 3.0 Practical Learning 284


}
}
}

In the body of the get clause, you can implement the behavior that would be used to
make the field's value available outside. The simplest way consists of just returning the
corresponding field. Here is an example:
public class Square
{
private double _side;

// This is a new property


public double Side
{
get
{
return _side;
}
}
}

A read property is also referred to as read-only property because the clients of the class
can only retrieve the value of the property but they cannot change it. Therefore, if you
create (only) a read property, you should provide the users with the ability to primarily
specify the value of the member variable. To do this, you can create an accessory
method or a constructor for the class . Here is an example of such a constructor:
public class Square
{
private double _side;

// This is a new property


public double Side
{
get
{
return _side;
}
}

public Square(double s)
{
_side = s;
}
}

Once a read property has been created, other classes can access it, for example they
can read its value as follows:
using System;

public class Square


{
private double _side;

// This is a new property

C# 3.0 Practical Learning 285


public double Side
{
get
{
return _side;
}
}

public Square(double s)
{
_side = s;
}
}

public class Exercise


{
public static int Main()
{
var sq = new Square(-25.55);

Console.WriteLine("Square Side: {0}", sq.Side);


return 0;
}
}

This would produce:


Square Side: -25.55

Press any key to continue...

We described a property as serving as a door from outside to its corresponding field,


preventing those outside classes to mess with the member variable. Notice that the
Square class was given a negative value for the member variable, which is usually
unrealistic for the side of a square. In this case and others, while still protecting the field
as private, you can use the read property to reset the value of the field or even to reject
it. To provide this functionality, you can create a conditional statement in the read
property to perform a checking process. Here is an example:
using System;

public class Square


{
private double _side;

// This is a new property


public double Side
{
get
{
// If the value given to the side is negative,
// then set it to 0
if (_side < 0)
return 0;
else
return _side;
}
}

C# 3.0 Practical Learning 286


public Square(double s)
{
_side = s;
}
}

public class Exercise


{
public static int Main()
{
var sq1 = new Square(-12.48);
var sq2 = new Square(25.55);

Console.WriteLine("First Square Characteristics");


Console.WriteLine("Side: {0}\n", sq1.Side);

Console.WriteLine("Second Square Characteristics");


Console.WriteLine("Side: {0}\n", sq2.Side);
return 0;
}
}

This would produce:


First Square Characteristics
Side: 0

Second Square Characteristics


Side: 25.55

Practical Learning: Creating Property Readers

1. To create read properties, change the contents of the ShoppingStore.cs file as


follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class ShoppingItem
{
private long itemNo;
private string nm;
private string sz;
private decimal price;

// A property for the stock number of an item


public long ItemNumber
{
get
{
return itemNo;
}
}

C# 3.0 Practical Learning 287


// A property for the name of an item
public string Name
{
get
{
return nm;
}
}

// A property for size of a merchandise


public string Size
{
get
{
if( sz == "0" )
return "Unknown Size or Fits All";
else
return sz;
}
}

// A property for the marked price of an item


public decimal UnitPrice
{
get
{
return price;
}
}

// A constructor used to initialize an item


public ShoppingItem(long nbr,
string nme,
string siz,
decimal prc)
{
itemNo = nbr;
nm = nme;
sz = siz;
price = prc;
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class Program
{
static void Main()
{
long number;
string name;
C# 3.0 Practical Learning 288
string size;
decimal price;

Console.WriteLine("/-/Arrington Department Store/-/");


Console.Write("Enter the Item #: ");
number = long.Parse(Console.ReadLine());
Console.Write("Enter the Item Name: ");
name = Console.ReadLine();
Console.Write("Enter the Item Size: ");
size = Console.ReadLine();
Console.Write("Enter the Unit Price: ");
price = decimal.Parse(Console.ReadLine());

ShoppingItem store = new ShoppingItem(number, name, size,


price);

Console.WriteLine("\n================================");
Console.WriteLine("/-/Arrington Department Store/-/");
Console.WriteLine("--------------------------------");
Console.WriteLine("Customer Invoice");
Console.WriteLine("Item #: {0}", store.ItemNumber);
Console.WriteLine("Description: {0}", store.Name);
Console.WriteLine("Item Size: {0}", store.Size);
Console.WriteLine("Unit Price: {0:C}", store.UnitPrice);
Console.WriteLine("================================\n");
}
}
}

3. Execute the program:

 
/-/Arrington Department Store/-/
Enter the Item #: 622805
Enter the Item Name: Black Leather Hand Bag
Enter the Item Size: Medium
Enter the Unit Price: 85.95

================================
/-/Arrington Department Store/-/
--------------------------------
Customer Invoice

C# 3.0 Practical Learning 289


Item #: 622805
Description: Black Leather Hand Bag
Item Size: Medium
Unit Price: $85.95
================================

Press any key to continue . . .

4. Close the DOS window

Property Writers

In our Square class so far, we were using a constructor to create a value for each of the
necessary member variables. This meant that we had to always make sure that we knew
the value of the field when we declared an instance of the class. Sometimes, this is not
effective. For example, you cannot just call a constructor in the middle of the program,
that is after the object has been declared, to assign a new value to the field. To solve
this kind of problem, you can provide another means of accessing the field any time to
change its value.

Besides, or instead of, retrieving the value of a field of a class, you may want external
classes to be able to change the value of that member. Continuing with our concern to
hide a field as private, you can create another type of property. A property is referred to
as write if it can change (or write) the value of its corresponding field.

To create a write property, type the set keyword followed by the curly bracket
delimiters. Here is an example:
public class Square
{
private double _side;

// This is a new property


public double Side
{
set
{
}
}
}

The minimum assignment you can perform with a write property is to assign it a value
that would be provided by the outside world. To support this, C# provides the value
contextual keyword (contextual means the word is a keyword only in some cases,
depending on how it is being used). Here is an example:
public class Square
{
private double _side;

// This is a new property


public double Side
{
C# 3.0 Practical Learning 290
set
{
_side = value;
}
}
}

As you see, clients of a class can change the corresponding field of a member variable
through the property writer. Based on this relationship, it is not unusual for a client of a
class to make an attempt to "mess" with a field. For example, an external object can
assign an invalid value to a member variable. Consider the following program:
using System;

public class Square


{
public double _side;

// This is a new property


public double Side
{
set
{
_side = value;
}
}

public Square()
{
_side = 0;
}

public Square(double s)
{
_side = s;
}

public double Perimeter()


{
return _side * 4;
}

public double Area()


{
return _side * _side;
}
}

public class Exercise


{
public static int Main()
{
var sq1 = new Square();
var sq2 = new Square();

sq1._side = -12.48;
sq2._side = 25.55;

Console.WriteLine("First Square Characteristics");

C# 3.0 Practical Learning 291


Console.WriteLine("Side: {0}", sq1._side);
Console.WriteLine("Perimeter: {0}", sq1.Perimeter());
Console.WriteLine("Area: {0}\n", sq1.Area());

Console.WriteLine("Second Square Characteristics");


Console.WriteLine("Side: {0}", sq2._side);
Console.WriteLine("Perimeter: {0}", sq2.Perimeter());
Console.WriteLine("Area: {0}", sq2.Area());

return 0;
}
}

This would produce:


First Square Characteristics
Side: -12.48
Perimeter: -49.92
Area: 155.7504

Second Square Characteristics


Side: 25.55
Perimeter: 102.2
Area: 652.8025

Press any key to continue...

Because of this, and since it is through the writer that the external objects would change
the value of the member variable, you can use the write property, rather than the
reader, to validate or reject a new value assigned to the field. Remember that the client
objects of the class can only read the value of the field through the read property.
Therefore, there may be only little concern on that side.

Read/Write Properties

If you create a property that has only a set section, the property is referred to as write-
only because the other classes can only assign it a value (or write a value to it). If you
create a property that has both a get and a set sections, its corresponding member
variable can receive new values from outside the class and the member variable can
provide its values to clients of the class. Such a property is referred to as read/write.

Practical Learning: Creating Property Writers

1. To create property writers and complete the program, change the content of the
ShoppingItem.cs file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{

C# 3.0 Practical Learning 292


class ShoppingItem
{
private long itemNo;
private string nm;
private string sz;
private decimal price;

// A property for the stock number of an item


public long ItemNumber
{
get
{
return itemNo;
}

set
{
if (itemNo <= 0)
itemNo = 0;
else
itemNo = value;
}
}

// A property for the name of an item


public string Name
{
get
{
return nm;
}

set
{
if (nm == "")
nm = "Item no Description";
else
nm = value;
}
}

// A property for size of a merchandise


public string Size
{
get
{
if( sz == "0" )
return "Unknown Size or Fits All";
else
return sz;
}

set
{
sz = value;
}
}

// A property for the marked price of an item


public decimal UnitPrice
C# 3.0 Practical Learning 293
{
get
{
return price;
}

set
{
if (price < 0)
price = 0.00M;
else
price = value;
}
}

public static ShoppingItem Read()


{
ShoppingItem shop = new ShoppingItem();

Console.Write("Item #: ");
shop.itemNo = long.Parse(Console.ReadLine());
Console.Write("Item Name: ");
shop.Name = Console.ReadLine();
Console.Write("Item Size (Enter 0 if unknown): ");
shop.Size = Console.ReadLine();
Console.Write("Unit Price: ");
shop.UnitPrice = decimal.Parse(Console.ReadLine());

return shop;
}

public static void Write(ShoppingItem item)


{
Console.WriteLine("Item #: {0}", item.ItemNumber);
Console.WriteLine("Description: {0}", item.Name);
Console.WriteLine("Item Size: {0}", item.Size);
Console.WriteLine("Unit Price: {0:C}", item.UnitPrice);
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class Program
{
static void Main()
{
Console.WriteLine("/-/Arrington Department Store/-/");
Console.Write("Enter the following pieces of ");
Console.WriteLine("information about the sale item");
ShoppingItem saleItem = ShoppingItem.Read();

C# 3.0 Practical Learning 294


Console.WriteLine("\n================================");
Console.WriteLine("/-/Arrington Department Store/-/");
Console.WriteLine("--------------------------------");
ShoppingItem.Write(saleItem);
}
}
}

3. Execute the program. Here is an example:


 

/-/Arrington Department Store/-/


Enter the following pieces of
information about the sale item
Item #: 114888
Item Name: North Hook Alpine Jacket
Item Size (Enter 0 if unknown): Large
Unit Price: 275.95

================================
/-/Arrington Department Store/-/
--------------------------------
Item #: 114888
Description: North Hook Alpine Jacket
Item Size: Large
Unit Price: $275.95
Press any key to continue . . .

4. Close the DOS window

A Boolean Property

You can create a property as a Boolean type. To do this, first specify its data type as
bool. When treating the property, make sure its get accessory returns a Boolean type.
A Boolean property is not like the other regular properties. It must specify its value as
true or false. As done for Boolean methods, a Boolean property must produce only a
true or false value.
C# 3.0 Practical Learning 295
Properties of External Classes
 

Properties and Enumerations

An enumeration is a technique of creating data type that mimics an integer. After


creating it, you can treat it as a pseudo data type. You can declare a variable from it,
you can pass it as an argument, and you can return it from a method. Based on these
characteristics, you can create a property that is based on an enumeration.

To create an enumeration property, you use the same formula as one of the primitive
data types we have used previously. Keep it mind that the property is of the type of an
enumeration. This means that you cannot request its value like that of a primitive type
and, when manipulating it, you must process it appropriately.

Practical Learning: Creating an Enumeration Property

1. Access the ShoppingStore.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
public enum ItemCategory
{
Unspecified,
Women,
Men,
Girls,
Boys,
Babies
}

class ShoppingItem
{
private long itemNo;
private ItemCategory cat;
private string nm;
private string sz;
private decimal price;

// A property for the stock number of an item


public long ItemNumber
{
get
{
return itemNo;
}

set

C# 3.0 Practical Learning 296


{
if (itemNo <= 0)
itemNo = 0;
else
itemNo = value;
}
}

// A property for the category of item


public ItemCategory Category
{
get
{
return cat;
}

set
{
cat = value;
}
}

// A property for the name of an item


public string Name
{
get
{
return nm;
}

set
{
if (nm == "")
nm = "Item no Description";
else
nm = value;
}
}

// A property for size of a merchandise


public string Size
{
get
{
if( sz == "0" )
return "Unknown Size or Fits All";
else
return sz;
}

set
{
sz = value;
}
}

// A property for the marked price of an item


public decimal UnitPrice
{
get
C# 3.0 Practical Learning 297
{
return price;
}

set
{
if (price < 0)
price = 0.00M;
else
price = value;
}
}

public static ShoppingItem Read()


{
int category = 0;
ShoppingItem shop = new ShoppingItem();

Console.Write("Item #: ");
shop.itemNo = long.Parse(Console.ReadLine());
Console.WriteLine("Store Items Categories");
Console.WriteLine("\t1. Women");
Console.WriteLine("\t2. Men");
Console.WriteLine("\t3. Girls");
Console.WriteLine("\t4. Boys");
Console.WriteLine("\t5. Babies");
Console.Write("Enter the Category: ");
category = int.Parse(Console.ReadLine());
if (category == 1)
shop.Category = ItemCategory.Women;
else if (category == 2)
shop.Category = ItemCategory.Men;
else if (category == 3)
shop.Category = ItemCategory.Girls;
else if (category == 4)
shop.Category = ItemCategory.Boys;
else if (category == 5)
shop.Category = ItemCategory.Babies;
else
shop.Category = ItemCategory.Unspecified;
Console.Write("Item Name: ");
shop.Name = Console.ReadLine();
Console.Write("Item Size (Enter 0 if unknown): ");
shop.Size = Console.ReadLine();
Console.Write("Unit Price: ");
shop.UnitPrice = decimal.Parse(Console.ReadLine());

return shop;
}

public static void Write(ShoppingItem item)


{
Console.WriteLine("Item #: {0}", item.ItemNumber);
Console.WriteLine("Category: {0}", item.Category);
Console.WriteLine("Description: {0}", item.Name);
Console.WriteLine("Item Size: {0}", item.Size);
Console.WriteLine("Unit Price: {0:C}", item.UnitPrice);
}
}
}
C# 3.0 Practical Learning 298
2. Execute the application and test it. Here is an example:

 
/-/Arrington Department Store/-/
Enter the following pieces of
information about the sale item
Item #: 624008
Store Items Categories
1. Women
2. Men
3. Girls
4. Boys
5. Babies
Enter the Category: 3
Item Name: Scotta Miniskirt
Item Size (Enter 0 if unknown): 11
Unit Price: 35.95

================================
/-/Arrington Department Store/-/
--------------------------------
Item #: 624008
Category: Girls
Description: Scotta Miniskirt
Item Size: 11
Unit Price: $35.95
Press any key to continue . . .

3. Close the DOS window

A Class as a Property

Remember that, after creating a class, it becomes a data type in its own right. We have
seen that you could declare a variable from it, you could pass it as argument, and you
could return it from a method. As a normal data type, a class can be validated. This
means that its value can be evaluated, rejected, or retrieved. Based on these
characteristics of a class, you can create a property from it.

To create a property that is based on a class, primarily follow the same formulas we
have applied to the other properties. The most important aspect to remember is that the
class is composite. That is, it is (likely) made of fields of various types.

Practical Learning: Creating a Property of a Class Type


C# 3.0 Practical Learning 299
1. Access the ShoppingItem.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
public enum ItemCategory
{
Unspecified,
Women,
Men,
Girls,
Boys,
Babies
}

class ShoppingItem
{
private long itemNo;
private ItemCategory cat;
private string nm;
private string sz;
private decimal price;

// A property for the stock number of an item


public long ItemNumber
{
get
{
return itemNo;
}

set
{
itemNo = value;
}
}

// A property for the category of item


public ItemCategory Category
{
get
{
return cat;
}

set
{
cat = value;
}
}

// A property for the name of an item


public string Name
{
C# 3.0 Practical Learning 300
get
{
return nm;
}

set
{
if (nm == "")
nm = "Item no Description";
else
nm = value;
}
}

// A property for size of a merchandise


public string Size
{
get
{
if (sz == "0")
return "Unknown Size or Fits All";
else
return sz;
}

set
{
sz = value;
}
}

// A property for the marked price of an item


public decimal UnitPrice
{
get
{
return price;
}

set
{
if (price < 0)
price = 0.00M;
else
price = value;
}
}
}
}

2. To create a new class, in the Solution Explorer, right-click the name of the project,
position the mouse on Add and click Class...

3. Set the Name to DepartmentStore and click Add

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
C# 3.0 Practical Learning 301
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class DepartmentStore
{
private int qty;
private ShoppingItem itm;

public int Quantity


{
get { return qty; }
set
{
if (qty <= 0)
qty = 0;
else
qty = value;
}
}

public ShoppingItem SaleItem


{
get { return itm; }
set
{
if (itm == null)
{
itm.ItemNumber = 0;
itm.Category = ItemCategory.Unspecified;
itm.Name = "Unknown";
itm.Size = "0";
itm.UnitPrice = 0.00M;
}
else
itm = value;
}
}

public DepartmentStore()
{
itm = new ShoppingItem();
}

public void ProcessOrder()


{
int category;

Console.WriteLine("/-/Arrington Department Store/-/");


Console.WriteLine("Enter the following pieces of");
Console.WriteLine("information about the sale item");
Console.Write("Item #: ");
itm.ItemNumber = long.Parse(Console.ReadLine());
Console.WriteLine("Store Items Categories");
Console.WriteLine("\t1. Women");
Console.WriteLine("\t2. Men");
Console.WriteLine("\t3. Girls");
Console.WriteLine("\t4. Boys");
Console.WriteLine("\t5. Babies");
C# 3.0 Practical Learning 302
Console.Write("Enter the Category: ");
category = int.Parse(Console.ReadLine());
if (category == 1)
itm.Category = ItemCategory.Women;
else if (category == 2)
itm.Category = ItemCategory.Men;
else if (category == 3)
itm.Category = ItemCategory.Girls;
else if (category == 4)
itm.Category = ItemCategory.Boys;
else if (category == 5)
itm.Category = ItemCategory.Babies;
else
itm.Category = ItemCategory.Unspecified;
Console.Write("Item Name: ");
itm.Name = Console.ReadLine();
Console.Write("Item Size (Enter 0 if unknown): ");
itm.Size = Console.ReadLine();
Console.Write("Unit Price: ");
itm.UnitPrice = decimal.Parse(Console.ReadLine());

Console.Write("How many samples of ");


Console.Write(itm.Name);
Console.Write(": ");
qty = int.Parse(Console.ReadLine());
}

public void DisplayReceipt()


{
decimal totalPrice = itm.UnitPrice * Quantity;

Console.WriteLine("\n================================");
Console.WriteLine("/-/Arrington Department Store/-/");
Console.WriteLine("--------------------------------");
Console.WriteLine("Item #: {0}", itm.ItemNumber);
Console.WriteLine("Category: {0}", itm.Category);
Console.WriteLine("Description: {0}", itm.Name);
Console.WriteLine("Item Size: {0}", itm.Size);
Console.WriteLine("Unit Price: {0:C}", itm.UnitPrice);
Console.WriteLine("Quantity: {0}", Quantity);
Console.WriteLine("Total Price: {0:C}\n", totalPrice);
Console.WriteLine("\n================================");
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore2
{
class Program
{
static void Main()
{
C# 3.0 Practical Learning 303
DepartmentStore store = new DepartmentStore();

store.ProcessOrder();
store.DisplayReceipt();
}
}
}

6. Execute the application and test it. Here is an example:

 
/-/Arrington Department Store/-/
Enter the following pieces of
information about the sale item
Item #: 444412
Store Items Categories
1. Women
2. Men
3. Girls
4. Boys
5. Babies
Enter the Category: 1
Item Name: Stretch Cotton Shirt
Item Size (Enter 0 if unknown): 14
Unit Price: 55.95
How many samples of Stretch Cotton Shirt: 2

================================
/-/Arrington Department Store/-/
--------------------------------
Item #: 444412
Category: Women
Description: Stretch Cotton Shirt
Item Size: 14
Unit Price: $55.95
Quantity: 2
Total Price: $111.90

================================
Press any key to continue . . .

7. Close the DOS window

C# 3.0 Practical Learning 304


C# 3.0 Practical Learning 305
Inheritance
 

Introduction to Inheritance
 

Definition
 

Volley Ball Football Basketball Handball Golf

The primary characteristic of the objects on the above pictures is that they are balls
used in different sports. Another characteristic they share is that they are round. On the
other hand, although these balls are used in sport, one made for one sport cannot (or
should not) be used in another sport (of course, it is not unusual for a footballer to
mess with a basketball on a lawn but it is not appropriate). The common characteristics
of these objects can be listed in a group like a C# class. The class would appear as:
class Ball
{
TypeOfSport;
Size;
}

If you were asked to create a class to represent these balls, you may be tempted to
implement a general class that defines each ball. This may be a bad idea because,
despite their round resemblance, there are many internal differences among these balls.
Programming languages like C# provide an alternate solution to this type of situation.

Inheritance consists of creating a class whose primary definition or behavior is based on


another class. In other words, inheritance starts by having a class that can provide
behavior that other classes can improve on.

Practical Learning: Introducing Inheritance

C# 3.0 Practical Learning 306


1. Start Microsoft Visual C# 2005 Express Edition and create a new Console
Application named RealEstate2

2. To create a new class, in the Class View, right-click the name of the project,
position the mouse on Add and click Class...

3. Set the Name to Property and press Enter

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate2
{
public enum PropertyCondition
{
Unknown,
Excellent,
Good,
NeedsRepair,
BadShape
}

public class Property


{

private string propNbr;


private PropertyCondition cond;
private int beds;
private float baths;
private int yr;
private decimal val;

public Property()
{
}

public string PropertyNumber


{
get { return propNbr; }
set
C# 3.0 Practical Learning 307
{
if (propNbr == "")
propNbr = "N/A";
else
propNbr = value;
}
}

public PropertyCondition Condition


{
get { return cond; }
set { cond = value; }
}

public int Bedrooms


{
get
{
if (beds <= 1)
return 1;
else
return beds;
}
set { beds = value; }
}

public float Bathrooms


{
get { return baths; }
set { baths = value; }
}

public int YearBuilt


{
get { return yr; }
set { yr = value; }
}

public decimal Value


{
get { return val; }
set { val = value; }
}
}
}

5. To create a new class, in the Solution Explorer, right-click the name of the project,
position the mouse on Add and click Class...

6. Set the Name to PropertyListing and press Enter

7. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate2
C# 3.0 Practical Learning 308
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,

Condominium
}

public class PropertyListing


{
private Property prop;
private PropertyType tp;

public Property ListProperty


{
get { return prop; }
set { prop = value; }
}

public PropertyType Type


{
get { return tp; }
set { tp = value; }
}

public PropertyListing()
{
prop = new Property();
}

public void CreateListing()


{
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("-=- Property Creation -=-");

Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condonium");
Console.WriteLine("4. Don't Know");
Console.Write("Enter Type of Property: ");
int propType = int.Parse(Console.ReadLine());

Console.Write("\nEnter Property #: ");


ListProperty.PropertyNumber = Console.ReadLine();
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.Write("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
Console.Write("Enter Property Condition: ");
int condition = int.Parse(Console.ReadLine());
if (condition == 1)
ListProperty.Condition = PropertyCondition.Excellent;
else if (condition == 2)
ListProperty.Condition = PropertyCondition.Good;
C# 3.0 Practical Learning 309
else if (condition == 3)
ListProperty.Condition = PropertyCondition.NeedsRepair;
else if (condition == 4)
ListProperty.Condition = PropertyCondition.BadShape;
else
ListProperty.Condition = PropertyCondition.Unknown;

switch ((PropertyType)propType)
{
case PropertyType.SingleFamily:
Type = PropertyType.SingleFamily;
break;

case PropertyType.Townhouse:
Type = PropertyType.Townhouse;
break;

case PropertyType.Condominium:
Type = PropertyType.Condominium;
break;

default:
Type = PropertyType.Unknown;
break;
}

Console.Write("\nHow many bedrooms? ");


ListProperty.Bedrooms = int.Parse(Console.ReadLine());
Console.Write("How many bathrooms? ");
ListProperty.Bathrooms = float.Parse(Console.ReadLine());
Console.Write("Year built: ");
ListProperty.YearBuilt = int.Parse(Console.ReadLine());

Console.Write("Property Value: ");

ListProperty.Value = decimal.Parse(Console.ReadLine());
}

public void ShowProperty()


{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
ListProperty.PropertyNumber);
Console.WriteLine("Property Type: {0}", Type);

switch (Type)
{
case PropertyType.SingleFamily:
case PropertyType.Townhouse:
Type = PropertyType.SingleFamily;
break;

case PropertyType.Condominium:
break;
}

Console.WriteLine("Condition: {0}",
C# 3.0 Practical Learning 310
ListProperty.Condition);
Console.WriteLine("Bedrooms: {0}",
ListProperty.Bedrooms);
Console.WriteLine("Bathrooms: {0}",
ListProperty.Bathrooms);
Console.WriteLine("Year Built: {0}",
ListProperty.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
ListProperty.Value);
Console.WriteLine("==================================");
}
}
}

8. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate2
{
class Program
{
static void Main()
{
PropertyListing listing = new PropertyListing();

listing.CreateListing();
Console.WriteLine("\n");
listing.ShowProperty();
Console.WriteLine();
}
}
}

9. Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 2

Enter Property #: 66DG8P

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 2

C# 3.0 Practical Learning 311


How many bedrooms? 2
How many bathrooms? 1.0
Year built: 1994
Property Value: 325880.75

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 66DG8P
Property Type: Townhouse
Condition: Good
Bedrooms: 2
Bathrooms: 1
Year Built: 1994
Market Value: $325,880.75
==================================

Press any key to continue . . .

10.Close the DOS window

Class Derivation

As you may have guessed, in order to implement inheritance, you must first have a class
that provides the fundamental definition or behavior you need. There is nothing magical
about such a class. It could appear exactly like any of the classes we have used so far.
Here is an example:
using System;

public class Circle


{
private double _radius;

public double Radius


{
get
{
return _radius;
}
set
{
if( _radius < 0 )
_radius = 0.00;
else
_radius = value;
}
}

public double Diameter


{
get
{
return Radius * 2;
}
}

C# 3.0 Practical Learning 312


public double Circumference
{
get
{
return Diameter * 3.14159;
}
}

public double Area


{
get
{
return Radius * Radius * 3.14159;
}
}
}

class Exercise
{
public static int Main()
{
var Round = new Circle();
Round.Radius = 25.55;

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Side: {0}", Round.Radius);
Console.WriteLine("Diameter: {0}", Round.Diameter);
Console.WriteLine("Circumference: {0}", Round.Circumference);
Console.WriteLine("Area: {0}", Round.Area);

return 0;
}
}

This would produce:


Circle Characteristics
Side: 25.55
Diameter: 51.1
Circumference: 160.535249
Area: 2050.837805975
Press any key to continue

The above class is used to process a circle. It can request or provide a radius. It can
also calculate the circumference and the area of a circle. Now, suppose you want to
create a class for a sphere. You could start from scratch as we have done so far. On the
other hand, since a sphere is primarily a 3-dimensional circle, and if you have a class for
a circle already, you can simply create your sphere class that uses the already
implemented behavior of a circle class.

Creating a class that is based on another class is also referred to as deriving a class from
another. The first class serves as parent or base. The class that is based on another

C# 3.0 Practical Learning 313


class is also referred to as child or derived. To create a class based on another, you use
the following formula:
class NewChild : BaseClass
{
// Body of the new class
}

In this formula, you start with the class keyword followed by a name from your class. On
the right side of the name of your class, you must type the : operator, followed by the
name of the class that will serve as parent. Of course, the BaseClass class must have
been defined; that is, the compiler must be able to find its definition. Based on the
above formula, you can create a sphere class based on the earlier mentioned Circle class
as follows:
class Sphere : Circle
{
// The class is ready
}

After deriving a class, it becomes available and you can use it just as you would any
other class. Here is an example:
using System;

class Circle
{
private double _radius;

public double Radius


{
get
{
if( _radius < 0 )
return 0.00;
else
return _radius;
}
set
{
_radius = value;
}
}

public double Diameter


{
get
{
return Radius * 2;
}
}

public double Circumference


{
get
{
return Diameter * 3.14159;
}
}
C# 3.0 Practical Learning 314
public double Area
{
get
{
return Radius * Radius * 3.14159;
}
}
}

class Sphere : Circle


{
}

class Exercise
{
public static int Main()
{
var Round = new Circle();
Round.Radius = 25.55;

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Side: {0}", Round.Radius);
Console.WriteLine("Diameter: {0}", Round.Diameter);
Console.WriteLine("Circumference: {0}", Round.Circumference);
Console.WriteLine("Area: {0}", Round.Area);

var Ball = new Sphere();


Ball.Radius = 25.55;

Console.WriteLine("\nSphere Characteristics");
Console.WriteLine("Side: {0}", Ball.Radius);
Console.WriteLine("Diameter: {0}", Ball.Diameter);
Console.WriteLine("Circumference: {0}", Ball.Circumference);
Console.WriteLine("Area: {0}", Ball.Area);

return 0;
}
}

This would produce:


Circle Characteristics
Side: 25.55
Diameter: 51.1
Circumference: 160.535249
Area: 2050.837805975

Sphere Characteristics
Side: 25.55
Diameter: 51.1
Circumference: 160.535249
Area: 2050.837805975
Press any key to continue

When a class is based on another class, all public (we will also introduce another
inheritance-oriented keyword for this issue) members of the parent class are made
available to the derived class that can use them as easily. While other methods and
classes can also use the public members of a class, the difference is that the derived

C# 3.0 Practical Learning 315


class can call the public members of the parent as if they belonged to the derived class.
That is, the child class doesn't have to "qualify" the public members of the parent class
when these public members are used in the body of the derived class. This is illustrated
in the following program:
using System;

class Circle
{
private double _radius;

public double Radius


{
get
{
if( _radius < 0 )
return 0.00;
else
return _radius;
}
set
{
_radius = value;
}
}

public double Diameter


{
get
{
return Radius * 2;
}
}

public double Circumference


{
get
{
return Diameter * 3.14159;
}
}

public double Area


{
get
{
return Radius * Radius * 3.14159;
}
}

public void ShowCharacteristics()


{
Console.WriteLine("Circle Characteristics");
Console.WriteLine("Side: {0}", Radius);
Console.WriteLine("Diameter: {0}", Diameter);
Console.WriteLine("Circumference: {0}", Circumference);
Console.WriteLine("Area: {0}", Area);
}
}

C# 3.0 Practical Learning 316


class Sphere : Circle
{
public void ShowCharacteristics()
{
// Because Sphere is based on Circle, you can access
// any public member(s) of Circle without qualifying it(them)
Console.WriteLine("\nSphere Characteristics");
Console.WriteLine("Side: {0}", Radius);
Console.WriteLine("Diameter: {0}", Diameter);
Console.WriteLine("Circumference: {0}", Circumference);
Console.WriteLine("Area: {0}\n", Area);
}
}

class Exercise
{
public static int Main()
{
var Round = new Circle();

Round.Radius = 25.55;
Round.ShowCharacteristics();

var Ball = new Sphere();

Ball.Radius = 25.55;
Ball.ShowCharacteristics();

return 0;
}
}

This would produce the same result.

Practical Learning: Inheriting

1. On the main menu, click Project -> Add -> Class...

2. Set the Name to HouseType and press Enter

3. To derive a class, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate2
{
public class HouseType : Property
{
private int nbrOfStories;
private bool basement;
private bool garage;

public int Stories


{
C# 3.0 Practical Learning 317
get { return nbrOfStories; }
set { nbrOfStories = value; }
}

public bool FinishedBasement


{
get { return basement; }
set { basement = value; }
}

public bool IndoorGarage


{
get { return garage; }
set { garage = value; }
}
}
}

4. On the main menu, click Project -> Add -> Class...

5. Set the Name to Condominium and press Enter

6. To create another class based on the Property class, change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate2
{
public class Condominium : Property
{
private bool handicap;

public bool HandicapAccessible


{
get { return handicap; }
set { handicap = value; }
}
}
}

7. Access the PropertyListing.cs file file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate2
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,
Condominium
C# 3.0 Practical Learning 318
}

class PropertyListing
{
private Property prop;
private HouseType hse;
private Condominium cond;
private PropertyType tp;

public Property ListProperty


{
get { return prop; }
set { prop = value; }
}

public HouseType House

{
get { return hse; }
set { hse = value; }
}

public Condominium Condo

{
get { return cond; }
set { cond = value; }
}

public PropertyType Type


{
get { return tp; }
set { tp = value; }
}

public PropertyListing()
{
prop = new Property();
hse = new HouseType();
cond = new Condominium();
}

public void CreateListing()


{
char answer;

Console.WriteLine(" =//= Altair Realty =//=");


Console.WriteLine("-=- Property Creation -=-");
Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condonium");
Console.WriteLine("4. Don't Know");
Console.Write("Enter Type of Property: ");
int propType = int.Parse(Console.ReadLine());

Console.Write("\nEnter Property #: ");


ListProperty.PropertyNumber = Console.ReadLine();
C# 3.0 Practical Learning 319
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.Write("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
Console.Write("Enter Property Condition: ");
int condition = int.Parse(Console.ReadLine());
if (condition == 1)
ListProperty.Condition = PropertyCondition.Excellent;
else if (condition == 2)
ListProperty.Condition = PropertyCondition.Good;
else if (condition == 3)
ListProperty.Condition = PropertyCondition.NeedsRepair;
else if (condition == 4)
ListProperty.Condition = PropertyCondition.BadShape;
else
ListProperty.Condition = PropertyCondition.Unknown;

switch ((PropertyType)propType)
{
case PropertyType.SingleFamily:
Type = PropertyType.SingleFamily;
Console.Write("\nHow many stories (levels)? ");
House.Stories = int.Parse(Console.ReadLine());
Console.Write("Does it have an indoor car garage (y/n):
");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
break;

case PropertyType.Townhouse:
Type = PropertyType.Townhouse;
Console.Write("\nHow many stories (levels)? ");
House.Stories = int.Parse(Console.ReadLine());
Console.Write("Does it have an indoor car garage (y/n):
");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
break;

case PropertyType.Condominium:
C# 3.0 Practical Learning 320
Type = PropertyType.Condominium;
Console.Write("\nIs the building accessible to handicapped (y/n):
");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
Condo.HandicapAccessible = true;
else
Condo.HandicapAccessible = false;
break;

default:
Type = PropertyType.Unknown;
break;
}

Console.Write("\nHow many bedrooms? ");


ListProperty.Bedrooms = int.Parse(Console.ReadLine());
Console.Write("How many bathrooms? ");
ListProperty.Bathrooms = float.Parse(Console.ReadLine());
Console.Write("Year built: ");
ListProperty.YearBuilt = int.Parse(Console.ReadLine());
Console.Write("Property Value: ");
ListProperty.Value = decimal.Parse(Console.ReadLine());
}

public void ShowProperty()


{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
ListProperty.PropertyNumber);
Console.WriteLine("Property Type: {0}", Type);

switch(Type)
{
case PropertyType.SingleFamily:
case PropertyType.Townhouse:
Type = PropertyType.SingleFamily;
Console.WriteLine("Stories: {0}",
House.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
House.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
House.FinishedBasement);
break;

case PropertyType.Condominium:
Console.WriteLine("Handicapped Accessible Building:
{0}",
Condo.HandicapAccessible);
break;
}

Console.WriteLine("Condition: {0}",
ListProperty.Condition);
Console.WriteLine("Bedrooms: {0}",
ListProperty.Bedrooms);

C# 3.0 Practical Learning 321


Console.WriteLine("Bathrooms: {0}",
ListProperty.Bathrooms);
Console.WriteLine("Year Built: {0}",
ListProperty.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
ListProperty.Value);
}
}
}

8. Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condonium
4. Don't Know
Enter Type of Property: 1

Enter Property #: 4LP804

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? 3


Does it have an indoor car garage (y/n): y
Is the basement finished(y/n): n

How many bedrooms? 4


How many bathrooms? 2.5
Year built: 1996
Property Value: 640885.80

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 4LP804
Property Type: SingleFamily
Stories: 3
Has Indoor Car Garage: True
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 4
Bathrooms: 2.5
Year Built: 1996
Market Value: $640,885.80

Press any key to continue . . .

9. Close the DOS window and return to your programming environment


C# 3.0 Practical Learning 322
Implementation of Derived Members 

You can notice in the above example that the derived class produces the same results as
the base class. In reality, inheritance is used to solve various Object-Oriented
Programming (OOP) problems. One of them consists of customizing, adapting, or
improving the behavior of a feature (property or method, etc) of the parent class. For
example, although both the circle and the sphere have an area, their areas are not the
same. A circle is a flat surface but a sphere is a volume, which makes its area very much
higher. Since they use different formulas for their respective area, you should implement
a new version of the area in the sphere. Based on this, when deriving your class from
another class, you should be aware of the properties and methods of the base class so
that, if you know that the parent class has a certain behavior or a characteristic that is
not conform to the new derived class, you can do something about that. A new version
of the area in the sphere can be calculated as follows:
using System;

class Circle
{
private double _radius;

public double Radius


{
get
{
if( _radius < 0 )
return 0.00;
else
return _radius;
}
set
{
_radius = value;
}
}

public double Diameter


{
C# 3.0 Practical Learning 323
get
{
return Radius * 2;
}
}

public double Circumference


{
get
{
return Diameter * 3.14159;
}
}

public double Area


{
get
{
return Radius * Radius * 3.14159;
}
}
}

class Sphere : Circle


{
public double Area
{
get
{
return 4 * Radius * Radius * 3.14159;
}
}
}

class Exercise
{
public static int Main()
{
var Round = new Circle();
Round.Radius = 25.55;

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Side: {0}", Round.Radius);
Console.WriteLine("Diameter: {0}", Round.Diameter);
Console.WriteLine("Circumference: {0}", Round.Circumference);
Console.WriteLine("Area: {0}", Round.Area);

var Ball = new Sphere();


Ball.Radius = 25.55;

Console.WriteLine("\nSphere Characteristics");
Console.WriteLine("Side: {0}", Ball.Radius);
Console.WriteLine("Diameter: {0}", Ball.Diameter);
Console.WriteLine("Circumference: {0}", Ball.Circumference);
Console.WriteLine("Area: {0}", Ball.Area);

return 0;
}
}

C# 3.0 Practical Learning 324


This would produce:
Circle Characteristics
Side: 25.55
Diameter: 51.1
Circumference: 160.535249
Area: 2050.837805975

Sphere Characteristics
Side: 25.55
Diameter: 51.1
Circumference: 160.535249
Area: 8203.3512239

Press any key to continue

Notice that, this time, the areas of both figures are not the same even though their radii
are similar.

Besides customizing member variables and methods of a parent class, you can add new
members as you wish. This is another valuable feature of inheritance. In our example,
while the is a flat shape, a sphere has a volume. In this case, you may need to calculate
the volume of a sphere as a new method or property of the derived class. Here is an
example:
using System;

class Circle
{
private double _radius;

public double Radius


{
get
{
if (_radius < 0)
return 0.00;
else
return _radius;
}
set
{
_radius = value;
}
}
public double Diameter
{
get
{
return Radius * 2;
}
}
public double Circumference
{
get
{
return Diameter * 3.14159;
}
}

C# 3.0 Practical Learning 325


public double Area
{
get
{
return Radius * Radius * 3.14159;
}
}
}

class Sphere : Circle


{
public double Area
{
get
{
return 4 * Radius * Radius * 3.14159;
}
}

public double Volume


{
get
{
return 4 * 3.14159 * Radius * Radius * Radius / 3;
}
}
}

class Exercise
{
public static int Main()
{
var Round = new Circle();
Round.Radius = 25.55;

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Side: {0}", Round.Radius);
Console.WriteLine("Diameter: {0}", Round.Diameter);
Console.WriteLine("Circumference: {0}", Round.Circumference);
Console.WriteLine("Area: {0}", Round.Area);

var Ball = new Sphere();


Ball.Radius = 25.55;

Console.WriteLine("\nSphere Characteristics");
Console.WriteLine("Side: {0}", Ball.Radius);
Console.WriteLine("Diameter: {0}", Ball.Diameter);
Console.WriteLine("Circumference: {0}", Ball.Circumference);
Console.WriteLine("Area: {0}", Ball.Area);
Console.WriteLine("Volume: {0}\n", Ball.Volume);

return 0;
}
}

This would produce:


Circle Characteristics
Side: 25.55
Diameter: 51.1
C# 3.0 Practical Learning 326
Circumference: 160.535249
Area: 2050.837805975

Sphere Characteristics
Side: 25.55
Diameter: 51.1
Circumference: 160.535249
Area: 8203.3512239
Volume: 209595.623770645

Press any key to continue

If you create a property or method in a derived class and that property or method
already exists in the parent class, when you access the property or method in the
derived class, you must make sure you indicate what member you are accessing. To
make this possible, the C# language provides the base keyword. To access a property
or method of a parent class from the derived class, type the base keyword, followed by
the period operator, followed by the name of the property or method of the base class.

The new Modifier

Imagine you create a class used to process a circle as we saw earlier. You can use this
as the base class for a sphere. Both the circle and the sphere have an area but their
values are different. This means that, as mentioned in our introduction to inheritance,
when deriving the sphere class, you would have to calculate a new area for the cube.

If you create or declare a new member in a derived class and that member has the
same name as a member of the base class, when creating the new member, you may
want to indicate to the compiler that, instead of overriding that same method that was
defined in the base class, you want to create a brand new and independent version of
that method. When doing this, you would be asking the compiler to hide the member of
the base class that has the same name, when the member of the current class is
invoked. To do this, type the new keyword to its left. Here is an example:
using System;

class Circle
{
private double _radius;

public double Radius


{
get { return (_radius < 0) ? 0.00 : _radius; }
set { _radius = value; }
}

public double Diameter


{
get { return Radius * 2; }
}

public double Circumference


{
get { return Diameter * 3.14159; }
}

C# 3.0 Practical Learning 327


public double Area
{
get { return Radius * Radius * 3.14159; }
}
}

class Sphere : Circle


{
new public double Area
{
get { return 4 * Radius * Radius * 3.14159; }
}

public double Volume


{
get { return 4 * 3.14159 * Radius * Radius * Radius / 3; }
}
}

class Exercise
{
public static int Main()
{
var Round = new Circle();
Round.Radius = 25.55;

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Side: {0}", Round.Radius);
Console.WriteLine("Diameter: {0}", Round.Diameter);
Console.WriteLine("Circumference: {0}", Round.Circumference);
Console.WriteLine("Area: {0}", Round.Area);

var Ball = new Sphere();


Ball.Radius = 25.55;

Console.WriteLine("\nSphere Characteristics");
Console.WriteLine("Side: {0}", Ball.Radius);
Console.WriteLine("Diameter: {0}", Ball.Diameter);
Console.WriteLine("Circumference: {0}", Ball.Circumference);
Console.WriteLine("Area: {0}", Ball.Area);
Console.WriteLine("Volume: {0}\n", Ball.Volume);

return 0;
}
}

C# 3.0 Practical Learning 328


Polymorphism and
Abstraction
 

Characteristics of Inheritance
 

Namespaces and Inheritance

Imagine you had created a class named Person in a namespace named People as
follows:
Source File: Persons.cs

using System;

namespace People
{
public class Person
{
private string _name;
private string _gdr;

public Person()
{
this._name = "Not Available";
this._gdr = "Unknown";
}

public Person(string name, string gender)


{
this._name = name;
this._gdr = gender;
}

private string FullName


{
get { return _name; }
set { _name = value; }
}

private string Gender


{
get { return _gdr; }
set { _gdr = value; }
}
}
}

C# 3.0 Practical Learning 329


 

If you decide to derive a class from it, remember that this class belongs to a namespace.
To inherit from this class, the compiler will need to know the namespace in which the
class was created. Class inheritance that involves namespaces relies on qualification, like
the calling of the members of a namespace. To derive a class from a class member of a
namespace, type the name of the namespace, followed by the period operator ".", and
followed by the name of the base namespace. Here is an example:
Source File: StaffMembers.cs

using System;

namespace HighSchool
{
public class Teacher : People.Person
{
private string _pos;

public Teacher()
{
this._pos = "Staff Member";
}

public Teacher(string pos)


{
this._pos = pos;
}

private string Position


{
get { return _pos; }
set { _pos = value; }
}
}
}

If you need to call the class that was defined in a different namespace, remember to
qualify its name with the period operator. Here is an example:
Source File: Exercise.cs

using System;

class Exercise
{
public static int Main()
{
People.Person man = new People.Person("Hermine Sandt", "Male");
HighSchool.Teacher staff = new HighSchool.Teacher("Vice
Principal");

Console.WriteLine();
return 0;
}
}

C# 3.0 Practical Learning 330


Alternatively, to use the contents of a namespace, prior to calling a member of that
namespace, you can type the using keyword followed by the name of the
namespace. Here is an example:
Source File: Exercise.cs

using System;
using People;
using HighSchool;

class Exercise
{
public static int Main()
{
Person man = new Person("Hermine Sandt", "Male");
Teacher staff = new Teacher("Vice Principal");

Console.WriteLine();
return 0;
}
}

Practical Learning: Using Inheritance With Namespaces

1. Start Microsoft Visual C# and create a Console Application named Geometry2

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to Square and press Enter

4. Change the file as follows:


 
using System;

namespace Geometry2
{
public class Square
{
private double _side;

public Square()
{
_side = 0.00;
}

public Square(double s)
{
_side = s;
}
}
}

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to Rectangle and press Enter

C# 3.0 Practical Learning 331


7. Change the file as follows:
 
using System;

namespace Geometry2
{
public class Rectangle
{
double _length;
double _height;

public Rectangle()
{
_length = 0.00;
_height = 0.00;
}

public Rectangle(double L, double H)


{
_length = L;
_height = H;
}
}
}

8. Save all

Protected Members

To maintain a privileged relationship with its children, a parent class can make a
member available only to classes derived from it. With this relationship, some members
of a parent class have a protected access level. Of course, as the class creator, it is your
job to specify this relationship.

To create a member that derived classes only can access, type the protected keyword
to its left. Here are examples:
Source File: Persons.cs

using System;

public class Person


{
private string _name;
private string _gdr;

public Person()
{
this._name = "Not Available";
this._gdr = "Unknown";
}
public Person(string name, string gender)
{
this._name = name;
this._gdr = gender;
}

C# 3.0 Practical Learning 332


protected string FullName
{
get { return _name; }
set { _name = value; }
}

protected string Gender


{
get { return _gdr; }
set { _gdr = value; }
}

public void Show()


{
Console.WriteLine("Full Name: {0}", this.FullName);
Console.WriteLine("Gender: {0}", this.Gender);
}
}

You can access protected members only in derived classes. Therefore, if you instantiate
a class outside, you can call only public members:
Source File: Exercise.cs

using System;

class Exercise
{
public static int Main()
{
People.Person man = new People.Person("Hermine Sandt", "Male");

Console.WriteLine("Staff Member");
man.Show();

Console.WriteLine();
return 0;
}
}

This would produce:


Staff Member
Full Name: Hermine Sandt
Gender: Male

If you create a class member and mark it as protected, the classes derived of its parent
class, created in the current program or outside the current program, can access it. If
you want the member to be accessed only by derived classes implemented in the same
program but not derived classes implemented outside of the current program, mark the
member as protected internal. Here are examples:
Source File: Persons.cs

using System;

public class Person


{
private string _name;
private string _gdr;
C# 3.0 Practical Learning 333
public Person()
{
this._name = "Not Available";
this._gdr = "Unknown";
}
public Person(string name, string gender)
{
this._name = name;
this._gdr = gender;
}

protected internal string FullName


{
get { return _name; }
set { _name = value; }
}

protected internal string Gender


{
get { return _gdr; }
set { _gdr = value; }
}

public void Show()


{
Console.WriteLine("Full Name: {0}", this.FullName);
Console.WriteLine("Gender: {0}", this.Gender);
}
}

Virtual Members

We have just mentioned that you can create a new version of a member in a derived
class for a member that already exists in the parent class. After doing this, when you call
that member in your program, you need to make sure that the right member gets called,
the member in the base class or the equivalent member in the derived class.

When you create a base class, if you anticipate that a certain property or method would
need to be redefined in the derived class, you can indicate this to the compiler. On the
other hand, while creating your classes, if you find out that you are customizing a
property or a method that already exists in the base class, you should let the compiler
know that you are providing a new version. In both cases, the common member should
be created as virtual.

To create a virtual member, in the base class, type the virtual keyword to the left of
the property or method. Based on this, the Area property of our Circle class can be
created as follows:

class Circle
{
public virtual double Area
{
get
{

C# 3.0 Practical Learning 334


return Radius * Radius * 3.14159;
}
}
}

In Microsoft Visual C#, unlike C++, if you omit the virtual keyword, the (Microsoft
Visual C#) compiler would display a warning.

When you derive a class from an abstract class, since the methods (if any) of the
abstract class were not implemented, you must implement each one of them in the
derived class. When customizing virtual members in a derived class, to indicate that a
member is already virtual in the base class and that you are defining a new version, type
the override keyword to the left of its declaration. For example, the Area property in
our Sphere class can be created as follows:
class Sphere : Circle
{
public override double Area
{
get
{
return 4 * Radius * Radius * 3.14159;
}
}

public double Volume


{
get
{
return 4 * 3.14159 * Radius * Radius * Radius;
}
}
}

In the same way, when implementing an abstract method of a class, type the override
keyword to its left.

Practical Learning: Using Virtual Members

1. To create a new class, on the main menu, click Project -> Add Class...

2. Set the Name to a ShapeDescription and press Enter

3. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class ShapeDescription
{
public virtual string Description()
{
string Msg = "A quadrilateral is a geometric figure " +
C# 3.0 Practical Learning 335
"that has four sides and four angles.";
return Msg;
}
}
}

4. Save the file as Quadrilaterals.cs in the Shapes1 folder

5. Access the Square.cs file and override the Description method as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Square : ShapeDescription
{
private double _side;

public Square()
{
_side = 0.00;
}

public Square(double s)
{
_side = s;
}

public override string Description()


{
// Get the introduction from the parent
string Introduction = base.Description() +
"\nA square is a quadrilateral that has four " +
"equal sides and four right angles";

return Introduction;
}
}
}

6. Access Rectangle.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Rectangle : ShapeDescription
{
double _length;
double _height;

public Rectangle()
C# 3.0 Practical Learning 336
{
_length = 0.00;
_height = 0.00;
}

public Rectangle(double L, double H)


{
_length = L;
_height = H;
}

public override string Description()


{

// Get the introduction from the parent


string Introduction = base.Description();

string Msg = Introduction +


"\nA rectangle is a quadrilateral that has adjacent "
+
"perpendicular sides. This implies that its four " +
"angles are right.";
return Msg;
}
}
}

7. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Exercise
{
static void DisplaySquare(Square S)
{
Console.WriteLine("Square Characteristics");
Console.WriteLine("Description: {0}", S.Description());
}

static void DisplayRectangle(Rectangle R)


{
Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Description: {0}", R.Description());
}

static void Main()


{
Square Sq = new Square();
Rectangle Rect = new Rectangle();

Console.WriteLine("========================================");
DisplaySquare(Sq);
Console.WriteLine("========================================");
DisplayRectangle(Rect);
Console.WriteLine("========================================");

C# 3.0 Practical Learning 337


Console.WriteLine();
}
}

8. Execute the project. This would produce:


 
========================================
Square Characteristics
Description: A quadrilateral is a geometric figure that has four
sides and four angles. A square is a quadrilateral that has four equal
sides and four right angles
========================================
Rectangle Characteristics
Description: A quadrilateral is a geometric figure that has four
sides and four angles.
A rectangle is a quadrilateral that has adjacent perpendicular sides.
This implies that its four angles are right.
========================================

9. Close the DOS window

Abstract Classes

In a program, you can create a class whose role is only meant to provide fundamental
characteristics for other classes. This type of class cannot be used to declare a variable.
Such a class is referred to as abstract. Therefore, an abstract class can be created only
to serve as a parent class for other classes.

To create an abstract class, type the abstract keyword to the left of its name. Here is
an example:
abstract class Ball
{
protected int TypeOfSport;
protected string Dimensions;
}

Practical Learning: Creating an Abstract Class

1. To create an abstract class, access the ShapeDescription.cs file and change it as


follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public abstract class ShapeDescription
{
public virtual string Description()
{
string Msg = "A quadrilateral is a geometric figure " +
"that has four sides and four angles.";
C# 3.0 Practical Learning 338
return Msg;
}
}
}

2. Save the file

Abstract Properties and Methods

When creating a class that would mainly be used as a base for future inheritance, you
can create one or more properties and make them abstract. To do this, when creating
the property, type the abstract keyword to its left. Because you would not define the
property, you can simply type the get keyword and its semi-colon in the body of the
property.

A method of a class also can be made abstract. An abstract method can be a member of
only an abstract class. If you make a method abstract in a class, you must not
implement the method. To create an abstract method, when creating its class, type the
abstract keyword to the left of the method's name. End the declaration with a semi-
colon and no body for the method since you cannot implement it. Here is an example:
public abstract class Ball
{
protected int TypeOfSport;
protected string Dimensions;

public abstract CalculateArea();


}

In the same way, you can create as many properties and methods as you see fit. You
can choose what properties and methods to make abstract. This is important for
inheritance.

Practical Learning: Creating an Abstract Property

1. To create an abstract property, access the ShapeDescription.cs file and change its
class as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public abstract class ShapeDescription
{
public abstract string Name { get; }

public virtual string Description()


{
string Msg = "A quadrilateral is a geometric figure " +
"that has four sides and four angles.";
return Msg;
}
C# 3.0 Practical Learning 339
}
}

2. Access the Square.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Square : ShapeDescription
{
private double _side;

public Square()
{
_side = 0.00;
}

public Square(double s)
{
_side = s;
}

public override string Name


{
get { return "Square"; }
}

public override string Description()


{
// Get the introduction from the parent
string Introduction = base.Description() +
"\nA square is a quadrilateral that has four " +
"equal sides and four right angles";

return Introduction;
}
}
}

3. Access the Rectangle.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Rectangle : ShapeDescription
{
double _length;
double _height;

C# 3.0 Practical Learning 340


public Rectangle()
{
_length = 0.00;
_height = 0.00;
}

public Rectangle(double L, double H)


{
_length = L;
_height = H;
}

public override string Name


{
get { return "Rectangle"; }
}

public override string Description()


{

// Get the introduction from the parent


string Introduction = base.Description();

string Msg = Introduction +


"\nA rectangle is a quadrilateral that has adjacent
" +
"perpendicular sides. This implies that its four " +
"angles are right.";
return Msg;
}
}
}

4. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Program
{
static void DisplaySquare(Square S)
{
Console.WriteLine("Square Characteristics");
Console.WriteLine("Name: {0}", S.Name);
Console.WriteLine("Description: {0}", S.Description());
}

static void DisplayRectangle(Rectangle R)


{
Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Name: {0}", R.Name);
Console.WriteLine("Description: {0}", R.Description());
}

static void Main()


C# 3.0 Practical Learning 341
{
FlatShapes.Square Sq = new FlatShapes.Square();
FlatShapes.Rectangle Rect = new FlatShapes.Rectangle();

Console.WriteLine("========================================");
DisplaySquare(Sq);

Console.WriteLine("========================================");
DisplayRectangle(Rect);

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

Console.WriteLine();
}
}
}

5. Execute the project. This would produce:


 
========================================
Square Characteristics
Name: Square
Description: A quadrilateral is a geometric figure that has four
sides and four angles. A square is a quadrilateral that has four equal
sides and four right angles
========================================
Rectangle Characteristics
Name: Rectangle
Description: A quadrilateral is a geometric figure that has four sides
and four angles.
A rectangle is a quadrilateral that has adjacent perpendicular sides.
This implies that its four angles are right.
========================================

6. Close the DOS window

Sealed Classes

Any of the classes we have used so far in our lessons can be inherited from. If you
create a certain class and don't want anybody to derive another class from it, you can
mark it as sealed. In other words, a sealed class is one that cannot serve as base for
another class.

To mark a class as sealed, type the sealed keyword to the left of the class keyword.
Here is an example:
public sealed class Ball
{
public int TypeOfSport;
public string Dimensions;
}

There is not much to do about a sealed class. Simply remember that no class can be
derived from it.

C# 3.0 Practical Learning 342


Interfaces
 

Introduction

Imagine you start creating a class and, while implementing or testing it, you find out
that this particular class can be used instead as a general base that other classes can be
derived from. An interface is a special class whose purpose is to serve as a template
that actual classes can be based on. An interface is primarily created like a class: it has a
name, a body and can have members.

To create an interface, instead of the class keyword, you use the interface keyword.
By convention, the name of an interface starts with I. Here is an example:
interface ICourtDimensions
{
}

Practical Learning: Introducing Interfaces

1. On the main menu, click Project -> Add New Item...

2. In the Templates list, click Interface

3. Set the Name to Quadrilateral and click Add

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
interface IQuadrilateral
{
}
}

5. Save the file

The Members of an Interface

As done for a class, the members of an interface are listed in its body. In an interface,
you cannot declare fields like those we have used in other classes. Instead, if you want
some type of member variable, you can create a property. If you create a property in an
interface, you cannot define that property. One of the rules of an interface is that you
cannot define any of its members. This is also valid for its properties. Therefore, if you
create a property in an interface:

C# 3.0 Practical Learning 343


 You can indicate that it would be read-only by adding an empty getter property to
it. Here is an example:
 
public interface ICourtDimensions
{
double Length { get; }
}

 You can indicate that it would be write-only by adding an empty setter property to
it. Here is an example:
 
public interface ICourtDimensions
{
double Length { set; }
}

 You can indicate that it would be used to write values to it and to read values from
it. To provide this information, add a getter and a setter accessories to it. Here is
an example:
 
public interface ICourtDimensions
{
double Length { get; set; }
}

In the same way, you can create as many properties as you judge necessary in an
interface. Besides the properties, an interface can also have other types of members
such as methods. Here is an example of an interface that has one read-only property
named NameOfSport, one read/write property named NumberOfPlayers, and one
method named SportCharacteristics:
public interface IBall
{
int NumberOfPlayers
{
get;
set;
}

string NameOfSport
{
get;
}

void SportCharacteristics();
}

Practical Learning: Creating Members of an Interface

1. To create a property, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
C# 3.0 Practical Learning 344
using System.Text;

namespace Geometry2
{
interface IQuadrilateral
{
double Area { get; }
}
}

2. Save the file

An Interface as a Base Class


An interface is used to lay a foundation for other classes. For this reason, it is the prime
candidate for class derivation. To derive from an interface, use the same technique we
have applied in inheritance so far. Here is an example of a class named SportBall that
derives from an interface named ISportType:
public class SportBall : ISportType
{
int players;
string sport;
}

Just as you can derive a class from an interface, you can create an interface that itself is
based on another interface. Here is an example:
public interface ISportType : IBall
{
SportCategory Type
{
get;
}
}

The C# language doesn't allow multiple inheritance, which is the ability to create a class
based on more than one class. Multiple inheritance is allowed only if the bases are
interfaces. To create multiple inheritance, separate the names of interface, with a
comma. Here is an example:
public interface ISportType : IBall, ICourtDimensions
{
SportCategory Type
{
get;
}
}

You can also involve a class as parent in a multiple inheritance scenario but there must
be only one class. Here is an example in which a class called Sports derives from one
class and various interfaces:
public interface Sports: Player, IBall, ICourtDimensions
{
}

Practical Learning: Inheriting From an Interface


C# 3.0 Practical Learning 345
1. On the main menu, click Project -> Add New Item...

2. In the Templates list, click Interface

3. Set the Name to RightAngle and click Add

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
interface IRightAngle : IQuadrilateral
{
double Base { get; set; }
double Height { get; set; }
double Perimeter { get; }
}
}

5. Access the Square.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Square : ShapeDescription, IRightAngle
{
. . .
}
}

6. Access the Rectangle.cs file and change it as follows:


 
using System;

namespace Geometry2
{
public class Rectangle : ShapeDescription, IRightAngle
{
. . .
}
}

7. Save all

Implementation of Derived Classes of an Interface

C# 3.0 Practical Learning 346


After creating an interface, you can derive other interfaces or other classes from it. If
you are deriving other interfaces from an interface, you can just proceed as you see fit.
For example, you can add or not add one or more new properties, you can add or not
add one or more methods, etc. Here is an example:
Source File: Preparation.cs

public enum SportCategory


{
SinglePlayer,
Collective,
Unknown
}

public interface ICourtDimensions


{
double Length { get; set; }
double Width { get; set; }
}

public interface IBall


{
int NumberOfPlayers
{
get;
set;
}

string NameOfSport
{
get;
}

void SportCharacteristics();
}

public interface ISportType : IBall, ICourtDimensions


{
SportCategory Type
{
get;
}
}

If you derive a class, from an interface, you must implement all properties that were
created in the interface. This means that you must define them so that, when a variable
is declared of that class, the properties have meaning. In the same way, if you create a
class that is based on an interface, you must implement all methods that were declared
in the interface. If you derive a class from an interface that itself was derived from
another interface, in your class, you must define all properties that were created in the
whole parental lineage and you must implement all methods that were created in the
parent and grant-parent interfaces. Here is an example:
Source File: Sport.cs

using System;

public class SportBall : ISportType


{
C# 3.0 Practical Learning 347
int players;
string sport;
SportCategory _type;
double Len;
double Wdt;

public SportBall(int nbr, SportCategory tp, string name)


{
players = nbr;
_type = tp;
sport = name;
}

public int NumberOfPlayers


{
get { return players;}
set { players = value;}
}

public string NameOfSport


{
get { return sport; }
}

public SportCategory Type


{
get { return _type; }
}

public double Length


{
get { return Len; }
set { Len = value; }
}

public double Width


{
get { return Wdt; }
set { Wdt = value; }
}

public void SportCharacteristics()


{
Console.WriteLine("Sport Characteristics");
Console.WriteLine("Name of Sport: {0}", NameOfSport);
Console.WriteLine("Type of Sport: {0}", Type);
Console.WriteLine("# of Players: {0}", NumberOfPlayers);
Console.WriteLine("Court Dimensions: {0}m x {1}m", Len,
Wdt);
}
}

Once the class is ready, you can then use it as you see fit. Here is an example:
Source File: Exercise.cs

using System;

class Exercise
{

C# 3.0 Practical Learning 348


public static int Main()
{
SportBall volley = new SportBall(6,
SportCategory.Collective,
"Volley Ball");
volley.Length = 18;
volley.Width = 9;
volley.SportCharacteristics();

Console.WriteLine();

SportBall tennis = new SportBall(1,


SportCategory.SinglePlayer,
"Table Tennis");
tennis.Length = 23.7;
tennis.Width = 8.25;
tennis.SportCharacteristics();

Console.WriteLine();
return 0;
}
}

This would produce:


Sport Characteristics
Name of Sport: Volley Ball
Type of Sport: Collective
# of Players: 6
Court Dimensions: 18m x 9m

Sport Characteristics
Name of Sport: Table Tennis
Type of Sport: SinglePlayer
# of Players: 1
Court Dimensions: 23.7m x 8.25m

Practical Learning: Implementing Derived Members of an Interface

1. Access the Square.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Square : ShapeDescription, IRightAngle
{
private double _side;

public Square()
{
_side = 0.00;
}

public Square(double s)
C# 3.0 Practical Learning 349
{
_side = s;
}

public override string Name


{
get { return "Square"; }
}

public override string Description()


{
// Get the introduction from the parent
string Introduction = base.Description() + " " +
"A square is a quadrilateral that has four " +
"equal sides and four right angles";

return Introduction;
}

public double Base


{
get { return (_side < 0) ? 0.00 : _side; }
set { _side = value; }
}

public double Height


{
get { return (_side < 0) ? 0.00 : _side; }
set { _side = value; }
}

public double Area


{
get { return Base * Base; }
}

public double Perimeter


{
get { return Base * 4; }
}
}
}

2. Access the Rectangle.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
{
public class Rectangle : ShapeDescription, IRightAngle
{
double _length;
double _height;

public Rectangle()
{
C# 3.0 Practical Learning 350
_length = 0.00;
_height = 0.00;
}

public Rectangle(double L, double H)


{
_length = L;
_height = H;
}

public override string Name


{
get { return "Rectangle"; }
}

public override string Description()


{
// Get the introduction from the parent
string Introduction = base.Description();

string Msg = Introduction + " " +


"\nA rectangle is a quadrilateral that has adjacent " +
"perpendicular sides. This implies that its four " +
"angles are right.";
return Msg;
}

public double Base


{
get { return _length; }
set { _length = value; }
}

public double Height


{
get { return _height; }
set { _height = value; }
}

public double Area


{
get{ return Base * Height; }
}

public double Perimeter


{
get { return 2 * (Base + Height); }
}
}
}

3. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry2
C# 3.0 Practical Learning 351
{
public class Program
{
static Square CreateASquare()
{
double side;

Console.Write("Enter the side of the square: ");


side = double.Parse(Console.ReadLine());

Square Sqr = new Square(side);


return Sqr;
}

static void DisplaySquare(Square S)


{
Console.WriteLine("Square Characteristics");
Console.WriteLine("Name: {0}", S.Name);
Console.WriteLine("Description: {0}", S.Description());
Console.WriteLine("----------------------------");
Console.WriteLine("Side: {0}", S.Base);
Console.WriteLine("Perimeter: {0}", S.Perimeter);
Console.WriteLine("Area: {0}", S.Area);
}

static Rectangle CreateARectangle()


{
double Len, Hgt;

Console.WriteLine("Enter the dimensions of the rectangle");


Console.Write("Base: ");
Len = double.Parse(Console.ReadLine());
Console.Write("Height: ");
Hgt = double.Parse(Console.ReadLine());

Rectangle Recto = new Rectangle(Len, Hgt);


return Recto;
}

static void DisplayRectangle(Rectangle R)


{
Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Name: {0}", R.Name);
Console.WriteLine("Description: {0}", R.Description());
Console.WriteLine("----------------------------");
Console.WriteLine("Base: {0}", R.Base);
Console.WriteLine("Height: {0}", R.Height);
Console.WriteLine("Perimeter: {0}", R.Perimeter);
Console.WriteLine("Area: {0}", R.Area);
}

static int Main()


{
Square Sq = new Square();
Rectangle Rect = new Rectangle();

Sq = CreateASquare();
Rect = CreateARectangle();

Console.WriteLine("============================");
C# 3.0 Practical Learning 352
DisplaySquare(Sq);
Console.WriteLine("============================");
DisplayRectangle(Rect);
Console.WriteLine("============================");

Console.WriteLine();
return 0;
}
}
}

4. Execute the application and test it. Here is an example:


 
Enter the side of the square: 44.16
Enter the dimensions of the rectangle
Base: 58.62
Height: 36.06
============================
Square Characteristics
Name: Square
Description: A quadrilateral is a geometric figure that has
four sides and four angles. A square is a quadrilateral that
has four equal sides and four right angles
----------------------------
Side: 44.16
Perimeter: 176.64
Area: 1950.1056
============================
Rectangle Characteristics
Name: Rectangle
Description: A quadrilateral is a geometric figure that has
four sides and four angles.
A rectangle is a quadrilateral that has adjacent perpendicular
sides. This implies that its four angles are right.
----------------------------
Base: 58.62
Height: 36.06
Perimeter: 189.36
Area: 2113.8372
============================

Press any key to continue . . .

5. Close the DOS window

Class Partial Implementation

In all of the classes we have defined so far, we were using a single file to implement the
class. In C#, you can create a class (the same class) in different files. This means that
you can start a class in one file and continue it in another file or in other files. This is
referred to as partial implementation.

If you have programmed in C++ or C++/CLI, don't confuse its header and
source files with C#'s partial implementation of classes. In C++ or C++/CLI, you
can include the structure of a class with its member variables (called fields in
C#) and the declaration of its methods. In C++, a header file has the
C# 3.0 Practical Learning 353
extension .h. Here is an example of a C++/CLI header file:
Header File: Cylinder.h

#pragma once

using namespace System;

public ref class CCylinder


{
private:
double rad;
double hgt;

public:
CCylinder(void);
CCylinder(double radius, double height);

property double Radius


{
double get() { return rad; }
void set(double value) { rad = value; }
}

property double Height


{
double get() { return hgt; }
void set(double value) { hgt = value; }
}

double Volume();
};

In C++, after creating a header file, you can create its associated source file.
The source file has the extention .cpp. Here is an example of the source file
corresponding to the above header file:
Source File: Cylinder.cpp

#include "Cylinder.h"

CCylinder::CCylinder(void)
: rad(0.00), hgt(0.00)
{
}

CCylinder::CCylinder(double radius, double height)


: rad(radius), hgt(height)
{
}

double CCylinder::Volume()
{
return rad * rad * hgt * Math::PI;
}

The above class can be tested with the following:


Source File: Exercise.cpp

C# 3.0 Practical Learning 354


#include "Cylinder.h"

using namespace System;

CCylinder ^ Initialize()
{
CCylinder ^ c = gcnew CCylinder(36.12, 18.84);
return c;
}

const void Show(CCylinder ^ vol)


{
Console::WriteLine(L"Radius: {0}", vol->Radius);
Console::WriteLine(L"Height: {0}", vol->Height);
Console::WriteLine(L"Volume: {0}", vol->Volume());
}

int main()
{
CCylinder ^ cyl = Initialize();
Show(cyl);

return 0;
}

As we have seen so far, in C#, you cannot simply and only declare a method in a file for
a forward (later) implementation, as it's done in C, C++, C++/CLI, and (Object) Pascal.
In C#, to create a class in various classes, start the class in one file but precede the
class keyword with partial. Here is an example of a file named first.cs that contains
some (2) private fields and some (2) properties:
Source File: geometry1.cs

using System;

partial class Cylinder


{
private double rad;
private double hgt;

public Cylinder(double radius, double height)


{
this.rad = radius;
this.hgt = height;
}

public double Radius


{
get { return rad; }
set { rad = value; }
}

public double Height


{
get { return hgt; }
set { hgt = value; }
}
C# 3.0 Practical Learning 355
}

After creating the class in one file, you can use as any of the classes as we have done so
far. Here is an example:
Source File: Exercise.cs

using System;

class Program
{
static Cylinder Initialize()
{
Cylinder c = new Cylinder(36.12, 18.84);
return c;
}

static void Show(Cylinder vol)


{
Console.WriteLine("Radius: {0}", vol.Radius);
Console.WriteLine("Height: {0}", vol.Height);
}

static int Main()


{
Cylinder cyl = Initialize();

Show(cyl);

Console.WriteLine();
return 0;
}
}

This would produce:


Radius: 36.12
Height: 18.84

Press any key to continue . . .

If you had created a partial class, or you got a partial class from somebody (not as part
of a DLL or nor from another type of library), and you find out that the class is not
complete, you can then complement it. One of the rules you must observe is that the
partial class must have been marked as partial, as we did above. One of the
advantages of partial implementation is that you don't have to get back to the first or
previous file to modify it in order to complement the class. You can simply start another
file and continue the class in it. Two other rules you must observe are that you must use
the same name for the class and you must precede the class keyword with partial.
Here is an example:
Source File: geometry2.cs

using System;

partial class Cylinder


{
public Cylinder()
{

C# 3.0 Practical Learning 356


this.rad = 0.00;
this.hgt = 0.00;
}

public double Volume()


{
return rad * rad * hgt * Math.PI;
}
}

This class can then be tested as follows:


Source File: Exercise.cs

using System;

class Program
{
static Cylinder Initialize()
{
Cylinder c = new Cylinder();

c.Radius = 42.66;
c.Height = 26.48;

return c;
}

static void Show(Cylinder vol)


{
Console.WriteLine("Radius: {0}", vol.Radius);
Console.WriteLine("Height: {0}", vol.Height);
Console.WriteLine("Volume: {0}", vol.Volume());
}

static int Main()


{
Cylinder cyl = Initialize();

Show(cyl);

Console.WriteLine();
return 0;
}
}

This would produce:


Radius: 42.66
Height: 26.48
Volume: 151394.310951986

Press any key to continue . . .

Once a partial class has been created, you can create another based on it. The child
class doesn't have to be partial, although it can be.

Practical Learning: Partially Implementing a Class

C# 3.0 Practical Learning 357


1. Start Microsoft Visual C# and create a Console Application named Geometry3

2. To add a new source file, on the main menu, click Project -> Add New Item...

3. In the Templates list, click Code File

4. Set the Name to circle1 and click Add

5. Change the file as follows:


 
public partial class Circle
{
private double _radius;

public double Radius


{
get { return (this._radius <= 0) ? 0.00 : this._radius; }
set { this._radius = value; }
}

public double Diameter


{
get { return this.Radius * 2; }
}

public double Circumference


{
get { return Diameter * 3.14159; }
}

public double Area


{
get { return this.Radius * this.Radius * 3.14159; }
}
}

6. To create a new source file, in the Solution Explorer, right-click Geometry3 -> Add
-> New Item...

7. In the Templates list, make sure Code File is selected; otherwise, click it.
Set the Name to circle2 and click Add

8. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public partial class Circle


{
public Circle()
{
this.Radius = 0.00;
}

public Circle(double radius)

C# 3.0 Practical Learning 358


{
this.Radius = radius;
}

public void Present()


{
Console.WriteLine("Radius: {0}", this.Radius);
Console.WriteLine("Diameter: {0}", this.Diameter);
Console.WriteLine("Circumference: {0}", this.Circumference);
Console.WriteLine("Area: {0}", this.Area);
}
}

9. To test the class, access the Program.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry3
{
class Program
{
static Circle Initialize()
{
Console.Write("Enter the radius: ");
double rad = double.Parse(Console.ReadLine());

Circle c = new Circle(rad);


return c;
}

static int Main()


{
Console.WriteLine(
"This application allows you to process a circle");
Circle circ = Initialize();

Console.WriteLine("\n==============================");
Console.WriteLine("Circle Characteristics");
Console.WriteLine("------------------------------");
circ.Present();
Console.WriteLine("==============================\n");

return 0;
}
}
}

10.Execute the application to sew the result. Here is an example:


 
This application allows you to process a circle
Enter the radius: 10.08

==============================
Circle Characteristics
------------------------------
C# 3.0 Practical Learning 359
Radius: 10.08
Diameter: 20.16
Circumference: 63.3344544
Area: 319.205650176
==============================

Press any key to continue . . .

11.Return to your programming environment

12.To create a new source file, on the main menu, click Project -> Add New Item...

13.In the Templates list, make sure Code File is selected; otherwise, click it.
Set the Name to cylinder1 and press Enter

14.Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public partial class Cylinder : Circle


{
private double hgt;

public double Height


{
get { return (this.hgt <= 0) ? 0.00 : this.hgt; }
set { this.hgt = value; }
}

public double LateralArea


{
get { return this.Circumference * Height; }
}

public double TotalArea


{
get { return this.Area + this.LateralArea; }
}

public double Volume


{
get
{
return this.Radius * this.Radius * this.Height * Math.PI;
}
}
}

15.To create a new source file, in the Solution Explorer, right- click Geometry3 -> Add
-> New Item...

16.In the Templates list, make sure Code File is selected; otherwise, click it.
Set the Name to cylindder2 and click Add

C# 3.0 Practical Learning 360


17.Change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public partial class Cylinder : Circle


{
// This is the default constructor of the cylinder
// This constructor assumes that we don't have any dimension
public Cylinder()
{
this.Radius = 0.00;
}

// This constructor assumes that there exists a radius


// The radius could have been specified on a parent circle
public Cylinder(double height)
{
this.Height = height;
}

// This constructor can be used to specify both


// the radius of the base and the height of the volume
// The radius can also have been defined by a parent circle
public Cylinder(double radius, double height)
{
this.Radius = radius;
this.Height = height;
}

new public void Present()


{
Console.WriteLine("Height: {0}", this.Height);
Console.WriteLine("Lateral Area: {0}", this.LateralArea);
Console.WriteLine("Total Area: {0}", this.TotalArea);
Console.WriteLine("Volume: {0}", this.Volume);
}
}

18.To test the class, access the Program.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geometry3
{
class Program
{
static Circle Initialize()
{
Console.Write("Enter the radius: ");
double rad = double.Parse(Console.ReadLine());

Circle c = new Circle(rad);


C# 3.0 Practical Learning 361
return c;
}

static double GetHeight()


{
Console.Write("Enter the height: ");
double hgt = double.Parse(Console.ReadLine());

return hgt;
}

static int Main()


{
Console.WriteLine(
"This application allows you to process a cylinder");
Circle circ = Initialize();
double height = GetHeight();
Cylinder cldr = new Cylinder(circ.Radius, height);

Console.WriteLine("\n================================");
Console.WriteLine("=//=Cylinder Characteristics=//=");
Console.WriteLine("================================");
Console.WriteLine(" =-= Base Characteristics =-=");
Console.WriteLine("--------------------------------");
circ.Present();
Console.WriteLine("------------------------------");
Console.WriteLine("=-= Volume Characteristics =-=");
cldr.Present();
Console.WriteLine("================================\n");

return 0;
}
}
}

19.Execute the application to sew the result. Here is an example:


 
This application allows you to process a cylinder
Enter the radius: 85.15
Enter the height: 44.95

================================
=//=Cylinder Characteristics=//=
================================
=-= Base Characteristics =-=
--------------------------------
Radius: 85.15
Diameter: 170.3
Circumference: 535.012777
Area: 22778.168980775
------------------------------
=-= Volume Characteristics =-=
Height: 44.95
Lateral Area: 24048.82432615
Total Area: 46826.993306925
Volume: 1023879.5605199
================================

Press any key to continue . . .


C# 3.0 Practical Learning 362
20.Return to your programming environment

C# 3.0 Practical Learning 363


Delegates and Events
 

Fundamentals of Delegates
 

Introduction

The C and C++ languages have long used the concept of function pointer. This was
even more useful when programming for the Microsoft Windows operating systems
because the Win32 library relies on the concept of callback functions. Callback functions
are used in Microsoft Windows programming to process messages. For this reason and
because of their functionality, callback functions were carried out in the .NET Framework
but they were defined with the name of delegate.

A delegate is a special type of user-defined variable that is declared globally, like a


class. A delegate provides a template for a method, like an interface provides a template
for a class. Like an interface, a delegate is not defined. Its role is to show what a useful
method would look like. To support this concept, a delegate can provide all the
necessary information that would be used on a method. This includes a return type, no
argument or one or more arguments.

Practical Learning: Introducing Delegates

1. Start Microsoft Visual C# and create a Console Application named WattsALoan1

2. To create a new class, on the main menu, click Project -> Add Class...

3. Change the name of the file to LoanEvaluation and click Add

4. Change the contents of the file as follows:


 

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WattsALoan1
{
public class LoanEvaluation
{
public double GetPrincipal()
{
Console.Write("Enter the Principal: $");
C# 3.0 Practical Learning 364
double P = double.Parse(Console.ReadLine());

return P;
}

public double GetInterestRate()


{
Console.Write("Enter the Interest Rate (%): ");
double r = double.Parse(Console.ReadLine());

return r;
}

public int GetPeriod()


{
Console.Write("Enter the number of months: ");
int t = int.Parse(Console.ReadLine());

return t;
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WattsALoan1
{
public class Program
{
static int Main()
{
int NumberOfPeriods;
double Principal, IntRate;
LoanEvaluation loan = new LoanEvaluation();

Console.WriteLine(
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%");
Console.WriteLine("Loan Processing\n");
Console.WriteLine(
"This program allows you to calculate the amount of money a
");
Console.WriteLine(
"customer will owe at the end of the lifetime of a loan\n");

Principal = loan.GetPrincipal();
IntRate = loan.GetInterestRate();
NumberOfPeriods = loan.GetPeriod();
Console.WriteLine(
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%\n");

Console.WriteLine("================================");
Console.WriteLine("Loan Estimation");
C# 3.0 Practical Learning 365
Console.WriteLine("--------------------------------");
Console.WriteLine("Principal: {0:C}", Principal);
Console.WriteLine("Interest: {0:P}", IntRate / 100);
Console.WriteLine("Period: {0} months", NumberOfPeriods);
Console.WriteLine("================================\n");

return 0;
}
}
}

6. Execute the application test it.


Here is an example:
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Loan Processing

This program allows you to calculate the amount of money a


customer will owe at the end of the lifetime of a loan

Enter the Principal: $14500


Enter the Interest Rate (%): 12.25
Enter the number of months: 48
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

================================
Loan Estimation
--------------------------------
Principal: $14,500.00
Interest: 12.25 %
Period: 48 months
================================

Press any key to continue . . .

7. Close the DOS window

8. In the above program, the clerk was asked to provide the number of months for
the period of the loan. Depending on the loan, one customer may want to specify
the number of days necessary to pay the loan. Another customer may want to pay
a loan over a number of years. To make this possible, we will allow the clerk to
select the type of period for a loan.
Access the LoanProcecssing.cs file and change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WattsALoan1
{
class LoanEvaluation
{
public double GetPrincipal()
{
Console.Write("Enter the Principal: $");
double P = double.Parse(Console.ReadLine());
C# 3.0 Practical Learning 366
return P;
}

public double GetInterestRate()


{
Console.Write("Enter the Interest Rate (%): ");
double r = double.Parse(Console.ReadLine());

return r;
}

public void GetPeriod(ref int TypeOfPeriod, ref int Periods)


{
Console.WriteLine("How do you want to enter the length of
time?");
Console.WriteLine("1 - In Days");
Console.WriteLine("2 - In Months");
Console.WriteLine("3 - In Years");
Console.Write("Your Choice: ");
TypeOfPeriod = int.Parse(Console.ReadLine());

if (TypeOfPeriod == 1)
{
Console.Write("Enter the number of days: ");
Periods = int.Parse(Console.ReadLine());
}
else if (TypeOfPeriod == 2)
{
Console.Write("Enter the number of months: ");
Periods = int.Parse(Console.ReadLine());
}
else if (TypeOfPeriod == 3)
{
Console.Write("Enter the number of years: ");
Periods = int.Parse(Console.ReadLine());
}
else
{
TypeOfPeriod = 0;
// The user made an invalid selection. So, we will give
up
Console.WriteLine("Bad Selection\n");
}
}
}
}

9. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WattsALoan1
{
public class Program
{
C# 3.0 Practical Learning 367
static int Main()
{
int Periods = 0;
int TypeOfPeriod = 0;
double Principal, IntRate;
string PeriodName = null;
LoanEvaluation loan = new LoanEvaluation();

Console.WriteLine(
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
Console.WriteLine(
"This program allows you to calculate the amount of money a ");
Console.WriteLine(
"customer will owe at the end of the lifetime of a loan\n");

Console.WriteLine("Loan Processing\n");
Principal = loan.GetPrincipal();
IntRate = loan.GetInterestRate();

loan.GetPeriod(ref TypeOfPeriod, ref Periods);


if (TypeOfPeriod == 0)
{
// Since the user made a bad selection, stop the program
here
return 0;
}// Since this "if" condition has a "return 0" line, if the
"if"
// condition produces true, the "return 0" means the function
// would be terminated. If the condition is false, the inside
of
// this "if" condition would not execute and the function
would
// continue. This means that, if the condition is false, then
// the "else' is implied. Therefore, we don't have to write
an
// "else" condition: it is automatic.

if (TypeOfPeriod == 1)
{
PeriodName = "days";
}
else if (TypeOfPeriod == 2)
{
PeriodName = "months";
}
else if (TypeOfPeriod == 3)
{
PeriodName = "years";
}

Console.WriteLine(
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");

Console.WriteLine("==================================");
Console.WriteLine("Loan Estimation");
Console.WriteLine("----------------------------------");
Console.WriteLine("Principal: {0:C}", Principal);
Console.WriteLine("Interest: {0:P}", IntRate / 100);
Console.WriteLine("Period: {0} {1}", Periods, PeriodName);
Console.WriteLine("==================================\n");
C# 3.0 Practical Learning 368
return 0;
}
}
}

10.Execute the application and test it. Here is an example:


 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
This program allows you to calculate the amount of money a
customer will owe at the end of the lifetime of a loan

Loan Processing

Enter the Principal: $7500.00


Enter the Interest Rate (%): 8.75
How do you want to enter the length of time?
1 - In Days
2 - In Months
3 - In Years
Your Choice: 3
Enter the number of years: 4
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
==================================
Loan Estimation
----------------------------------
Principal: $7,500.00
Interest: 8.75 %
Period: 4 years
==================================

Press any key to continue . . .

11.Close the DOS window

Creating a Delegate

To create a delegate, you use the delegate keyword. The basic formula used to create
a delegate is:
[attributes] [modifiers] delegate ReturnType Name ([formal-parameters]);

The attributes factor can be a normal C# attribute.

The modifier can be one or an appropriate combination of the following keywords: new,
public, private, protected, or internal.

The delegate keyword is required.

The ReturnType can be any of the data types we have used so far. It can also be a type
void or the name of a class.

The Name must be a valid C# name.

Because a delegate is some type of a template for a method, you must use parentheses,
required for every method. If this method will not take any argument, leave the
parentheses empty.
C# 3.0 Practical Learning 369
Here is an example:
using System;

public delegate void Simple();

public class Program


{
static int Main()
{
return 0;
}
}

After declaring a delegate, it only provides a template for a method, not an actual
method. In order to use it, you must define a method that would carry an assignment to
perform. That method must have the same return type and the same (number of)
argument(s), if any. For example, the above declared delegate is of type void and it
does not take any argument. you can define a corresponding method as follows:
public delegate void Simple();

public class Exercise


{
public void Welcome()
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}
}

With such a method implemented, you can associate it to the name of the delegate. To
do that, where you want to use the method, declare a variable of the type of the
delegate and assign the method to the delegate variable. Because you are assigning the
method to a delegate, one of the rules of delegates is that you must not apply the
parentheses to the method. Here is an example
public class Program
{
static int Main()
{
Exercise exo = new Exercise();

Simple msg = exo.Welcome;

return 0;
}
}

Accessing a Delegate
 

Introduction

Once you have assigned a method to a delegate variable, you can you the delegate
variable as if it were a defined method. That is, you can call as you would a normal
method. Here is an example:
C# 3.0 Practical Learning 370
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public delegate void Simple();

public class Exercise


{
public void Welcome()
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}
}

namespace Delegates
{
public class Program
{
static int Main()
{
Exercise exo = new Exercise();

Simple msg = exo.Welcome;

msg();

return 0;
}
}
}

This would produce:


Welcome to the Wonderful World of C# Programming!
Press any key to continue . . .

A Static Method for a Delegate

In the above example, we had to declare a variable of the (Exercise) class before
accessing the method. An alternative is to create the associated method as static. That
way, you would not need to declare the variable first. Here is an example:
using System;

public delegate void Simple();

public class Exercise


{
public static void Welcome()
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}
}

public class Program


{
C# 3.0 Practical Learning 371
static int Main()
{
Simple msg = Exercise.Welcome;

msg();

return 0;
}
}

An Anonymous Delegate

In the above examples, we had to create a method that would be associated with a
delegate. You can create a delegate, then, when you need to use, create a type of local
implementation of a method and use it. In other words, you do not have to explicitly
define a method prior to using the delegate. Such a method is referred to as anymous.

Before implementing an anonymous method, first declare the delegate you will use:
using System;

public delegate void Simple();

public class Program


{
static int Main()
{
return 0;
}
}

To create an anonymous method, declare a variable for the delegate and assign it the
delegate keyword as if it were a method. That is, followed by parentheses and curly
brackets that would represent the body of the method. In the body of the anonymous
method, do whatever you want. Here is an example:
using System;

public delegate void Simple();

public class Program


{
static int Main()
{
Simple msg = delegate()
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
};

return 0;
}
}

Once you have done this, you can then call the delegate variable as if it were a normal
method. Here is an example:
using System;

C# 3.0 Practical Learning 372


public delegate void Simple();

public class Program


{
static int Main()
{
Simple msg = delegate()
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
};

msg();

return 0;
}
}

The Lambda Operator

You can also create an anonymous method using an operator called lambda and
represented by =>. From our example above, to use the lambda operator to create an
anonymous method, omit the delegate keyword and follow the parentheses by the
operator. Here is an example:
using System;

public delegate void Simple();

public class Program


{
static int Main()
{
Simple msg = () =>
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
};

return 0;
}
}

Once you have done this, you can call the delegate variable as a method. Here is an
example:
using System;

public delegate void Simple();

public class Program


{
static int Main()
{
Simple msg = () =>
{

C# 3.0 Practical Learning 373


Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
};

msg();

return 0;
}
}

A Delegate that Returns a Value

You can create a delegate that returns a value. When creating the delegate, specify the
data type to the left side of the name of the delegate. When defining a method that
would be associated with the delegate, remember that the method must return the
same type of value. In the body of the method, use it as you see fit. Before exiting the
method, make sure you appropriately return a value.

To use the method, follow the same approach as above. This time, when calling the
delegate variable, you should use the parentheses. Here is an example:
using System;

delegate double Doubler();

public class Exercise


{
public static double MultiplyBy2()
{
return 255 * 2;
}
}

public class Program


{
static int Main()
{
Doubler By2 = Exercise.MultiplyBy2;

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

return 0;
}
}

This would produce:


Number = 510
Press any key to continue . . .

In the same way, you can create an anonymous method that implements the delegate.
To do this, follow the same rule we defined earlier. For example, you can use the
delegate keyword. Here is an example:
using System;

delegate double Doubler();

C# 3.0 Practical Learning 374


public class Program
{
static int Main()
{
Doubler By2 = delegate()
{
return 255 * 2;
};

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

return 0;
}
}

Or you can use the lambda operator:


using System;

delegate double Doubler();

public class Program


{
static int Main()
{
Doubler By2 = () =>
{
return 255 * 2;
};

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

return 0;
}
}

Delegates Compositions

One of the characteristics that set delegates apart from C/C++ function pointers is that
one delegate can be added to another using the + operation. This is referred to as
composition. This is done by adding one delegate variable to another as in a = b + c.

Delegates and Arguments


 

Introduction

If you want to use a method that takes arguments and associate it to a delegate, when
declaring the delegate, provide the necessary argument(s) in its parentheses. Here is an
example of a delegate that takes two arguments (and returns a value):
delegate double Doubler(double x);

When defining the associated method, besides returning the same type of value if not
void, make sure that the method takes the same number of arguments. Here is an
example:
C# 3.0 Practical Learning 375
public class Algebra
{
public static double MultiplyBy2(double a)
{
return a * 2;
}
}

Using an Argumentative Delegate

To associate the method to the delegate, you can declare a variable for the delegate
and assign the name of the method to it. Here is an example:
using System;

delegate double Doubler(double x);

public class Algebra


{
public static double MultiplyBy2(double a)
{
return a * 2;
}
}

public class Program


{
static int Main()
{
Doubler dbl = Algebra.MultiplyBy2;

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

return 0;
}
}

Notice that only the name of the method is passed to the delegate. To actually use the
delegate, when calling it, add the parentheses to it and in the parentheses, provide a
value for the argument(s). Here is an example:
using System;

delegate double Doubler(double x);

public class Algebra


{
public static double MultiplyBy2(double a)
{
return a * 2;
}
}

public class Program


{
static int Main()
{
Doubler dbl = Algebra.MultiplyBy2;

C# 3.0 Practical Learning 376


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

return 0;
}
}

This would produce:


Result = 496
Press any key to continue . . .

A Lambda Expression

You can create an anonymous method for a delegate that takes one or more arguments.
You can do this using the delegate keyword. In its parentheses, pass an argument that
is the same type as the argument of the delegate. Then, in the body of the method, do
what you judge necessary. When calling the variable of the delegate, use the same rules
we have applied so far. Here is an example:
using System;

delegate double Doubler(double x);

public class Program


{
static int Main()
{
Doubler dbl = delegate(double alpha)
{
return alpha * 2;
};

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

return 0;
}
}

This technique of using the delegate keyword was introduced in C# 2.0 and has been
updated with the lambda operator. Therefore, this was probably the last time we use it
since we have been able to apply to different types of delegates.

Instead of the delegate keyword, you can define an anonymous method using the
lambda operator. In this case, in the parentheses of the lambda expression, enter the
data type of the argument followed by its name. Here is an example:
using System;

delegate double Doubler(double x);

public class Program


{
static int Main()
{
Doubler dbl = (double alpha) =>
{
};

C# 3.0 Practical Learning 377


return 0;
}
}

In the body of the anonymous method, use the argument as you see fit. Here is an
example:
using System;

delegate double Doubler(double x);

public class Program


{
static int Main()
{
Doubler dbl = (double alpha) =>
{
return alpha * 2;
};

return 0;
}
}

After defining the method, you can call it like a normal method. Here is an example:
using System;

delegate double Doubler(double x);

public class Program


{
static int Main()
{
Doubler dbl = (double alpha) =>
{
return alpha * 2;
};

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

return 0;
}
}

In our example, we specified the type of the argument. If you want, you can let the
compiler figure out the type of argument. In this case, pass only the name of the
argument and not its type. Here is an example:
using System;

delegate double Doubler(double x);

public class Program


{
static int Main()
{
Doubler dbl = (alpha) =>
{
return alpha * 2;
C# 3.0 Practical Learning 378
};

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

return 0;
}
}

A Delegate With Many Arguments

A delegate can take more than one argument. To start, when declaring it, pass the
desired number of arguments. If you will use a method to associate to the delegate,
then create the method also. Here is an example:
delegate double Addition(double x, double y);

public class Algebra


{
public static double Plus(double a, double b)
{
return a + b;
}
}

To use the delegate, follow the techniques we have applied so far and call the delegate
as a method. Here is an example:
using System;

delegate double Addition(double x, double y);

public class Algebra


{
public static double Plus(double a, double b)
{
return a + b;
}
}

public class Exercise


{
static int Main()
{
Addition Operation = Algebra.Plus;

Console.WriteLine("Result = {0}", Operation(52.04, 9.368));

return 0;
}
}

This would produce:


Result = 61.408
Press any key to continue . . .

If you want to use a lambda expression to create an anonymous method, in its


parentheses, pass the right number of arguments. In the body of the anonymous

C# 3.0 Practical Learning 379


method, use the arguments ad you see fit. To use the delegate, call it as you would a
normal method. Here is an example:
using System;

delegate double Addition(double x, double y);

public class Exercise


{
static int Main()
{
Addition Operation = (x, y) =>
{
return x + y;
};

Console.WriteLine("Result = {0}", Operation(52.04, 9.368));

return 0;
}
}

Practical Learning: Passing Arguments to a Delegate

1. Access the LoanEvaluation.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WattsALoan1
{
public class LoanEvaluation
{
public double GetPrincipal()
{
Console.Write("Enter the Principal: $");
double P = double.Parse(Console.ReadLine());

return P;
}

public double GetInterestRate()


{
Console.Write("Enter the Interest Rate (%): ");
double r = double.Parse(Console.ReadLine());

return r;
}

public double GetPeriod(ref int TypeOfPeriod, ref double Periods)


{
Console.WriteLine("How do you want to enter the length of
time?");
Console.WriteLine("1 - In Days");
C# 3.0 Practical Learning 380
Console.WriteLine("2 - In Months");
Console.WriteLine("3 - In Years");
Console.Write("Your Choice: ");
TypeOfPeriod = int.Parse(Console.ReadLine());

if (TypeOfPeriod == 1)
{
Console.Write("Enter the number of days: ");
Periods = double.Parse(Console.ReadLine());
return Periods / 360;
}
else if (TypeOfPeriod == 2)
{
Console.Write("Enter the number of months: ");
Periods = double.Parse(Console.ReadLine());
return Periods / 12;
}
else if (TypeOfPeriod == 3)
{
Console.Write("Enter the number of years: ");
Periods = double.Parse(Console.ReadLine());
return Periods;
}
else
{
TypeOfPeriod = 0;
// The user made an invalid selection. So, we will give
up
Console.WriteLine("Bad Selection\n");
return 0.00;
}
}

// Interest = Principal * rate * time in years


public double InterestAmount(double P, double r, double t)
{
return P * (r / 100) * t;
}
}
}

2. Access the Program.cs file

3. To declare and use a delegate, change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WattsALoan1
{
delegate double Add2Values(double Value1, double Value2);

public class Program


{
static int Main()
{
double Principal, IntRate, Period, AmountPaidAsInterest;
C# 3.0 Practical Learning 381
int TypeOfPeriod = 0;
double Periods = 0D;
string PeriodName = null;
LoanEvaluation loan = new LoanEvaluation();

Console.WriteLine("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
Console.WriteLine(
"This program allows you to calculate the amount of money a ");
Console.WriteLine(
"customer will owe at the end of the lifetime of a loan\n");

Console.WriteLine("Loan Processing\n");
Principal = loan.GetPrincipal();
IntRate = loan.GetInterestRate();
Period = loan.GetPeriod(ref TypeOfPeriod, ref Periods);
AmountPaidAsInterest =
loan.InterestAmount(Principal, IntRate, Period);

// A lambda expression
Add2Values Add = (double Value1, double Value2) =>
{
return Value1 + Value2;
};

if (TypeOfPeriod == 0)
{
// Since the user made a bad selection, stop the program
here
return 0;
}// Since this "if" condition has a "return 0" line, if the
"if"
// condition produces true, the "return 0" means the function
// would be terminated. If the condition is false, the inside
of
// this "if" condition would not execute and the function
would
// continue. This means that, if the condition is false, then
// the "else' is implied. Therefore, we don't have to write
an
// "else" condition: it is automatic.

if (TypeOfPeriod == 1)
{
PeriodName = "days";
}
else if (TypeOfPeriod == 2)
{
PeriodName = "months";
}
else if (TypeOfPeriod == 3)
{
PeriodName = "years";
}

Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");

Console.WriteLine("==================================");
Console.WriteLine("Estimate on loan");
Console.WriteLine("----------------------------------");
Console.WriteLine("Principal: {0:C}", Principal);
C# 3.0 Practical Learning 382
Console.WriteLine("Interest: {0:P}", IntRate / 100);
Console.WriteLine("Period: {0} {1}", Periods, PeriodName);
Console.WriteLine("--------------------------------");
Console.WriteLine("Total Amount Paid: {0:C}", Add);
Console.WriteLine("Interest paid on Loan: {0:C}",
AmountPaidAsInterest);
Console.WriteLine("==================================\n");

return 0;
}
}
}

4. Execute the program and test it. Here is an example:


 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
This program allows you to calculate the amount of money a
customer will owe at the end of the lifetime of a loan

Loan Processing

Enter the Principal: $12500


Enter the Interest Rate (%): 10.55
How do you want to enter the length of time?
1 - In Days
2 - In Months
3 - In Years
Your Choice: 2
Enter the number of months: 42
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

==================================
Estimate on loan
----------------------------------
Principal: $12,500.00
Interest: 10.55 %
Period: 42 months
--------------------------------
Total Amount Paid: $17,115.63
Interest paid on Loan: $4,615.63
==================================

Press any key to continue . . .

5. Close the DOS window and return to your programming environment

A Delegate Passed as Argument

Using delegates, one method can be indirectly passed as argument to another method.
To proceed, first declare the necessary delegate. Here is a example of such a delegate:
public delegate double Squared(double x);

public class Circle


{
private double _radius;

public double Radius


C# 3.0 Practical Learning 383
{
get { return _radius; }
set { _radius = value; }
}
}

A delegate can be passed as argument to a method. Such an argument would be used


as if it were a method itself. This means that, when accessed in the body of the method,
the name of the delegate must be accompanied by parentheses and if the delegate
takes an argument or arguments, the argument(s) must be provided in the parentheses
of the called delegate. Here is an example:
public delegate double Squared(double x);

public class Circle


{
private double _radius;

public double Radius


{
get { return _radius; }
set { _radius = value; }
}

public double Area(Squared sqd)


{
return sqd(_radius) * Math.PI;
}
}

After declaring a delegate, remember to define a method that implements the needed
behavior of that delegate. You can define the associated method in a class other than
the one where the delegate would be used. Here is an example:
using System;

public class Exercise


{
public static double ValueTimesValue(double Value)
{
return Value * Value;
}

static int Main()


{
return 0;
}
}

You can also define the method in the class where the delegate would be needed. Once
the method that implements the delegate is known, you can use the delegate as you see
fit. To do that, you can declare a variable of the type of that delegate and assign it to
the variable. Here is an example:
using System;

public delegate double Squared(double x);

public class Circle


C# 3.0 Practical Learning 384
{
private double _radius;

public double Radius


{
get { return _radius; }
set { _radius = value; }
}

public double Area(Squared sqd)


{
return sqd(_radius) * Math.PI;
}
}

public class Exercise


{
public static double ValueTimesValue(double Value)
{
return Value * Value;
}

static int Main()


{
Squared Sq = ValueTimesValue;

return 0;
}
}

This declaration gives life to the delegate and can then be used as we have proceed
with delegates so far. Here is an example:
using System;

public delegate double Squared(double x);

public class Circle


{
private double _radius;

public double Radius


{
get { return _radius; }
set { _radius = value; }
}

public double Area(Squared sqd)


{
return sqd(_radius) * Math.PI;
}
}

public class Exercise


{
public static double ValueTimesValue(double Value)
{
return Value * Value;
}

C# 3.0 Practical Learning 385


static int Main()
{
Squared Sqr = ValueTimesValue;

Console.WriteLine("Circle Area: {0}\n", Sqr(24.68));

return 0;
}
}

This would produce:


Circle Area: 609.1024

Press any key to continue . . .

In the same way, you can use a lambda expression to implement an anonymous method
that would be associated with a delegate. Here is an example:
using System;

public delegate double Squared(double x);

public class Circle


{
private double _radius;

public double Radius


{
get { return _radius; }
set { _radius = value; }
}

public double Area(Squared sqd)


{
return sqd(_radius) * Math.PI;
}
}

public class Exercise


{
static int Main()
{
Squared Sqr = (a) =>
{
return a * a;
};

Console.WriteLine("Circle Area: {0}\n", Sqr(24.68));

return 0;
}
}

Delegates and Classes


 

Introduction
C# 3.0 Practical Learning 386
So far, we have learned how to create and use delegate of primitive types. We learned
how to create a void delegate, how to create a delegate that returns a value, and how
to create a delegate that takes one or more argument. Just as a reminder, here is an
example:
using System;

delegate double Multiplication();

public class Cube


{
private double _side;

public double Side


{
get { return _side; }

set { _side = value; }


}

public Cube()
{
_side = 0;
}

public Cube(double s)
{
_side = s;
}

internal double Area()


{
return 6 * Side * Side;
}

internal double Volume()


{
return Side * Side * Side;
}
}

public class Exercise


{
static int Main()
{
Cube SmallBox = new Cube(25.58);

Multiplication AreaDefinition = SmallBox.Area;


Multiplication VolDefinition = SmallBox.Volume;

Console.WriteLine("Cube Characteristics");
Console.WriteLine("Side: {0}", SmallBox.Side);
Console.WriteLine("Area: {0}", AreaDefinition);
Console.WriteLine("Volume: {0}\n", VolDefinition);

return 0;
}
}

C# 3.0 Practical Learning 387


This would produce:
Cube Characteristics
Side: 25.58
Area: 3926.0184
Volume: 16737.925112

A Delegate that Returns an Object

A delegate can be created to return a value that is of a class type. Of course you must
know the class you want to use because the compiler would like to know the type of
value that the delegate would return. You can use one of the many built-in classes of
the .NET Framework or you can create your own class. When creating the delegate,
specify the name of the class to its left as the returned type of value. Here is an
example:
delegate Person Creator();

public class Person


{
public string FirstName;
public string LastName;
}

After doing this, you can create a method that implements the delegate. The method
must return the same type of value as the delegate. Here is an example:
using System;

delegate Person Creator();

public class Person


{
public string FirstName;
public string LastName;
}

public class Exercise


{
private static Person Create()
{
Person pers = new Person();
pers.FirstName = "Julius";
pers.LastName = "Krands";
return pers;
}
}

To use the delegate, declare a variable for it and assign the method to it. Here is an
example:
using System;

delegate Person Creator();

public class Person


{
public string FirstName;

C# 3.0 Practical Learning 388


public string LastName;
}

public class Exercise


{
private static Person Create()
{
Person pers = new Person();
pers.FirstName = "Julius";
pers.LastName = "Krands";
return pers;
}

static int Main()


{
Creator crt = Create;

return 0;
}
}

You can then call use the variable as you see fit. Instead of explicitly creating a method
that implements the delegate, you can create an anonymous method using a lambda
expression. In the body of the anonymous method, make sure you return a value of the
type of the delegate. Here is an example:
using System;

delegate Person Creator();

public class Person


{
public string FirstName;
public string LastName;
}

public class Exercise


{
static int Main()
{
Creator Create = () =>
{
var PersonalInformation = new Person();

PersonalInformation.FirstName = "Julius";
PersonalInformation.LastName = "Krands";

return PersonalInformation;
};

Create();
return 0;
}
}

A Delegate that Takes an Object as Argument

C# 3.0 Practical Learning 389


A delegate can be created to receive a class type as argument. When creating the
delegate, in its parentheses, specify the class whose value it takes as argument. Here is
an example:
using System;

delegate void Anchor(Person p);

public class Person


{
public string FirstName;
public string LastName;
}

To use the delegate, you can first create a method that implements the delegate, then
declare a variable for the delegate and assign the method to it. If you prefer to create
an anonymous method using a lambda expression, in the parentheses, enter a name for
the argument and use that argument in the body of the method as you see fit. Here is
an example: 
public class Exercise
{
static int Main()
{
Anchor personal = (individual) =>
{
Console.WriteLine("=//= Personal Information =//=");
Console.WriteLine("First Name: {0}", sample.FirstName);
Console.WriteLine("Last Name: {0}", sample.LastName);
};

return 0;
}
}

You can then call the method as you see fit. Here is an example:
using System;

delegate Person Creator();


delegate void Anchor(Person p);

public class Person


{
public string FirstName;
public string LastName;
}

public class Exercise


{
static int Main()
{
var PersonalInformation = new Person();

Creator Create = () =>


{
PersonalInformation.FirstName = "Julius";
PersonalInformation.LastName = "Krands";

C# 3.0 Practical Learning 390


return PersonalInformation;
};

Anchor personal = (individual) =>


{
Console.WriteLine("=//= Personal Information =//=");
Console.WriteLine("First Name: {0}", individual.FirstName);
Console.WriteLine("Last Name: {0}", individual.LastName);
};

Create();
personal(PersonalInformation);

return 0;
}
}

This would produce:


=//= Personal Information =//=
First Name: Julius
Last Name: Krands
Press any key to continue . . .

In the same way:

 You can create a delegate that takes a class as argument and returns a class type

 You can create a delegate that takes more than one argument. One of the
arguments could be a class type and the other(s) a class or a primitive type 

Events
 

Introduction

Except for the main class of your program (the class that contains the Main() method),
every class is mostly meant to interact with other, either to request values and methods
of the other classes or to provide other classes with some values or a behavior they
need. When a class A requests a value or service from another class B, class A is
referred to as a client of class B. This relationship is important not simply because it
establishes a relationship between both classes but also because class B should be ready
to provide the value or behavior that a client needs at a certain time.

While a class B is asked to provide some values or methods to another class A, many
things would happen. In fact, there is an order that things should follow. For example,
during the lifetime of a program, that is, while a program is running, a class may be
holding a value it can provide to its client but at another time, that value may not be
available anymore, for any reason; nothing strange, this is just the ways it happens.
Because different things can happen to a class B while a program is running, and
because only class B would be aware of these, it must be able to signal to the other
classes when there is a change. This is the basis of events: An event is an action that
occurs on an object and affects it in a way that its clients must be made aware of.
Events are mostly familiar to those who do graphical (GUI) programming as they are
able to "visually" work on Windows controls and as they are able to access the objects
C# 3.0 Practical Learning 391
on which actions are happening and the objects that must know when these actions
occur. Still, because events are dealt with in C#, you should be aware of their
functionality.

Although events are mostly used in Windows controls programming, they can also be
implemented in console applications.

Event Creation

An event is declared like a pseudo-variable but based on a delegate. Therefore, to


declare an event, you must have a delegate that would implement it. Here is an
example:
using System;

delegate void dlgSimple();

class Exercise
{
public static void Welcome()
{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}
}

To actually declare an event, you use the event keyword with the following formula:
[attributes] [modifiers] event type declarator;
[attributes] [modifiers] event type member-name {accessor-declarations};

The attributes factor can be a normal C# attribute.

The modifier can be one or a combination of the following keywords: public, private,
protected, internal, abstract, new, override, static, virtual, or extern.

The event keyword is required. It is followed by the name of the delegate that specifies
its behavior. If the event is declared in the main class, it should be made static. Like
everything in a program, an event must have a name. This would allow the clients to
know what (particular) event occurred. Here is an example:
using System;

delegate void dlgSimple();

class Exercise
{
public static event dlgSimple Simply;

public static void Welcome()


{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}
}

C# 3.0 Practical Learning 392


After declaring the event, you must define a method that calls the event. Here is an
example:
using System;

delegate void dlgSimple();

class Exercise
{
public static event dlgSimple Simply;

public static void Welcome()


{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}

public static void SayHello()


{
Simply();
}
}

When the event occurs, its delegate would be invoked. This specification is also referred
to as hooking up an event. As the event occurs (or fires), the method that implements
the delegate runs. This provides complete functionality for the event and makes the
event ready to be used. Before using an event, you must combine it to the method that
implements it. This can be done by passing the name of the method to the appropriate
delegate, as we learned when studying delegates. You can then assign this variable to
the event's name using the += operator. Once this is done, you can call the event. Here
is an example:
using System;

delegate void dlgSimple();

class Exercise
{
public static event dlgSimple Simply;

public static void Welcome()


{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}

public static void SayHello()


{
Simply();
}

static int Main()


{
Simply += new dlgSimple(Welcome);

SayHello();

return 0;
}
C# 3.0 Practical Learning 393
}

Instead of the += operator used when initializing the event, you can implement add and
remove of the event class. Here is an example:

using System;

delegate void dlgSimple();

class Exercise
{
public event dlgSimple Simply
{
add
{
Simply += new dlgSimple(Welcome);
}
remove
{
Simply -= new dlgSimple(Welcome);
}
}

public void Welcome()


{
Console.WriteLine("Welcome to the Wonderful World of C#
Programming!");
}
}

C# 3.0 Practical Learning 394


Structures
 

Fundamentals of Structures
 

Introduction

A structure is an enhanced version of the primitive data types we have used in previous
lessons. Like a class, a structure is created from one variable of a primitive type or by
combining various variables of primitive types.

To create a structure, you use the same formula as for a class but with the struct
keyword. Here is an example of a structure:
struct Integer
{
}

Like a class, a structure can have fields. They are listed in the body of the structure.
Here is an example:
struct Integer
{
private int val;
}

A structure can also have properties. Here is an example:


struct Integer
{
private int val;

public int Value


{
get { return val; }
set { val = value; }
}
}

A structure can also have methods. Here is an example:


struct Integer
{
private int val;

public int Value


{
get { return val; }
set { val = value; }
}
C# 3.0 Practical Learning 395
public int Read()
{
return int.Parse(Console.ReadLine());
}
}

Structure Declaration

Like any other data type, to use a structure, you can first declare a variable from it. To
allocation memory for a variable declared from a structure, use the new operator as
done for a class. Here is an example:

using System;

struct Integer
{
private int val;

public int Value


{
get { return val; }
set { val = value; }
}

public int Read()


{
return int.Parse(Console.ReadLine());
}
}

class Program
{
static int Main()
{
Integer Natural = new Integer();
return 0;
}
}

As done for variables of the other types and as seen for classes, to declare a variable for
a structure, you can use the var keyword. After declaring the variable, you can use the
object the same way you would a class. You can access its members (fields, properties,
and methods) using the period operator. Here is an example:
using System;

struct Integer
{
private int val;

public int Value


{
get { return val; }
set { val = value; }
}

C# 3.0 Practical Learning 396


public int Read()
{
return int.Parse(Console.ReadLine());
}
}

class Program
{
static int Main()
{
var Natural = new Integer();

Console.Write("Enter a natural number: ");


// Accessing a property of the structure
Natural.Value =
// Calling a method of the structure
Natural.Read();

Console.WriteLine("The value you entered was: {0}",


Natural.Value);
return 0;
}
}

Here is an example of running the program:


Enter a natural number: 248
The value you entered was: 248
Press any key to continue . . .

Although there are many similarities in the behaviors of classes and structures, you
should use a structure when the object you are creating is meant to represent relatively
small values. Like primitive data types and unlike a class, a structure is a value type. 

Techniques of Using Structures


 

A Structure as a Property

Once a structure exists, you can use it like a data type. For example, you can create a
property that is a structure type. The rules are the same we reviewed for creating a
property of a class. After creating the property, you can use it as you see fit. Here is an
example:
using System;

public struct Real


{
private double val;

public double Value


{
get { return val; }
set { val = value; }
}

C# 3.0 Practical Learning 397


public double Read()
{
return double.Parse(Console.ReadLine());
}
}

public struct Rectangle


{
Real len;
Real hgt;

public Real Length


{
get { return len; }
set { len = value; }
}

public Real Height


{
get { return hgt; }
set { hgt = value; }
}

public void CreateRectangle()


{
Real rat = new Real();

Console.WriteLine("Enter the dimensions of the rectangle");


Console.Write("Enter the length: ");
len.Value = rat.Read();
Console.Write("Enter the height: ");
hgt.Value = rat.Read();
}
}

public class Program


{
static int Main()
{
var Rect = new Rectangle();

Rect.CreateRectangle();
Console.WriteLine();

Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Length: {0}", Rect.Length.Value);
Console.WriteLine("Height: {0}", Rect.Height.Value);
Console.WriteLine("Perimeter: {0}",
(Rect.Length.Value + Rect.Height.Value) * 2);
Console.WriteLine("Area: {0}",
Rect.Length.Value * Rect.Height.Value);

return 0;
}
}

Here is an example of running the program:


Enter the dimensions of the rectangle
Enter the length: 44.84
C# 3.0 Practical Learning 398
Enter the height: 26.75

Rectangle Characteristics
Length: 44.84
Height: 26.75
Perimeter: 143.18
Area: 1199.47
Press any key to continue . . .

Returning a Structure From a Method

Like regular data type or a class, a structure can serve as the return type of a method.  
The rules are more related to those of a class. When creating the method, type the
name of the structure on the left side of the name of the method. In the body of the
method, implement the desired behavior. Before exiting the method, make sure you
return a valid value that is of the type of the structure. When a method returns a value
of the type of a structure, you can assign the method to a variable of the type of the
structure.

Here is an example of implementing a method that returns a structure type, including


calling the method and using its value:
using System;

public struct Real


{
private double val;

public double Value


{
get { return val; }
set { val = value; }
}

public double Read()


{
return double.Parse(Console.ReadLine());
}
}

public struct Rectangle


{
Real len;
Real hgt;

public Real Length


{
get { return len; }
set { len = value; }
}

public Real Height


{
get { return hgt; }
set { hgt = value; }
}

public void CreateRectangle()


C# 3.0 Practical Learning 399
{
Real rat = new Real();

Console.WriteLine("Enter the dimensions of the rectangle");


len = GetLength();
Console.Write("Enter the height: ");
hgt.Value = rat.Read();
}

public Real GetLength()


{
Real rat = new Real();

Console.Write("Enter the length: ");


rat.Value = rat.Read();
return rat;
}
}

public class Program


{
static int Main()
{
var Rect = new Rectangle();

Rect.CreateRectangle();
Console.WriteLine();

Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Length: {0}", Rect.Length.Value);
Console.WriteLine("Height: {0}", Rect.Height.Value);
Console.WriteLine("Perimeter: {0}",
(Rect.Length.Value + Rect.Height.Value) * 2);
Console.WriteLine("Area: {0}",
Rect.Length.Value * Rect.Height.Value);

return 0;
}
}

Here is an example of running the application:


Enter the dimensions of the rectangle
Enter the length: 36.04
Enter the height: 22.86

Rectangle Characteristics
Length: 36.04
Height: 22.86
Perimeter: 117.8
Area: 823.8744
Press any key to continue . . .

Passing a Structure as Argument

Like a data type, a structure can be passed as argument to a method. The argument is
primarily passed as done for a class. After passing the argument, in the body of the

C# 3.0 Practical Learning 400


method, you can access the public members of the structure, using the period operator.
Here is an example:
using System;

public struct Real


{
private double val;

public double Value


{
get { return val; }
set { val = value; }
}

public double Read()


{
return double.Parse(Console.ReadLine());
}
}

public struct Rectangle


{
Real len;
Real hgt;

public Real Length


{
get { return len; }
set { len = value; }
}

public Real Height


{
get { return hgt; }
set { hgt = value; }
}

public void CreateRectangle()


{
Real rat = new Real();

Console.WriteLine("Enter the dimensions of the rectangle");


len = GetLength();
Console.Write("Enter the height: ");
hgt.Value = rat.Read();
}

public Real GetLength()


{
Real rat = new Real();

Console.Write("Enter the length: ");


rat.Value = rat.Read();
return rat;
}
}

public class Program


{
C# 3.0 Practical Learning 401
public static void ShowCharacteristics(Rectangle rect)
{
Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Length: {0}", rect.Length.Value);
Console.WriteLine("Height: {0}", rect.Height.Value);
Console.WriteLine("Perimeter: {0}",
(rect.Length.Value + rect.Height.Value) * 2);
Console.WriteLine("Area: {0}",
rect.Length.Value * rect.Height.Value);
}
static int Main()
{
var Rect = new Rectangle();
Rect.CreateRectangle();

Console.WriteLine();
ShowCharacteristics(Rect);

return 0;
}
}

Here is an example of running the program:


Enter the dimensions of the rectangle
Enter the length: 114.55
Enter the height: 82.72

Rectangle Characteristics
Length: 114.55
Height: 82.72
Perimeter: 394.54
Area: 9475.576
Press any key to continue . . .

When you pass a structure to a method as we did above, it referred to as passing by


value. A copy of the value of the structure is passed to the method. If the method
modifies the argument, the original variable would stay intact. If you want the method
to modify the value of the structure, you can pass the argument by reference. You can
do this using the (rules of the) ref and the out keywords.

Here is an example of passing a structure by reference using the ref keyword:


using System;

public struct Real


{
private double val;

public double Value


{
get { return val; }
set { val = value; }
}

public double Read()


{
return double.Parse(Console.ReadLine());
}
}
C# 3.0 Practical Learning 402
public struct Rectangle
{
Real len;
Real hgt;

public Real Length


{
get { return len; }
set { len = value; }
}

public Real Height


{
get { return hgt; }
set { hgt = value; }
}

public void CreateRectangle()


{
Console.WriteLine("Enter the dimensions of the rectangle");
len = GetLength();
GetHeight(ref hgt);
}

public Real GetLength()


{
Real rat = new Real();

Console.Write("Enter the length: ");


rat.Value = rat.Read();
return rat;
}

public void GetHeight(ref Real rl)


{
Real rat = new Real();

Console.Write("Enter the height: ");


rl.Value = rat.Read();
}
}

public class Program


{
static int Main()
{
Rectangle rect = new Rectangle();

rect.CreateRectangle();
Console.WriteLine();

Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Length: {0}", rect.Length.Value);
Console.WriteLine("Height: {0}", rect.Height.Value);
Console.WriteLine("Perimeter: {0}",
(rect.Length.Value + rect.Height.Value) * 2);
Console.WriteLine("Area: {0}",
rect.Length.Value * rect.Height.Value);

C# 3.0 Practical Learning 403


return 0;
}
}

Here is an example of running the program:


Enter the dimensions of the rectangle
Enter the length: 75.82
Enter the height: 55.64

Rectangle Characteristics
Length: 75.82
Height: 55.64
Perimeter: 262.92
Area: 4218.6248
Press any key to continue . . .

Built-In Structures: The Integral Data Types


 

Introduction

The C# language (actually the .NET Framework) treats each primitive data type as a
class. In fact, each data type was created as a structure. Some characteristics are
common to many of these structures while some other aspects are unique to some
others.

To support the routine operations of regular variables, each structure that represents a
primitive type is equipped with some member variables and methods.

Conversion to a String

With a value of a primitive type, at one time or another, you may need to convert the
value of a variable from its type to a string. To support this, each structure of a
primitive type is equipped with a method named ToString. This method is overloaded
with various versions. One of the versions of this method takes no argument. The syntax
of this method is:
public override string ToString();

Another version of this method takes as argument a string. This string holds an
expression used to format the value of the variable that called the method. The syntax
of this method is:
public string ToString(string format);

You can pass the desired string to format the value to be displayed.

Parsing a String

In Lesson 5, we saw how to retrieve a value from the console and convert it to the
desired value. To support this operation, each structure of a primitive data type is
equipped with a static method named Parse. The syntaxes of this method are:

C# 3.0 Practical Learning 404


byte

public static byte Parse(string s);

sbyte

public static sbyte Parse(string s);

short

public static short Parse(string s);

ushort <=> UInt16

public static ushort Parse(string s);

int <=> Int32

public static int Parse(string s);

uint <=> UInt32

public static uint Parse(string s);

long <=> Int64

public static long Parse(string s);

unsigned long <=> uint64

public static ulong Parse(string s);

 Here is an example of calling this method:


using System;

class Program
{
static int Main()
{
double value = 0;

Console.Write("Enter a Value: ");


value = double.Parse(Console.ReadLine());

Console.WriteLine("Value Entered: {0}", value);

return 0;
}
}

Here is an example of executing the program:


Enter a Value: 245.85
Value Entered: 245.85
Press any key to continue . . .

C# 3.0 Practical Learning 405


You can also parse a value that is not primarily known. To support values other than
byte types, you can use another version of the Equals() method that takes as
argument an object type. The syntaxes of this version of the method are:

byte

public static byte Parse(string s)

sbyte

public static sbyte Parse(string s)

short

public static short Parse(string s)

ushort <=> UInt16

public static ushort Parse(string s)

int <=> Int32

public static int Parse(string s)

uint <=> UInt32

public static uint Parse(string s)

long <=> Int64

public static long Parse(string s)

unsigned long <=> uint64

public static ulong Parse(string s)

When calling this method, if a bad value is passed to the Parse() method, for example
if the user enters an invalid value to a double.Parse(Console.ReadLine()) call, the
program produces an error (in Lesson 17, we will learn that the program throws an
exception). To assist you with this type of problem, each structure of a primitive type is
equipped with a method named TryParse. This method is overloaded with two versions
that each returns a bool. One of the versions of this method takes two arguments: a
string and a variable passed as an out reference. The syntaxes of this method are:

byte

public static bool TryParse(string s, out byte result)

sbyte

public static bool TryParse(string s, out sbyte result)

short

public static bool TryParse(string s, out short result)

ushort <=> UInt16

C# 3.0 Practical Learning 406


public static bool TryParse(string s, out ushort result)

int <=> Int32

public static bool TryParse(string s, out int result)

uint <=> UInt32

public static bool TryParse(string s, out uint result)

long <=> Int64

public static bool TryParse(string s, out long result)

unsigned long <=> uint64

public static bool TryParse(string s, out ulong result)

Based on this, if a double variable calls this method, the first argument is passed a
string and the second argument is passed as an out double. This means that the
second argument is returned from the method also.

When the TryParse() method is called:

 If the first argument passed to the method is valid, the method returns two values:
true and the entered value is stored in the out argument

 If the value of the first argument is invalid, the method returns false and the
default value of the data type is stored in the out argument. For example, if the
variable that called the method is on type int but the user entered the wrong
value, the method returns two values: false and 0 (because 0 is the default value
of an int. If the variable that called the method is on type char but the user
entered a bad value, the method returns two values: false and an empty
character (because the default value of a char is empty). 

Here is another example of running the above program:


Enter a Value: 506GH
False: Value Entered = 0
Press any key to continue . . .

Notice that the compiler didn't produce (throw) an error (an exception).

The Minimum and Maximum Values of a Primitive Type

In Lesson 1, we saw that, when you declare a variable, the compiler reserves an amount
of memory space preparing to store its value. As different variables have different
requirements, some of them use less or more memory than others. When you declare a
variable, the data type you specify allows the compiler to know how mush space would
be needed to store the value of  that variable. There is a minimum and a maximum
values that can be stored in the memory space reserved for a variable. Based on this, a

C# 3.0 Practical Learning 407


value such as 224855 can be stored in space reserved for an int variable but it is beyond
the space reserved for a Byte or a short.

To help you find out the minimum value that a data type can hold, each structure of a
primitive type is equipped with a constant member named MinValue. In the same way,
the maximum value that a data type can support is represented by a constant field
named MaxValue. You can check these minimum and maximum with the following
program:
using System;

class Program
{
static int Main()
{
Console.WriteLine(
"=================================================================
======");
Console.WriteLine("C# Type .NET Structure Minimum
Maximum");
Console.WriteLine(
"=================================================================
======");
Console.WriteLine("char Char {0}\t\t\t{1}",
char.MinValue, char.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("byte Byte {0}\t\t\t{1}",
byte.MinValue, byte.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("sbyte SByte {0}\t\t\t{1}",
sbyte.MinValue, sbyte.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("short Int16 {0}\t\t\t{1}",
short.MinValue, short.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("ushort UInt16 {0}\t\t\t{1}",
UInt16.MinValue, UInt16.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("int Int32 {0}\t\t{1}",
int.MinValue, int.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("uint UInt32 {0}\t\t\t{1}",
UInt32.MinValue, UInt32.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("long Int64 {0}\t{1}",
C# 3.0 Practical Learning 408
long.MinValue, long.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("uint64 UInt64 {0}\t\t\t{1}",
UInt64.MinValue, UInt64.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("float Single {0}\t\t{1}",
float.MinValue, float.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("double Double {0}\t{1}",|
double.MinValue, double.MaxValue);
Console.WriteLine(
"-----------------------------------------------------------------
------");
Console.WriteLine("decimal Decimal {0} {1}",
decimal.MinValue, decimal.MaxValue);
Console.WriteLine(
"=============================================================");

return 0;
}
}

This would produce:


=======================================================================
C# Type .NET Structure Minimum Maximum
=======================================================================
char Char ?
-----------------------------------------------------------------------
byte Byte 0 255
-----------------------------------------------------------------------
sbyte SByte -128 127
-----------------------------------------------------------------------
short Int16 -32768 32767
-----------------------------------------------------------------------
ushort UInt16 0 65535
-----------------------------------------------------------------------
int Int32 -2147483648 2147483647
-----------------------------------------------------------------------
uint UInt32 0 4294967295
-----------------------------------------------------------------------
long Int64 -9223372036854775808 9223372036854775807
-----------------------------------------------------------------------
uint64 UInt64 0 18446744073709551615
-----------------------------------------------------------------------
float Single -3.402823E+38 3.402823E+38
-----------------------------------------------------------------------
double Double -1.79769313486232E+308 1.79769313486232E+308
-----------------------------------------------------------------------
decimal Decimal -79228162514264337593543950335
79228162514264337593543950335
=============================================================
Press any key to continue . . .

C# 3.0 Practical Learning 409


Value Comparisons

One of the most common operations performed on variables consists of comparing their
values: to find out whether they are equal or to know whether one is higher than the
other. These operations can be performed using the Boolean operators we reviewed in
Lesson 8. The Boolean operations are part of the C# language. To formally implement
them, each structure of a data type is equipped with a method named CompareTo that
is overloaded with two versions.

One of the implementations of the CompareTo() method compares a value or the


value of a variable of the same type, with the variable that calls the method. This
method takes one argument that is the same type as the variable that is calling it. The
syntaxes of this method are:

byte

public int CompareTo(byte value)

sbyte

public int CompareTo(sbyte value)

short

public int CompareTo(short value)

ushort <=> UInt16

public int CompareTo(ushort value)

int <=> Int32

public int CompareTo(int value)

uint <=> UInt32

public int CompareTo(uint value)

long <=> Int64

public int CompareTo(long value)

unsigned long <=> uint64


public int CompareTo(ulong value)

The method returns an int value. For example, imagine you have two int variables
named Variable1 and Variable2, you can call the CompareTo() method of the first
variable to compare its value to that of the second variable. This would be done as in:
int result = Variable1.CompareTo(Variable2);

The end result would be as follows:

 If the value of Variable1 is greater than the value of Variable2, the method returns
1
C# 3.0 Practical Learning 410
 If the value of Variable1 is less than the value of Variable2, the method returns -1

 If the values of both variables are equal, the method returns 0

Here is an example:
using System;

class Program
{
static int Main()
{
int Variable1 = 248;
int Variable2 = 72937;
int result = Variable1.CompareTo(Variable2);
Console.WriteLine("{0} compared to {1} produces {2}",
Variable1, Variable2, result);

return 0;
}
}

This would produce:


248 compared to 72937 produces -1
Press any key to continue . . .

Another version of the CompareTo() method allows you to compare the value of a
variable with a variable whose type is not the same as the variable that called it. Since
all types and classes of C# are based on object, this second version takes as argument
an object object. The method return an int value. The syntax of this version is:
public int CompareTo(object value);

Notice that you can use the CompareTo() method to test for equality. Another method
used to check the equality of two variables is the Equals() method. The Equals()
method is overloaded in two versions and each takes one argument. The Equals()
method returns a Boolean value. One of the versions of this method takes as argument
a value of the same type as the variable that called it. The syntaxes of this version are:

byte

public bool Equals(byte obj)

sbyte

public bool Equals(sbyte obj)

short

public bool Equals(short obj)

ushort <=> UInt16

public bool Equals(ushort obj)

int <=> Int32

C# 3.0 Practical Learning 411


public bool Equals(int obj)

uint <=> UInt32

public bool Equals(uint obj)

long <=> Int64

public bool Equals(long obj)

unsigned long <=> uint64


public bool Equals(ulong obj)

The method compares the values of the variable that called it and the argument, as in
bool result = Variable1.Equals(Variable2);

The comparison is performed as follows:

 If the value of the first variable is the same as that of the second variable, the
method returns true

 If the values of the variables are different, the method returns false

Here is an example:
using System;

class Program
{
static int Main()
{
int Variable1 = 1407;
int Variable2= 59266;
bool result = value1.Equals(value2);
Console.WriteLine("{0} = {1} produces {2}",
Variable1, Variable2, result);

return 0;
}
}

This would produce:


1407 = 59266 produces False
Press any key to continue . . .

The other version of the Equals() method takes as argument an object value. The
syntax of this version is:
public override bool Equals(object obj);

Here is an example:
using System;

class Program
{
static int Main()

C# 3.0 Practical Learning 412


{
int value1 = 824;
object value2 = 824;
bool result = value1.Equals(value2);
Console.WriteLine("{0} = {1} produces {2}",
value1, value2, result);

return 0;
}
}

This would produce:


824 = 824 produces True
Press any key to continue . . .

Built-In Structures: The Boolean Type


 

Introduction

As seen in previous lessons, the bool data type is used to represent a value considered
as being true or false. In the .NET Framework, the bool data type is represented by the
Boolean structure. The true value of a bool variable is represented by the TrueString
field and the false value is represented by the FalseString member variable. In other
words, when true (or false) is represented as a string, "true" (or "false"” is the
same as TrueString (or FalseString).

Parsing a Boolean Variable

We saw in a Lesson 8 that you could retrieve the value of a Boolean variable from a
user. To support this, the Boolean structure is equipped with a static method named
Parse. The Boolean.Parse() method is declared as follows:

public static bool Parse(string value);

This method takes as argument a string. The argument must contain either the word
True (case-insensitive) or the word False. If the argument is passed as "True", the
method returns true. If the argument is "false", this method returns false. Here is
an example:
using System;

class Program
{
static int Main()
{
bool result = bool.Parse("TRUE");

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


return 0;
}
}

This would produce:


C# 3.0 Practical Learning 413
Result: True
Press any key to continue . . .

When calling the Boolean.Parse() method to retrieve the value of a Boolean variable,
if the supplied value is "TRUE" or "FALSE", the compiler would process it. If the value is
not valid, the program would produce an error. Here is an example:
using System;

class Program
{
static int Main()
{
bool HouseHas3Bedrooms = bool.Parse("ItHas3Bedrooms");

Console.WriteLine("House has 3 bedrooms: {0}",


HouseHas3Bedrooms);
return 0;
}
}

To avoid the error, the Boolean structure provides the TryParse() method. Its syntax
is:
public static bool TryParse(string value, out bool result);

The first argument is the value to be parsed. If that value is valid, the second argument
holds the True or False value of the first. Here is an example:
using System;

class Program
{
static int Main()
{
bool alt;
bool HouseHas3Bedrooms = bool.TryParse("True", out alt);

Console.WriteLine("House has 3 bedrooms: {0}",


HouseHas3Bedrooms);
Console.WriteLine("Alternate value: {0}", alt);
return 0;
}
}

This would produce:


House has 3 bedrooms: True
Alternate value: True
Press any key to continue . . .

Consider this other version of the same program:


using System;

class Program
{
static int Main()
{
bool alt;

C# 3.0 Practical Learning 414


bool HouseHas3Bedrooms = bool.TryParse("False", out alt);

Console.WriteLine("House has 3 bedrooms: {0}",


HouseHas3Bedrooms);
Console.WriteLine("Alternate value: {0}", alt);
return 0;
}
}

This would produce:


House has 3 bedrooms: True
Alternate value: False
Press any key to continue . . .

Notice that the first argument returns True although it was passed as False. This means
that, if the value of the first argument is valid, it is the second argument, not the first,
that holds the result. If the first argument is not valid, the second argument returns a
False value. Consider the following version of the program:

using System;

class Program
{
static int Main()
{
bool alt;
bool HouseHas3Bedrooms = bool.TryParse("Don't Know", out alt);

Console.WriteLine("House has 3 bedrooms: {0}",


HouseHas3Bedrooms);
Console.WriteLine("Alternate value: {0}", alt);
return 0;
}
}

This would produce:


House has 3 bedrooms: False
Alternate value: False
Press any key to continue . . .

Comparisons of Boolean Variables

In C#, to compare the values of two Boolean variables for equality, you can use the
equality operator "==". Here is an example:
using System;

class Program
{
static int Main()
{
bool House1Has3Bedrooms = true;
bool House2Has3Bedrooms = false;

Console.WriteLine("House1 has 3 bedrooms: {0}",


House1Has3Bedrooms);

C# 3.0 Practical Learning 415


Console.WriteLine("House2 has 3 bedrooms: {0}",
House2Has3Bedrooms);
Console.WriteLine("House1 and House2 have the number of bedrooms:
{0}",
House1Has3Bedrooms == House2Has3Bedrooms);
return 0;
}
}

This would produce:


House1 has 3 bedrooms: True
House2 has 3 bedrooms: False
House1 and House2 have the number of bedrooms: False
Press any key to continue . . .

To support this comparison, the Boolean structure of the .NET Framework is equipped
with the Equals() method. Its syntax is:
public bool Equals(bool obj);

This method takes one argument as the Boolean value or variable to be compared to the
variable that called it. Here is an example of calling it:
using System;

class Program
{
static int Main()
{
bool House1Has3Bedrooms = false;
bool House2Has3Bedrooms = false;

Console.WriteLine("House1 has 3 bedrooms: {0}",


House1Has3Bedrooms);
Console.WriteLine("House2 has 3 bedrooms: {0}",
House2Has3Bedrooms);
Console.WriteLine("House1 and House2 have the number of bedrooms:
{0}",
House1Has3Bedrooms.Equals(House2Has3Bedrooms));
return 0;
}
}

This would produce:


House1 has 3 bedrooms: False
House2 has 3 bedrooms: False
House1 and House2 have the number of bedrooms: True
Press any key to continue . . .

The Equals() method can easily be called by one Boolean variable that receives
another Boolean variable as argument. If you don't know the exact type of value of the
argument, you can still pass it an object value. To support this, the Equals() method
has another version whose syntax is:
public override bool Equals(Object obj);

This version takes as argument a variable that is of any type.

C# 3.0 Practical Learning 416


Besides the equality, you can also compare two Boolean variables to know whether one
is lower than the other. To support this, the Boolean structure is equipped with the
CompareTo() method. Its syntax is:

public int CompareTo(bool value);

If the type of variable is not necessarily a Boolean type, you can pass it as an object
value. To do this, you can use the other version of the CompareTo() method. Its syntax
is:
public int CompareTo(Object obj);

Floating-Point Numbers
 

Introduction

As seen in Lesson 2, to support floating-point numbers, you can use the float, the
double, or the decimal data types. The C# float data type originates from the Single
structure of the .NET Framework. The double data type is based on the Double structure
of the .NET Framework. The C# decimal data type is type-defined from the .NET
Framework’s Decimal structure. To declare a floating-point variable, you can use one of
these data types and initialize it.

When initializing a floating-point variable, you should make sure you assign it a value
that can fit in the memory allocated for it. As mentioned for the integer data types, the
minimum value that a float variable can hold is represented by the MinValue constant
of the Single structure and the MinValue field of the Double. The maximum value that a
float or a double variable can hold is named MaxValue.

After declaring and initializing a float or a double variable, it should hold an appropriate
value. If you get the variable’s value some other way, at one time or another, you may
not know what value is stored in the memory allocated for the variable. In fact, the
variable may hold a value that is not a number. To check whether the variable is holding
a value that is not a number, you can access its NaN constant. To do this, type the float
or double data type, followed by the period operator, and followed by the NaN constant.
Here is an example:
using System;

class Program
{
static int Main()
{
double number = 0D;

if( number == double.NaN )


Console.WriteLine("The value is not a number");
return 0;
}
}

C# 3.0 Practical Learning 417


Another technique you can use to check this characteristic is to IsNaN() method of
either the Single or the Double structure.

Operations on Floating-Point Numbers

Using one integer and one floating-point number, or with two floating-point numbers,
you can perform one of the routine arithmetic operations such as the addition, the
subtraction, the multiplication, or the division. When it comes to the division and if
performed on two constants, you can get a positive or a negative number. In highly
precise calculations, you may have to deal with an approximate number whose exact
value is not known. For example, the smallest positive number is called epsilon. In the
Double and the Single structures, this constant is named Epsilon. For the single-
precision type, the epsilon is equal to 1.445. For a double-precision type, the epsilon
constant is equivalent to 4.94065645841247-324. As you can see, this number is
extremely low.

When dealing with real numbers, some operations produce very little or very large
numbers. In algebra, the smallest number is called negative infinity. In the .NET
Framework, the negative infinity is represented by a constant named
NegativeInfinity. To access this number, type either float or double, followed by a
period operator, followed by the name of this constant. Here is an example:
using System;

class Program
{
static int Main()
{
Console.WriteLine("Negative Infinity = {0}",
double.NegativeInfinity);
return 0;
}
}

To find out if a variable holds a negative infinity value, you can call the
IsNegativeInfinity() method from the variable. The syntaxes of this method are:

public static bool IsNegativeInfinity(float f);


public static bool IsNegativeInfinity(double d);

On the other extreme, the possible largest number is named positive infinity. This
constant is represented in the .NET Framework by the PositiveInfinity value. To
access this constant, type float or double, followed by the period, followed by the name
of this constant. To find out if a variable’s value is a positive infinity, you can call its
IsPositiveInfinity() method. The syntaxes of this method are:

public static bool IsPositiveInfinity(float f);


public static bool IsPositiveInfinity(double d);

To check whether the value of a variable is one of the infinities, you can call its
IsInfinity() method. The syntaxes of this method are:

public static bool IsInfinity(float f);


public static bool IsInfinity(double d);

C# 3.0 Practical Learning 418


Comparison Operations

Because floating-point numbers can be approximate, you should be careful when


comparing them, especially for equality. Consider the following examples:
using System;

class Program
{
static int Main()
{
double number1 = 22.15D;
double number2 = 22.15D;

if( number1 == number2 )


Console.WriteLine("The values are equal");
return 0;
}
}

This would produce:


The values are equal
Press any key to continue . . .

For the sake of discussion, these values of these variables were limited to 2 decimal
places. If they represented hourly salaries of employees, the comparison would be easily
performed and can produce an exact result. If you want to apply more precision do the
numbers, for example if the variables represent weight values, you would need more
places on the right side of the decimal separator. Consider the following program:
using System;

class Program
{
static int Main()
{
double number1 = 22.156D;
double number2 = 22.157D;

if( number1 == number2 )


Console.WriteLine("The values are equal");
else
Console.WriteLine("The values are NOT equal");
return 0;
}
}

This would produce:


The values are NOT equal
Press any key to continue . . .

This time, because of more precision, the variables don’t hold the same value.

Besides the equality, you can also compare floating-point variables to find out if one has
a value lower than the other. To support such operations, the Single and the Double

C# 3.0 Practical Learning 419


structures are equipped with a method named CompareTo. The rules of this method are
functionally the same as those we reviewed for integers.

C# 3.0 Practical Learning 420


Built-In Classes
 

The Object Class


 

Introduction

C# was clearly created to improve on C++ and possibly offer a new alternative. To
achieve this goal, Microsoft created a huge library to accompany the language.
The .NET Framework is a huge library made of various classes and constants you can
directly use in your C# application without necessarily explicitly loading an external
library. To start, this main library of C# provides a class called Object.

As you may have realized by now, every variable or function in C# (as in Java) must
belong to a class, unlike C/C++ where you can have global variables or functions.
Therefore, you always have to create at least one class for your application. As such,
when you create a class, it automatically inherits its primary characteristics from the
parent of all classes: Object.

  

Practical Learning: Introducing Ancestor Classes

1. Start Microsoft Visual C# and create a Console Application named Sport1

2. To create a new class, in the Solution Explorer, right-click Sport1 -> Add -> Class...

3. Set the Name to Sport and click Add

4. Change the file as follows:


 

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sport1
{
class Sport
{
private double _ballWeight;
private int _players;
private double _courtLength;
private double _courtWidth;

C# 3.0 Practical Learning 421


public double BallWeight
{
get { return _ballWeight; }
set { _ballWeight = value; }
}

public int NumberOfPlayers


{
get { return _players; }
set { _players = value; }
}

public double CourtLength


{
get { return _courtLength; }
set { _courtLength = value; }
}

public double CourtWidth


{
get { return _courtWidth; }
set { _courtWidth = value; }
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sport1
{
class Program
{
static int Main()
{
Sport tennis = new Sport();

tennis.BallWeight = 57.50; // grams


tennis.NumberOfPlayers = 1; // Singles game
tennis.CourtLength = 23.70; // meters
tennis.CourtWidth = 8.23; // meters;

Console.WriteLine("Sport Characteristics");
Console.WriteLine("Ball Weight: {0} grams",
tennis.BallWeight);
Console.WriteLine("Players on each side: {0}",
tennis.NumberOfPlayers);
Console.WriteLine("Court Dimensions(LxW): {0}m X {1}m\n",
tennis.CourtLength, tennis.CourtWidth);

return 0;
}
}
}

C# 3.0 Practical Learning 422


6. Execute the application:
 
Sport Characteristics
Ball Weight: 57.5 grams
Players on each side: 1
Court Dimensions(LxW): 23.7m X 8.23m

Press any key to continue . . .

7. Close the DOS window

Equality of Two Class Variables

When you declare and initialize two variables, one of the operations you may want to
subsequently perform is to compare their value. To support this operation, the Object
class provides its children with a method called Equals. The Equals() method comes in
two versions. The first has the following syntax:
public virtual bool Equals(object obj);

This version allows you to call the Equals() method on a declared variable and pass the
other variable as argument. Here is an example:
using System;

class BookCollection
{
static void Main()
{
// First book
int NumberOfPages1 = 422;
// Second book
int NumberOfPages2 = 858;
// Third book
int NumberOfPages3 = 422;

if( NumberOfPages1.Equals(NumberOfPages2) == true )


Console.WriteLine("The first and the second books have the same number
of pages");
else
Console.WriteLine("The first and the second books have different number
of pages");

if( NumberOfPages1.Equals(NumberOfPages3) == true )


Console.WriteLine("The first and the third books have the same number
of pages");
else
Console.WriteLine("The first and the third books have different number
of pages");
}
}

This would produce:


The first and the second books have different number of pages
The first and the third books have the same number of pages

C# 3.0 Practical Learning 423


The first version of the Object.Equals method is declared as virtual, which means you
can override it if you create your own class. The second version of the
Object.Equals() method is:

public static bool Equals(object obj2, object obj2);

As a static method, to use it, you can pass the variables of the two classes whose
values you want to compare.

In both cases, if the values of the variables are similar, the Equals() method returns
true. If they are different, the method returns false. If you are using the Equals()
method to compare the variables of two primitive types, the comparison should be
straight forward. If you want to use this methods on variables declared from your own
class, you should provide your own implementation of this method.

Practical Learning: Implementing Equality

1. Access the Sport.cs file

2. To create your own implementation of the Equals() method, change the file as
follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sport1
{
class Sport
{
. . .

public double CourtWidth


{
get { return _courtWidth; }
set { _courtWidth = value; }
}

public override bool Equals(Object obj)


{
Sport sp = (Sport)obj;

if ((_ballWeight == sp._ballWeight) &&


(_players == sp._players) &&
(_courtLength == sp._courtLength) &&
(_courtWidth == sp._courtWidth))
return true;

return false;
}
}
}

3. Access the Program.cs file and change it as follows:


 
C# 3.0 Practical Learning 424
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sport1
{
class Program
{
static int Main()
{
Sport Euro2002 = new Sport();
Sport CAN2004 = new Sport();
Sport tennis = new Sport();

Euro2002.BallWeight = 435; // grams


Euro2002.NumberOfPlayers = 11; // persons for each team
Euro2002.CourtLength = 100; // meters
Euro2002.CourtWidth = 60; // meters

tennis.BallWeight = 57.50; // grams


tennis.NumberOfPlayers = 1; // Singles game
tennis.CourtLength = 23.70; // meters
tennis.CourtWidth = 8.23; // meters;

CAN2004.BallWeight = 435; // grams


CAN2004.NumberOfPlayers = 11; // persons for each team
CAN2004.CourtLength = 100; // meters
CAN2004.CourtWidth = 60; // meters

if (CAN2004.Equals(tennis) == true)
Console.WriteLine("The CAN2004 and the tennis variables are
equal");
else
Console.WriteLine("The Euro2002 and the tennis variables are not
equal");

if (Euro2002.Equals(CAN2004) == true)
Console.WriteLine("The Euro2002 and CAN2004 variables are
equal");
else
Console.WriteLine("The Euro2002 and CAN2004 variables are not
equal");

return 0;
}
}
}

4. Execute the application. This would produce:


 
The Euro2002 and the tennis variables are not equal
The Euro2002 and CAN2004 variables are equal
Press any key to continue . . .

5. Close the DOS window

Stringing a Class

C# 3.0 Practical Learning 425


In previous lessons, we learned that, to convert the value of a variable declared from a
primitive type to a string, you could call the ToString() function. Here is an example:
using System;

class BookCollection
{
static int Main()
{
int NumberOfPages = 422;

Console.WriteLine("Number of Pages: {0}",


NumberOfPages.ToString());
return 0;
}
}

In many programming languages such as C++, programmers usually have to overload


an (extractor) operator to display the value(s) of class' variable to the screen. The
Object class provides an alternative to this somewhat complicated solution, through the
ToString() method. It syntax is:

public virtual string ToString();

Although the Object class provides this method as non abstract, its implemented
version is more useful if you use a primitive type such as int, double and their variances
or a string variable. The best way to rely on it consists of overriding it in your own class
if you desired to use its role.

Practical Learning: Converting to String

1. Access the Sport.cs file

2. To implement and use a ToString() method, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sport1
{
class Sport
{
private double _ballWeight;
private int _players;
private double _courtLength;
private double _courtWidth;

public double BallWeight


{
get { return _ballWeight; }
set { _ballWeight = value; }
}

C# 3.0 Practical Learning 426


public int NumberOfPlayers
{
get { return _players; }
set { _players = value; }
}

public double CourtLength


{
get { return _courtLength; }
set { _courtLength = value; }
}

public double CourtWidth


{
get { return _courtWidth; }
set { _courtWidth = value; }
}

public override bool Equals(Object obj)


{
Sport sp = (Sport)obj;

if ((_ballWeight == sp._ballWeight) &&


(_players == sp._players) &&
(_courtLength == sp._courtLength) &&
(_courtWidth == sp._courtWidth))
return true;

return false;
}

public override string ToString()


{
string person = null;

if (NumberOfPlayers.Equals(1))
person = " person";
else
person = " persons";

string result =
"\nBall Weight: " + BallWeight + " grams" +
"\nPlayers on each side: " + NumberOfPlayers + person +
"\nCourt Dimensions(LxW): " +
CourtLength + "m X " + CourtWidth + "m";

return result;
}
}
}

3. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

C# 3.0 Practical Learning 427


namespace Sport1
{
class Program
{
static int Main()
{
Sport CAN2004 = new Sport();
Sport tennis = new Sport();

tennis.BallWeight = 57.50; // grams


tennis.NumberOfPlayers = 1; // Singles game
tennis.CourtLength = 23.70; // meters
tennis.CourtWidth = 8.23; // meters;

CAN2004.BallWeight = 435; // grams


CAN2004.NumberOfPlayers = 11; // persons for each team
CAN2004.CourtLength = 100; // meters
CAN2004.CourtWidth = 60; // meters

Console.WriteLine("====================================");
Console.WriteLine("Cup Game Characteristics");
Console.Write("------------------------------------");
Console.WriteLine(CAN2004);

Console.WriteLine("\n====================================");

Console.WriteLine("Tennis Game Characteristics");


Console.Write("------------------------------------");
Console.WriteLine(tennis);
Console.WriteLine("\n====================================");

return 0;
}
}
}

4. Execute the application. This would produce:


 
====================================
Cup Game Characteristics
------------------------------------
Ball Weight: 435 grams
Players on each side: 11 persons
Court Dimensions(LxW): 100m X 60m

====================================
Tennis Game Characteristics
------------------------------------
Ball Weight: 57.5 grams
Players on each side: 1 person
Court Dimensions(LxW): 23.7m X 8.23m

====================================
Press any key to continue . . .

5. Close the DOS window

Boxing and Un-Boxing

C# 3.0 Practical Learning 428


When we study inheritance, we will learn that all data types used in a C# program are
"based on" an object called object. As introduced earlier, you can use this data type to
declare a variable that would hold any type of value. Because this is some type of a
"universal" data type, it can also be initialized with any value. Here are examples:
using System;

class Exercise
{
static void Main()
{
object Number = 244;
object Thing = "Professor Kabba";

Console.WriteLine(Number);
Console.WriteLine(Thing);
}
}

This would produce:


244
Professor Kabba

As you can see, when an object variable is initialized, the compiler finds out the type of
value that was assigned to it. This is referred to as boxing. This mechanism is
transparently done in C# (and in Visual Basic but not in Visual C++ 2003 (it is possible
that something will be done in the next version, or not)).

If you declare a variable using a primitive data type ( int, float, double, etc), at one
time, you may be interested in converting the value of that variable into an object.
Here is an example:
using System;

class Exercise
{
static int Main()
{
int Number = 244;
object Thing = Number;

Console.WriteLine(Number);
Console.WriteLine(Thing);
return 0;
}
}

This would produce:


244
244

This operation is referred to as unboxing. As you can see, this operation is performed
transparently (Visual C++ 2003 doesn't do it transparently).

Boxing and unboxing make C# a very flexible and wonderful language (if you misuse it,
of course it can be dangerous).

C# 3.0 Practical Learning 429


Finalizing a Variable

While a constructor, created for each class, is used to instantiate a class. The Object
class provides the Finalize() method as a type of destructor.

Other Built-In Classes

The System namespace provides one of the largest definition of classes of the .NET
Framework, but it doesn't contain everything. For example, when you start writing
graphical user interface (GUI) applications, you will have to use other namespaces. The
namespaces are contained in libraries called assemblies. The actual classes used in
various applications are created and defined in these libraries. Before using a class, you
must know the name of the assembly in which it is defined. You must also know the
name of its namespace. These three pieces of information, the name of the class, the
namespace in which it is defined, and the name of the assembly in which the
namespace is contained, are very important. Because there are so many classes,
namespaces, and libraries, the MSDN documentation is your best reference. We can
only mention a few, especially those that are relevant for the subjects we are reviewing.

Random numbers
 

Introduction

Imagine you have a series of numbers, such these: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, and 20. Imagine you want to select one of these numbers,
any of them. A number is referred to as random if it has been selected from a pool
without a specific pattern to follow. For example, if you decide to select the value 17
from this list, if there was an exact reason that number was selected, then it is not
considered random. In reality, it is difficult for a number to qualify as random. For this
reason, most random numbers are referred to as pseudo-random.

Getting a Random Number

To support the ability to create or choose a random number, the .NET Framework
provides the Random class. To start, you can declare a variable of this class, using one
of its two constructors. Here is an example that uses the default constructor:
using System;

class Program
{
static int Main()
{
Random rndNumber = new Random();

return 0;
}
}

C# 3.0 Practical Learning 430


After creating the variable, you can start getting numbers from it. To do this, you call
the Next() method, which is overloaded in three versions. One of the versions of this
method takes no argument and its syntax is:
public virtual int Next();

This method generates a randomly selected integer between 0 and the MinValue value
of the int data type. Here is an example:
using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random();
int rndNumber = rndNumbers.Next();

Console.WriteLine("Number: {0}", rndNumber);

return 0;
}
}

Here is an example of running the program:


Number: 1369872590
Press any key to continue . . .

In the same way, you can call this version of the Next() method repeatedly to get
random. Here is an example:
using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random();
int rndNumber = 0;

for (int nbr = 1; nbr < 9; nbr++)


{
rndNumber = rndNumbers.Next();
Console.WriteLine("Number: {0}", rndNumber);
}

return 0;
}
}

Here is an example of running the program:


Number: 1924504148
Number: 1257846191
Number: 424740120
Number: 1009211682
Number: 544356245
Number: 708951978
Number: 759684741
C# 3.0 Practical Learning 431
Number: 1325535324
Press any key to continue . . .

The Seed of a Random Number

Consider the following program:


using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random();
int rndNumber = rndNumbers.Next();

Console.WriteLine("Number: {0}", rndNumber);

return 0;
}
}

Here is an example of running the program:


Number: 573991745
Press any key to continue . . .

Here is another example of running the same program:


Number: 334223329
Press any key to continue . . .

Notice that the numbers generated are different. When creating a program that
repeatedly gets a series of random numbers, you may (or may not) want the Random
class to generate the same number over and over again. A seed is a constant value that
controls whether a random generation would produce the same result every time it
occurs. For example, using a seed, you can impose it upon the Random class to
generate the same number every time the Next() method is called. To support the ability
to use a seed, the Random class is equipped with a second constructor whose syntax is:
public Random(int Seed);

Based on this, to specify a seed, when declaring a Random variable, pass a constant
integer to the constructor. Here is an example:
using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random(20);
int rndNumber = rndNumbers.Next();

Console.WriteLine("Number: {0}", rndNumber);

return 0;
}
}
C# 3.0 Practical Learning 432
Here is one example of running the program:
Number: 375271809
Press any key to continue . . .

Here is another example of running the same program:


Number: 375271809
Press any key to continue . . .

Notice that the numbers are the same. Consider this program also:
using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random(20);
int rndNumber = 0;

for (int nbr = 1; nbr < 5; nbr++)


{
rndNumber = rndNumbers.Next();
Console.WriteLine("Number: {0}", rndNumber);
}

return 0;
}
}

Here is one example of running the program:


Number: 375271809
Number: 1472524622
Number: 1605850688
Number: 1776011503
Press any key to continue . . .

Here is another example of running the same program:


Number: 375271809
Number: 1472524622
Number: 1605850688
Number: 1776011503
Press any key to continue . . .

Notice that the sequences are the same. In both cases, this indicates that, if you specify
a seed, the Random class would generate the same number or the same sequence of
numbers.

Generating Random Numbers in a Range of Numbers

So far, we have been using with any number that would fit an integer. In some
assignments, you may want to restrict the range of numbers that can be extracted.
Fortunately, the Random class allows this. Using the Random class, you can generate
random positive numbers up to a maximum of your choice. To support this, the Random
class is equipped with another version of the Next() method whose syntax is:
C# 3.0 Practical Learning 433
public virtual int Next(int maxValue);

The argument to pass to the method determines the highest integer that can be
generated by the Next() method. The method returns an integer. Here is an example
that generates radom numbers from 0 to 20:
using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random();
int rndNumber = 0;

for (int nbr = 1; nbr < 9; nbr++)


{
rndNumber = rndNumbers.Next(20);
Console.WriteLine("Number: {0}", rndNumber);
}

return 0;
}
}

Here is an example of running the program:


Number: 1
Number: 7
Number: 1
Number: 16
Number: 14
Number: 19
Number: 3
Number: 1
Press any key to continue . . .

The above version of the Next() method generates numbers starting at 0. If you want,
you can specify the minimum and the maximum range of numbers that the Next()
method must work with. To support this, the Random class is equipped with one more
version of this method and that takes two arguments. Its syntax is:
public virtual int Next(int minValue, int maxValue);

The first argument specifies the lowest value that can come from the range. The second
argument holds the highest value that the Next() method can generate. Therefore, the
method would operate between both values. Here is an example that generates random
numbers from 6 to 18:
using System;

class Program
{
static int Main()
{
Random rndNumbers = new Random();
int rndNumber = 0;

C# 3.0 Practical Learning 434


for (int nbr = 1; nbr < 9; nbr++)
{
rndNumber = rndNumbers.Next(6, 18);
Console.WriteLine("Number: {0}", rndNumber);
}

return 0;
}
}

Here is an example of running the program:


Number: 17
Number: 9
Number: 8
Number: 15
Number: 10
Number: 9
Number: 13
Number: 11
Press any key to continue . . .

Notice that the numbers are between 6 and 18.

Built-In Assemblies and Libraries


 

Microsoft Visual Basic Functions

One of the strengths of Visual Basic, from its beginning, was its huge library of
functions. Unfortunately, even when Visual Basic was part of the Visual Studio 6.0
environment, its functions belonged only to it and to its child languages such as VBA
and VBScript. When Visual Studio .NET was created, the developers of Visual Basic
added all of its valuable functions and in fact made them available to the other
languages that use the .NET Framework. This means that those wonderful functions are
available to use in your C# programs.

The functions of Microsoft Visual Basic still belong to it and they can be called
transparently in a Visual Basic application. If you want to use them in a non-Visual Basic
application, you must remember to reference its library. Most (if not all) of the functions
of Visual Basic are created in the Microsoft.VisualBasic.dll assembly but they
might be in different namespaces. Based on this, you can include any Visual Basic
function in your program. Here is an example:
Source File: Exercise.cs

using System;

class Exercise
{
static void Main()
{
double Number;
double Result;

C# 3.0 Practical Learning 435


Console.Write("Enter a number: ");
string strNbr = Console.ReadLine();

if( !Microsoft.VisualBasic.Information.IsNumeric(strNbr) )
Number = 0.00;
else
Number = Microsoft.VisualBasic.Conversion.Val(strNbr);

Result = Number * 2;

Console.WriteLine("{0} * 2 = {1}", Number, Result);


}
}

When compiling the program, you must reference the Microsoft.VisualBasic.dll library.
Here is an example:
csc /reference:Microsoft.VisualBasic.dll Exercise.cs

C# Custom Libraries
 

Introduction

If the .NET Framework doesn't have a class you are looking for, you can create one and
be able to use it over and over again in different programs. You can even create a
commercial class and be able to distribute or sell it. To make this possible, you can
"package" one or more classes in a library. A library is a program that contains classes
and/or other resources that other programs can use. Such a program is created with the
same approach as the programs we have done so far. Because a library is not an
executable, it doesn't need the Main() function. A library usually has the extension .dll.

Creating a Library

A library can be made of a single file or as many files as necessary. A file that is part of
a library can contain one or more classes. Each class should implement a behavior that
can eventually be useful and accessible to other classes. The classes in a library are
created exactly like those we have used so far. Everything depends on how you compile
it.

To create a library, start by typing its code in a text file. Once the library is ready, to
compile it, at the Command Prompt, you would type:
csc /target:library NameOfFile.cs

and press Enter. After doing this, a library with the name of the file and the extension
.dll would be created. If you want a custom name, use the following syntax:
csc /target:library /out:DesiredNameOfLibrary.dll NameOfFile.cs

Practical Learning: Creating a Library

1. To start a new project, on the main menu, click File -> New Project...
C# 3.0 Practical Learning 436
2. In the New Project dialog box, click Class Library

3. Set the Name to Operations1 and click OK

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Operations1
{
public class Operations
{
public static double Addition(double x, double y)
{
return x + y;
}

public static double Subtraction(double x, double y)


{
return x - y;
}

public static double Multiplication(double x, double y)


{
return x * y;
}

public static double Division(double x, double y)


{
if (y == 0)
return 0;
return x / y;
}
}
}

5. In the Solution Explorer, right-click Class1.cs and click Rename

6. Change the name to Operations.cs and press Enter

7. To save the project, on the Standard toolbar, click the Save All button

8. Click Save to save everything

9. On the main menu, click Project -> Operations1 Properties

C# 3.0 Practical Learning 437


10.In the Output Type combo box, make sure Class Library is selected:
 

11.Click the X button to close the Properties window

12.To create the library, on the main menu, click Build -> Build Solution

13.To start another project, on the main menu, click File -> New Project...

14.In the New Project dialog box, select Console Application

15.Set the Name to Algebra1 and press Enter

16.In the Solution Explorer, right-click References and click Add Reference...

17.Click the Browse tab

18.In the list of folders, double-click Operations1 and locate the Operations1.dll file (it
should be in the Release (or the Debug) sub-folder of the bin folder)

C# 3.0 Practical Learning 438


19.Click Operations1.dll
 

20.Click OK.
In the Solution Explorer, expand the References node if necessary and make sure
that there is a new node labeled Operations1

21.Access the Program.cs file and change it as follows:


 
using System;

namespace Algebra1
{
class Program
{
static int Main()
{
double Number1 = 244.58;
double Number2 = 5082.88;
double Result =
Operations1.Operations.Addition(Number1, Number2);

Console.WriteLine("{0} + {1} = {2}\n",


Number1, Number2, Result);
return 0;
}
}
}

22.Execute the application to test it. This would produce:


 
244.58 + 5082.88 = 5327.46

Press any key to continue . . .

C# 3.0 Practical Learning 439


23.Close the DOS window

A Library Created in Another Language


 

Using a Visual C++/CLI Library

One of the most important sought goals in .NET is to allow different languages to
collaborate, such as sharing code. One way this can happen is to be able to use the
functionality of one language into another. As an illustration, we saw earlier that you
could use the rich library of Visual Basic functions in a C# application. As no library is
ever complete, you may still need functionality that is not easily found. Furthermore, you
may be working with a team of C++ programmers who have already created a set of
functions or complex operations. You should be able to use that existing code.

Creating a Library

In previous years, it used to be a challenge to create a library, especially in C++.


Fortunately, Microsoft Visual C++ now makes it particularly easy to create one, because
a wizard highly assists you. To create a library, first display the New Project dialog box.
After specifying Visual C++, in the Templates list, click Class Library and give it a name.
In the body of the file, you can create the classes and/or functions as you see fit. Here is
an example:
// Business.h

#pragma once

using namespace System;

namespace Business {

public ref class Finance


{
public:
double CalculateDiscount(double MarkedPrice,
double DiscountRate)
{
return MarkedPrice * DiscountRate / 100;
}
};
}

Once the project is ready, you must build it (on the main menu, Build -> Build
Business). As a result, the compiler would create a file with the .dll extension:

C# 3.0 Practical Learning 440


Normally, as far as creating a library, that's it.

Using the Library

Creating a library in C++ is easy. To use it, there are a few rules you must follow. To
start, you must make sure that your project can "physically" find the library. Probably
the easiest way to take care of this is to copy the dll file and paste it in the folder that
contains your project's executable. You can also do this directly in Visual Studio by
importing the library file as we saw earlier.

In your project, you should include the System.Runtime.InteropServices


namespace. Before the section where the library will be accessed, enter the DllImport
attribute that takes as argument the name of the library passed as a string. Here is an
example:
using System;
using System.Runtime.InteropServices;
using Business;

namespace DepartmentStore
{
class Exercise
{
[DllImport("Business.dll")]
public static extern double CalculateDiscount(double price,
double discount)

static int Main()


{
Finance fin = new Finance();

double markedPrice = 275.50;


double discountRate = 25.00; // %
double discountAmount = fin.CalculateDiscount(markedPrice,
discountDate);

C# 3.0 Practical Learning 441


double netPrice = markedPrice - discountAmount);

Console.WriteLine("Marked Price: {0:C}", markedPrice);


Console.WriteLine("Discount Rate: {0:P}", discountRate /
100);
Console.WriteLine("Discount Amount: {0:C}", discountAmount);
Console.WriteLine("Net Price: {0:C}\n", netPrice);

return 0;
}
}
}

This makes your library code ready to be used, which you can do as you would any
other code. This means that you can compile your program the way we did in the
previous section.

Using the Win32 Library

The Microsoft Windows operating system was originally written in C, the parent
language of C++ and C# (also of Java and JavaScript). To allow programmers to create
applications, Microsoft released a library called Win32. This is a series of functions and
classes, etc, that you previously had to use. As time has changed, you don't need to
exclusively use Win32 anymore to create a Windows application. Nonetheless, Win32 is
still everywhere and it is not completely avoidable because many or some of the actions
you would want to perform in a Windows application are still available only in Win32.
Fortunately, in most cases, it is not always difficult to use some of these functions in a
C# applications, as long as you observe some rules. Here is an example:
using System;
using System.Runtime.InteropServices;

namespace Win32Applied
{
class Program
{
[DllImport("Kernel32.dll")]
public static extern bool SetConsoleTitle(string strMessage);

static int Main()


{
SetConsoleTitle("C# Programming");

return 0;
}
}
}

C# 3.0 Practical Learning 442


Introduction to Exception
Handling
 

Introduction to Exceptions
 

Overview

During the execution of a program, the computer will face two types of situations: those
it is prepared to deal with and those it is not. Imagine you write a program that requests
a number from the user:
using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
return 0;
}
}

This is a classic easy program. When it comes up, the user is asked to simply type a
number. The number would then be multiplied by 4 and display the result. Imagine that
a user types something that is not a valid number, such as the name of a country or
somebody’s telephone number. Since this program was expecting a number and it is not
prepared to multiply a string to a number, it would not know what to do. The only
alternative the compiler would have is to send the problem to the operating system,
hoping that the OS would know what to do. What actually happens is that, whenever
the compiler is handed a task, it would try to perform the assignment. If it can’t perform
the assignment, for any reason it is not prepared for, it would produce an error. As a
programmer, if you can anticipate the type of error that could occur in your program,
you can identify the error yourself and deal with it by telling the compiler what to do
when this type of error occurs.

C# 3.0 Practical Learning 443


Practical Learning: Introducing Exception Handling

1. Start Microsoft Visual C# and create a Console Application named


GeorgetownCleaningServices5

2. To create a new class, in the Solution Explorer, right-click


GeorgetownCleaningServices2 -> Add -> Class...

3. Set the Name to CleaningOrderInfo and click OK

4. Change the file as follows:


 

using System;

namespace GeorgetownCleaningServices5
{
public class CleaningOrderInfo
{
// Basic information about an order
public string CustomerName;
public string HomePhone;
public DateTime OrderDate;
public DateTime OrderTime;
// Unsigned numbers to represent cleaning items
public uint NumberOfShirts;
public uint NumberOfPants;
public uint NumberOfDresses;
}
}

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to OrderProcessing and press Enter

7. Change the file as follows:


 
using System;

namespace GeorgetownCleaningServices5
{
public class sealed OrderProcessing
{
#region Objects used to process an order
// Price of items
const decimal PriceOneShirt = 0.95M;
const decimal PriceAPairOfPants = 2.95M;
const decimal PriceOneDress = 4.55M;
const decimal TaxRate = 0.0575M; // 5.75%

CleaningOrderInfo cleaningOrder;

// Each of these sub totals will be used for cleaning items


private decimal SubTotalShirts;
private decimal SubTotalPants;
private decimal SubTotalDresses;

C# 3.0 Practical Learning 444


// Values used to process an order
private decimal TotalOrder;
private decimal TaxAmount;
private decimal SalesTotal;
private decimal AmountTended;
private decimal Difference;

#endregion

#region Actions used to process and present an order

public OrderProcessing()
{
cleaningOrder = new CleaningOrderInfo();
}

public void ProcessOrder()


{
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
// Request order information from the user
Console.Write("Enter Customer Name: ");
cleaningOrder.CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
cleaningOrder.HomePhone = Console.ReadLine();
Console.Write("Enter the order date(mm/dd/yyyy): ");
cleaningOrder.OrderDate = DateTime.Parse(Console.ReadLine());
Console.Write("Enter the order time(hh:mm AM/PM): ");
cleaningOrder.OrderTime = DateTime.Parse(Console.ReadLine());

// Request the quantity of each category of items


Console.Write("Number of Shirts: ");
cleaningOrder.NumberOfShirts =
uint.Parse(Console.ReadLine());

Console.Write("Number of Pants: ");


cleaningOrder.NumberOfPants = uint.Parse(Console.ReadLine());

Console.Write("Number of Dresses: ");


cleaningOrder.NumberOfDresses =
uint.Parse(Console.ReadLine());

// Perform the necessary calculations


SubTotalShirts = cleaningOrder.NumberOfShirts *
PriceOneShirt;
SubTotalPants = cleaningOrder.NumberOfPants *
PriceAPairOfPants;
SubTotalDresses = cleaningOrder.NumberOfDresses *
PriceOneDress;
// Calculate the "temporary" total of the order
TotalOrder = SubTotalShirts + SubTotalPants +
SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.WriteLine("\nThe Total order is: {0:C}", SalesTotal);
C# 3.0 Practical Learning 445
// and request money for the order
Console.Write("Amount Tended? ");
AmountTended = decimal.Parse(Console.ReadLine());

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;

ShowReceipt();
}

private void ShowReceipt()


{
Console.WriteLine();
// Display the receipt
Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}",
cleaningOrder.CustomerName);
Console.WriteLine("Home Phone: {0}",
cleaningOrder.HomePhone);
Console.WriteLine("Order Date: {0:D}",
cleaningOrder.OrderDate);
Console.WriteLine("Order Time: {0:t}",
cleaningOrder.OrderTime);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0,3} {1,4} {2,6}",
cleaningOrder.NumberOfShirts, PriceOneShirt,
SubTotalShirts);
Console.WriteLine("Pants {0,3} {1,4} {2,6}",
cleaningOrder.NumberOfPants, PriceAPairOfPants,
SubTotalPants);
Console.WriteLine("Dresses {0,3} {1,4} {2,6}",
cleaningOrder.NumberOfDresses, PriceOneDress,
SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0,6}",
TotalOrder.ToString("C"));
Console.WriteLine("Tax Rate: {0,6}",
TaxRate.ToString("P"));
Console.WriteLine("Tax Amount: {0,6}",
TaxAmount.ToString("C"));
Console.WriteLine("Net Price: {0,6}",
SalesTotal.ToString("C"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0,6}",
AmountTended.ToString("C"));
Console.WriteLine("Difference: {0,6}",
Difference.ToString("C"));
Console.WriteLine("====================================");
}
#endregion
}
}

8. Access the program.cs file and change it as follows:


 
C# 3.0 Practical Learning 446
using System;

namespace GeorgetownCleaningServices5
{
class Program
{
static int Main()
{
OrderProcessing Order = new OrderProcessing();

Order.ProcessOrder();
return 0;
}
}
}

9. Execute the application and test it. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Peter Moonstruck
Enter Customer Phone: (301) 728-8830
Enter the order date(mm/dd/yyyy): 04/22/2006
Enter the order time(hh:mm AM/PM): 08:46
Number of Shirts: 5
Number of Pants: 2
Number of Dresses: 3

The Total order is: $25.70


Amount Tended? 30

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Peter Moonstruck
Home Phone: (301) 728-8830
Order Date: Saturday, April 22, 2006
Order Time: 8:46 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 5 0.95 4.75
Pants 2 2.95 5.90
Dresses 3 4.55 13.65
------------------------------------
Total Order: $24.30
Tax Rate: 5.75 %
Tax Amount: $1.40
Net Price: $25.70
------------------------------------
Amount Tended: $30.00
Difference: $4.30
====================================
Press any key to continue . . .

10.Close the DOS window

Exceptional Behaviors

C# 3.0 Practical Learning 447


An exception is an unusual situation that could occur in your program. As a programmer,
you should anticipate any abnormal behavior that could be caused by the user entering
wrong information that could otherwise lead to unpredictable results. The ability to deal
with a program’s eventual abnormal behavior is called exception handling. C# provides
three keywords to handle an exception.

1. Trying the normal flow: To deal with the expected behavior of a program, use
the try keyword as in the following syntax:

try {Behavior}

The try keyword is required. It lets the compiler know that you are attempting a
normal flow of the program. The actual behavior that needs to be evaluated is
included between an opening curly bracket “{“ and a closing curly bracket “}”.
Inside of the brackets, implement the normal flow that the program must follow, at
least for this section of the code. Here is an example:
 
using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");

try
{
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
}

return 0;
}
}

2. Catching Errors: During the flow of the program as part of the try section, if an
abnormal behavior occurs, instead of letting the program crash or instead of letting
the compiler send the error to the operating system, you can transfer the flow of
the program to another section that can deal with it. The syntax used by this
section is:

catch {WhatToDo}

This section always follows the try section. There must not be any code between
the try’s closing bracket and the catch section. The catch keyword is required
and follows the try section. Combined with the try block, the syntax of an

C# 3.0 Practical Learning 448


exception would be:
 
try
{
// Try the program flow
}
catch
{
// Catch the exception
}

A program that includes a catch section would appear as follows:


 
using System;

public class Exercise


{
static int Main()
{
double Number;

try
{
Console.Write("Type a number: ");
Number = double.Parse(Console.ReadLine());

Console.WriteLine("\n{0} * 2 = {1}", Number, Number * 2);


}
catch
{
}

return 0;
}
}

Practical Learning: Introducing Vague Exceptions

1. To introduce exceptions, access the OrderProcessing.cs file and change it as


follows:
 
using System;

namespace GeorgetownCleaningServices5
{
class OrderProcessing
{
. . . No Change

public void ProcessOrder()


{
. . . No Change

C# 3.0 Practical Learning 449


// Request the quantity of each category of items
try
{
Console.Write("Number of Shirts: ");
Order.NumberOfShirts = uint.Parse(Console.ReadLine());
}
catch
{
}

try
{
Console.Write("Number of Pants: ");
Order.NumberOfPants = uint.Parse(Console.ReadLine());
}
catch
{
}

try
{
Console.Write("Number of Dresses: ");
Order.NumberOfDresses = uint.Parse(Console.ReadLine());
}
catch
{
}

. . . No Change

// and request money for the order


try
{
Console.Write("Amount Tended? ");
AmountTended = decimal.Parse(Console.ReadLine());
}
catch
{
}

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;

ShowReceipt();
}

private void ShowReceipt()


{
. . . No Change
}
}
}

2. Execute the application to test it

3. Close the DOS window

Exceptions and Custom Messages


C# 3.0 Practical Learning 450
As mentioned already, if an error occurs when processing the program in the try section,
the compiler transfers the processing to the next catch section. You can then use the
catch section to deal with the error. At a minimum, you can display a message to inform
the user. Here is an example:
using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");
try
{
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
}
catch
{
Console.WriteLine("There was a problem with the program");
}

return 0;
}
}

Here is an error of running the program:


Square Processing
Enter Side: w4
There was a problem with the program
Press any key to continue . . .

Of course, this type of message is not particularly clear but this time, the program will
not crash. In the next sections, we will learn better ways of dealing with the errors and
the messages.

Practical Learning: Displaying Custom Messages

1. To display custom messages to the user, change the OrderProcessing.cs file as


follows:
 
using System;

namespace GeorgetownCleaningServices5
{
class OrderProcessing
{
. . . No Change

C# 3.0 Practical Learning 451


public void ProcessOrder()
{
. . . No Change

// Request the quantity of each category of items


try
{
Console.Write("Number of Shirts: ");
Order.NumberOfShirts = uint.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("The value you typed for the number of "
+
"shirts is not a valid number");
}

try
{
Console.Write("Number of Pants: ");
Order.NumberOfPants = uint.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("The value you typed for the number of "
+
"pair or pants is not a valid number");
}

try
{
Console.Write("Number of Dresses: ");
Order.NumberOfDresses = uint.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("The value you typed for the number of "
+
"dresses is not a valid number");
}

. . . No Change

try
{
Console.Write("Amount Tended? ");
AmountTended = decimal.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine(
"You were asked to enter an amount of money but...");
}

// Calculate the difference owed to the customer


// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;

ShowReceipt();
}
C# 3.0 Practical Learning 452
private void ShowReceipt()
{
. . . No Change
}
}
}

2. Execute the application to test it. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Alexandria
Enter Customer Phone: (102) 797-8382
Enter the order date(mm/dd/yyyy): 04/02/2001
Enter the order time(hh:mm AM/PM): 09:22 AM
Number of Shirts: 6
Number of Pants: W
The value you typed for the number of pair or pants is not a valid number
Number of Dresses: 5

The Total order is: $30.09


Amount Tended? _100D
You were asked to enter an amount of money but...

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Alexandria
Home Phone: (102) 797-8382
Order Date: Monday, April 02, 2001
Order Time: 9:22 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 6 0.95 5.70
Pants 0 2.95 0
Dresses 5 4.55 22.75
------------------------------------
Total Order: $28.45
Tax Rate: 5.75 %
Tax Amount: $1.64
Net Price: $30.09
------------------------------------
Amount Tended: $0.00
Difference: ($30.09)
====================================

3. Close the DOS window

Exceptions in the .NET Framework


 

The Exception Class

In traditionally-oriented error dealing languages such as C/C++, Object Pascal, or Visual


Basic, you could create any exception of your choice, including numeric or strings. To
C# 3.0 Practical Learning 453
customize exception handling, you could also create your own class(es). Most libraries
such as Borland's VCL and Microsoft's MFC also shipped with their own classes to handle
exceptions. Even the Win32 library provides its type of mechanism to face errors. To
support exception handling, the .NET Framework provides a special class called
Exception. Once the compiler encounters an error, the Exception class allows you to
identify the type of error and take an appropriate action.

Normally, Exception mostly serves as the general class of exceptions. Anticipating


various types of problems that can occur in a program, Microsoft derived various classes
from Exception to make this issue friendlier. As a result, almost any type of exception
you may encounter already has a class created to deal with it. Therefore, when your
program faces an exception, you can easily identify the type of error. There are so many
exception classes that we cannot study or review them all. The solution we will use is to
introduce or review a class when we meet its type of error.

The Exception's Message

In exception handling, errors are dealt with in the catch section. To do this, use catch
as if it were a method. This means that, on the right side of catch, open a parenthesis,
declare a variable of the type of exception you want to deal with. By default, an
exception is first of type Exception. Based on this, a typical formula to implement
exception handling is:
try
{
// Process the normal flow of the program here
}
catch(Exception e)
{
// Deal with the exception here
}

When an exception occurs in the try section, code compilation is transferred to the
catch section. If you declare the exception as an Exception type, this class will identify
the error. One of the properties of the Exception class is called Message. This property
contains a string that describes the type of error that occurred. You can then access this
Exception.Message property to display an error message if you want. Here is an
example:
using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");
try
{
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

C# 3.0 Practical Learning 454


Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}

return 0;
}
}

Here is an example of running the program:


Square Processing
Enter Side: Wer24
Input string was not in a correct format.
Press any key to continue . . .

Custom Error Messages

As you can see, one of the strengths of the Exception.Message property is that it gives
you a good indication of the type of problem that occurred. Sometimes, the message
provided by the Exception class may not appear explicit enough. In fact, you may not
want to show it to the user since, as in this case, the user may not understand what the
expression "correct format" in this context means and why it is being used. As an
alternative, you can create your own message and display it to the user. Here is an
example:
using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");
try
{
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
}
catch(Exception ex)
{

Console.WriteLine("The operation could not be carried because


" +

"the number you typed is not valid");


}

return 0;
C# 3.0 Practical Learning 455
}
}

Here is an example of running the program:


Square Processing
Enter Side: 24.Gh
The operation could not be carried because the number you typed is not
valid
Press any key to continue . . .

You can also combine the Exception.Message message and your own message:
using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");
try
{
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
}
catch(Exception ex)
{
Console.Write(ex.Message);
Console.WriteLine(
" Consequently, The operation could not be carried because
" +
"the number you typed is not valid");
}

return 0;
}
}

Here is an example of running the program:


Square Processing
Enter Side: 25.KL48
Input string was not in a correct format.. Consequently, The operation
could not
be carried because the number you typed is not valid
Press any key to continue . . .

A Review of .NET Exception Classes


 

Introduction

C# 3.0 Practical Learning 456


The .NET Framework provides various classes to handle almost any type of exception
you can think of. There are so many of these classes that we can only mention the few
that we regularly use in our application.

There are two main ways you can use one of the classes of the .NET Framework. If you
know for sure that a particular exception will be produced, pass its name to the catch()
clause. You don't have to name the argument. Then, in the catch() section, display a
custom message. The second option you have consists of using the throw keyword. We
will study it later.

From now on, we will try to always indicate the type of exception that could be thrown if
something goes wrong in a program

The FormatException Exception

When studying data formatting in Lesson 5, we saw that everything the user types
into an application using the keyboard is primarily a string and that you must convert it
to the appropriate type before using it. When you request a specific type of value from
the user, after the user has typed it and you decide to convert it to the appropriate type,
if your conversion fails, the program produces an error. The error is of the
FormatException class.

Here is a program that deals with a FormatException exception:


using System;

class Program
{
static int Main()
{
double side;

Console.WriteLine("Square Processing");
try
{
Console.Write("Enter Side: ");
side = double.Parse(Console.ReadLine());

Console.WriteLine("\nSquare Characteristics");
Console.WriteLine("Side: {0}", side);
Console.WriteLine("Perimeter: {0}", side * 4);
}
catch(FormatException)
{
Console.WriteLine("\nYou typed an invalid number");
}

return 0;
}
}

Here is an example of running the program:


Square Processing
Enter Side: 25.9G

You typed an invalid number


C# 3.0 Practical Learning 457
Press any key to continue . . .

Practical Learning: Using the FormatException Class

1. Change the OrderProcessing.cs file as follows (this includes the complete current
version of the file):
 
using System;

namespace GeorgetownCleaningServices5
{
class OrderProcessing
{
#region Objects used to process an order
// Price of items
const decimal PriceOneShirt = 0.95M;
const decimal PriceAPairOfPants = 2.95M;
const decimal PriceOneDress = 4.55M;
const decimal TaxRate = 0.0575M; // 5.75%

CleaningOrderInfo cleaningOrder;

// Each of these sub totals will be used for cleaning items


private decimal SubTotalShirts;
private decimal SubTotalPants;
private decimal SubTotalDresses;

// Values used to process an order


private decimal TotalOrder;
private decimal TaxAmount;
private decimal SalesTotal;
private decimal AmountTended;
private decimal Difference;

#endregion

#region Actions used to process and present an order

public OrderProcessing()
{
cleaningOrder = new CleaningOrderInfo();
}

public void ProcessOrder()


{
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
// Request order information from the user
Console.Write("Enter Customer Name: ");
cleaningOrder.CustomerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
cleaningOrder.HomePhone = Console.ReadLine();

try
{
Console.Write("Enter the order date(mm/dd/yyyy): ");
cleaningOrder.OrderDate =
DateTime.Parse(Console.ReadLine());

C# 3.0 Practical Learning 458


}
catch (FormatException)
{
Console.WriteLine("The value you entered is not a valid
date");
}
try
{
Console.Write("Enter the order time(hh:mm AM/PM): ");
cleaningOrder.OrderTime =
DateTime.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("The value you entered is not a valid
time");
}

// Request the quantity of each category of items


try
{
Console.Write("Number of Shirts: ");
cleaningOrder.NumberOfShirts =
uint.Parse(Console.ReadLine());
if (cleaningOrder.NumberOfShirts < uint.MinValue)
throw new OverflowException("Negative value not " +
"allowed for shirts");
}
catch (FormatException)
{
Console.WriteLine("The value you typed for the number of
" +
"shirts is not a valid number");
}
try
{
Console.Write("Number of Pants: ");
cleaningOrder.NumberOfPants =
uint.Parse(Console.ReadLine());
}
catch(FormatException)
{
Console.WriteLine("The value you typed for the number of
" +
"pair or pants is not a valid number");
}
try
{
Console.Write("Number of Dresses: ");
cleaningOrder.NumberOfDresses =
uint.Parse(Console.ReadLine());
}
catch(FormatException)
{
Console.WriteLine("The value you typed for the number of
" +
"dresses is not a valid number");
}
// Perform the necessary calculations

C# 3.0 Practical Learning 459


SubTotalShirts = cleaningOrder.NumberOfShirts *
PriceOneShirt;
SubTotalPants = cleaningOrder.NumberOfPants *
PriceAPairOfPants;
SubTotalDresses = cleaningOrder.NumberOfDresses *
PriceOneDress;
// Calculate the "temporary" total of the order
TotalOrder = SubTotalShirts + SubTotalPants +
SubTotalDresses;

// Calculate the tax amount using a constant rate


TaxAmount = TotalOrder * TaxRate;
// Add the tax amount to the total order
SalesTotal = TotalOrder + TaxAmount;

// Communicate the total to the user...


Console.WriteLine("\nThe Total order is: {0:C}", SalesTotal);
// and request money for the order
try
{
Console.Write("Amount Tended? ");
AmountTended = decimal.Parse(Console.ReadLine());
}
catch(FormatException)
{
Console.WriteLine("You were asked to enter an " +
"amount of money but...");
}
// Calculate the difference owed to the customer
// or that the customer still owes to the store
Difference = AmountTended - SalesTotal;

ShowReceipt();
}

private void ShowReceipt()


{
Console.WriteLine();
// Display the receipt
Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}",
cleaningOrder.CustomerName);
Console.WriteLine("Home Phone: {0}",
cleaningOrder.HomePhone);
Console.WriteLine("Order Date: {0:D}",
cleaningOrder.OrderDate);
Console.WriteLine("Order Time: {0:t}",
cleaningOrder.OrderTime);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0,3} {1,4} {2,6}",
cleaningOrder.NumberOfShirts, PriceOneShirt,
SubTotalShirts);
Console.WriteLine("Pants {0,3} {1,4} {2,6}",
cleaningOrder.NumberOfPants, PriceAPairOfPants,
SubTotalPants);
Console.WriteLine("Dresses {0,3} {1,4} {2,6}",
C# 3.0 Practical Learning 460
cleaningOrder.NumberOfDresses, PriceOneDress,
SubTotalDresses);
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0,6}",
TotalOrder.ToString("C"));
Console.WriteLine("Tax Rate: {0,6}",
TaxRate.ToString("P"));
Console.WriteLine("Tax Amount: {0,6}",
TaxAmount.ToString("C"));
Console.WriteLine("Net Price: {0,6}",
SalesTotal.ToString("C"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0,6}",
AmountTended.ToString("C"));
Console.WriteLine("Difference: {0,6}",
Difference.ToString("C"));
Console.WriteLine("====================================");
}
#endregion
}
}

2. Execute the application and test it. Here is an example:


 
-/- Georgetown Cleaning Services -/-
Enter Customer Name: Allen Dons
Enter Customer Phone: 202-442-0400
Enter the order date(mm/dd/yyyy): 7/14/2005
Enter the order time(hh:mm AM/PM): 8:46 AM
Number of Shirts: 5
Number of Pants: 2
Number of Dresses: 0

The Total order is: $11.26


Amount Tended? 15

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Allen Dons
Home Phone: 202-442-0400
Order Date: Thursday, July 14, 2005
Order Time: 8:46 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 5 0.95 4.75
Pants 2 2.95 5.90
Dresses 0 4.55 0.00
------------------------------------
Total Order: $10.65
Tax Rate: 5.75 %
Tax Amount: $0.61
Net Price: $11.26
------------------------------------
Amount Tended: $15.00
Difference: $3.74
====================================
Press any key to continue . . .
C# 3.0 Practical Learning 461
3. Close the DOS window

The OverflowException Exception

A computer application receives, processes, and produces values on a regular basis as


the program is running. To better manage these values, as we saw when studying
variables and data types in Lesson 1 and Lesson 2, the compiler uses appropriate
amounts of space to store its values. It is not unusual that either you the programmer or
a user of your application provides an value that is beyond the allowed range based on
the data type. For example, we saw that a byte uses 8 bits to store a value and a
combination of 8 bits can store a number no more than 255. If you provide a value
higher than 255 to be stored in a byte, you get an error. Consider the following
program:
using System;

// An Exercise class
class Exercise
{
static int Main()
{
byte NumberOfPages;

Console.Write("Enter the number of pages of the newspaper: ");


NumberOfPages = byte.Parse(Console.ReadLine());

Console.WriteLine("Number of Pages of the Newspaper: {0}\n",


NumberOfPages);
}

return 0;
}

When a value beyond the allowable range is asked to be stored in memory, the compiler
produces (the expression is "throws" as we will learn soon) an error of the
OverflowException class. Here is an example of running the program:

Enter the number of pages of the newspaper: 824

Unhandled Exception: System.OverflowException: Value was either too large


or too
small for an unsigned byte.
at System.Byte.Parse(String s, NumberStyles style, IFormatProvider
provider)
at System.Byte.Parse(String s)
at Exercise.Main() in c:\programs\msvcs .net
2003\project17\exercise.cs:line
11

As with the other errors, when this exception is thrown, you should take an appropriate
action.

The ArgumentOutOfRangeException Exception

C# 3.0 Practical Learning 462


Once again, when studying the techniques of converting or formatting values in Lesson
5, we saw that a value was passed to the Parse() method of its data type for analysis.
For a primitive data type, the Parse() method scans the string and if the string cannot
be converted into a valid value, the compiler usually produces a FormatException
exception as we saw above. Other classes such as DateTime also use a Parse()
method to scan the value submitted to it. For example, if you request a date value from
the user, the DateTime.Parse() method scans the string to validate it. In US English,
Parse() expects the user to type a string in the form m/d/yy or mm/dd/yy or
mm/dd/yyyy. Consider the following program:
using System;

// An Exercise class
class Exercise
{
static int Main()
{
DateTime DateHired;

Console.Write("Enter Date Hired: ");


DateHired = DateTime.Parse(Console.ReadLine());

Console.WriteLine("Date Hired: {0:d}\n", DateHired);

return 0;
}
}

If the user types a value that cannot be converted into a valid date, the compiler
produces an ArgumentOutOfRangeException exception. Here is an example of running
the above program:
Enter Date Hired: 1244/04/258

Unhandled Exception: System.FormatException:


String was not recognized as a valid DateTime.
at System.DateTimeParse.Lex(Int32 dps, __DTString str, DateTimeToken
dtok,
DateTimeRawInfo raw, DateTimeResult result, DateTimeFormatInfo& dtfi)
at System.DateTimeParse.Parse(String s,
DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider,
DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider)
at System.DateTime.Parse(String s)
at Exercise.Main() in c:\programs\msvcs .net
2003\project17\exercise.cs:line 11

One way you can avoid this is to guide the user but still take appropriate actions.

The DivideByZeroException Exception

Division by zero is an operation to always avoid. It is so important that it is one of the


most fundamental exceptions of the computer. It is addressed at the core level even by
the Intel and AMD processors. It is also addressed by the operating systems at their
level. It is also addressed by most, if not all, compilers. It is also addressed by most, if
C# 3.0 Practical Learning 463
not all, libraries. This means that this exception is never welcomed anywhere. The .NET
Framework also provides it own class to face this operation.

If an attempt to divide a value by 0 is performed, the compiler produces a


DivideByZeroException exception.

C# 3.0 Practical Learning 464


Using Exception Handling
 

Techniques of Using Exceptions


 

Introduction

As mentioned in the previous lesson, the Exception class is equipped with a Message
property that holds a string about the error that occurred. The message of this property
may not be particularly useful to a user. Fortunately, you can create your own message
and pass it to the Exception class. To be able to receive custom messages, the
Exception class provides the following constructor:

public Exception(string message);

Besides using this class or one of its derived classes in a catch clause, you can call this
constructor to give a new and customized implementation of the exception.

  

Practical Learning: Using Exceptions

1. Start Microsoft Visual C# and create a new Console Application named


RealEstate3

2. To create a new class, in the Class View, right-click the name of the project,
position the mouse on Add and click Class...

3. Set the Name to Property and press Enter

4. Change the file as follows:


 

using System;

namespace RealEstate3
{
public enum PropertyCondition
{
Unknown,
Excellent,
Good,
NeedsRepair,
BadShape
}

C# 3.0 Practical Learning 465


public class Property
{
private string propNbr;
private PropertyCondition cond;
private short beds;
private float baths;
private int yr;
private decimal val;

public Property()
{
}

public string PropertyNumber


{
get { return propNbr; }
set
{
if (propNbr == "")
propNbr = "N/A";
else
propNbr = value;
}
}

public PropertyCondition Condition


{
get { return cond; }
set { cond = value; }
}

public short Bedrooms


{
get
{
if (beds <= 1)
return 1;
else
return beds;
}
set { beds = value; }
}

public float Bathrooms


{
get{ return (baths <= 0) ? 0.00f : baths; }
set { baths = value; }
}

public int YearBuilt


{
get { return yr; }
set { yr = value; }
}

public decimal Value


{
get{ return (val <= 0) ? 0.00M : val; }
set { val = value; }
}
C# 3.0 Practical Learning 466
}
}

5. On the main menu, click Project -> Add Class...

6. Set the Name to HouseType and press Enter

7. To derive a class, change the file as follows:


 
using System;

namespace RealEstate3
{
public class HouseType : Property
{
private short nbrOfStories;
private bool basement;
private bool garage;

public short Stories


{
get { return nbrOfStories; }
set { nbrOfStories = value; }
}

public bool FinishedBasement


{
get { return basement; }
set { basement = value; }
}

public bool IndoorGarage


{
get { return garage; }
set { garage = value; }
}
}
}

8. On the main menu, click Project -> Add -> Class...

9. Set the Name to Condominium and press Enter

10.To create another class based on the Property class, change the file as follows:
 
using System;

namespace RealEstate3
{

public class Condominium : Property

{
private bool handicap;

public bool HandicapAccessible


{
get { return handicap; }
C# 3.0 Practical Learning 467
set { handicap = value; }
}
}
}

11. 

12.To create a new class, in the Solution Explorer, right-click RealEstate3, position the
mouse on Add and click Class...

13.Set the Name to PropertyListing and press Enter

14.Change the file as follows:


 
using System;

namespace RealEstate3
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class PropertyListing


{
private Property prop;
private HouseType hse;
private Condominium cond;
private PropertyType tp;

public Property ListProperty


{
get { return prop; }
set { prop = value; }
}

public HouseType House


{
get { return hse; }
set { hse = value; }
}

public Condominium Condo


{
get { return cond; }
set { cond = value; }
}

public PropertyType Type


{
get { return tp; }
set { tp = value; }
}

public PropertyListing()
{
C# 3.0 Practical Learning 468
prop = new Property();
hse = new HouseType();
cond = new Condominium();
}

public void CreateListing()


{
char answer = 'n';
short propType = 1;
short condition = 1;

Console.WriteLine(" =//= Altair Realty =//=");


Console.WriteLine("-=- Property Creation -=-");
try
{
Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.WriteLine("4. Don't Know");
Console.Write("Enter Type of Property: ");
propType = short.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}

Console.Write("\nEnter Property #: ");


ListProperty.PropertyNumber = Console.ReadLine();

try
{
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.Write("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
Console.Write("Enter Property Condition: ");
condition = short.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}

if (condition == 1)
ListProperty.Condition = PropertyCondition.Excellent;
else if (condition == 2)
ListProperty.Condition = PropertyCondition.Good;
else if (condition == 3)
ListProperty.Condition = PropertyCondition.NeedsRepair;
else if (condition == 4)
ListProperty.Condition = PropertyCondition.BadShape;
else
ListProperty.Condition = PropertyCondition.Unknown;

switch ((PropertyType)propType)
{
C# 3.0 Practical Learning 469
case PropertyType.SingleFamily:
Type = PropertyType.SingleFamily;
try
{
Console.Write("\nHow many stories (levels)? ");

House.Stories = short.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Console.Write(
"Does it have an indoor car garage (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Indoor Car Garage
Answer");
}
try
{
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Basement Answer");
}
break;

case PropertyType.Townhouse:
Type = PropertyType.Townhouse;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
Console.Write("Does it have an indoor car garage
(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
C# 3.0 Practical Learning 470
House.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
break;

case PropertyType.Condominium:
Type = PropertyType.Condominium;
Console.Write(
"\nIs the building accessible to handicapped (y/n):
");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
Condo.HandicapAccessible = true;
else
Condo.HandicapAccessible = false;
break;

default:
Type = PropertyType.Unknown;
break;
}

try
{
Console.Write("\nHow many bedrooms? ");
ListProperty.Bedrooms = short.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Console.Write("How many bathrooms? ");
ListProperty.Bathrooms = float.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Console.Write("Year built: ");
ListProperty.YearBuilt = int.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Console.Write("Property Value: ");
ListProperty.Value = decimal.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
C# 3.0 Practical Learning 471
Console.WriteLine(ex.Message);
}
}

public void ShowProperty()


{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
ListProperty.PropertyNumber);
Console.WriteLine("Property Type: {0}", Type);

switch (Type)
{
case PropertyType.SingleFamily:
case PropertyType.Townhouse:
Type = PropertyType.SingleFamily;
Console.WriteLine("Stories: {0}",
House.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
House.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
House.FinishedBasement);
break;

case PropertyType.Condominium:
Console.WriteLine("Handicapped Accessible Building:
{0}",
Condo.HandicapAccessible);
break;
}

Console.WriteLine("Condition: {0}",
ListProperty.Condition);
Console.WriteLine("Bedrooms: {0}",
ListProperty.Bedrooms);
Console.WriteLine("Bathrooms: {0}",
ListProperty.Bathrooms);
Console.WriteLine("Year Built: {0}",
ListProperty.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
ListProperty.Value);
}
}
}

15.Access the Program.cs file and change it as follows:


 
using System;

namespace RealEstate3
{
public static class Program
{
static int Main()
{
PropertyListing listing = new PropertyListing();
C# 3.0 Practical Learning 472
listing.CreateListing();
Console.WriteLine("\n");
listing.ShowProperty();
Console.WriteLine();
return 0;
}
}
}

16.Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 1

Enter Property #: 276744

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? -2


Does it have an indoor car garage (y/n): g
Is the basement finished(y/n): m

How many bedrooms? -5


How many bathrooms? 3684634
Year built: 87324
Property Value: 2

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 276744
Property Type: SingleFamily
Stories: -2
Has Indoor Car Garage: False
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 1
Bathrooms: 3684634
Year Built: 87324
Market Value: $2.00

Press any key to continue . . .

17.Close the DOS window


C# 3.0 Practical Learning 473
Throwing an Exception

When a bad behavior occurs in your application, the


program is said to throw an exception. Your job is to
know, as much as possible, when and why this would
happen. In the previous lesson and in the above section,
we saw that, when an application throws an exception,
you could display your own message. To effectively
address a particular exception, you need to identify the
(exact, if possible) section of code where the exception
would occur and you should know why the error would
be produced. After identifying the area in code where an
exception is likely to occur, you can further customize
the behavior of your application.

To customize the throwing of an exception, in the section of code where you are
anticipating the error, type the throw keyword followed by a new instance of the
Exception class (or one of its derived classes) using the constructor that takes a string.
Here is an example:
using System;

class Program
{
static int Main()
{
double Operand1, Operand2;
double Result = 0.00;
char Operator;

Console.WriteLine(
"This program allows you to perform an operation on two
numbers");

try
{
Console.Write("Enter a number: ");
Operand1 = double.Parse(Console.ReadLine());
Console.Write("Enter an operator: ");
Operator = char.Parse(Console.ReadLine());
Console.Write("Enter a number: ");
Operand2 = double.Parse(Console.ReadLine());

if (Operator != '+' && Operator != '-' && Operator != '*' &&


Operator != '/')
throw new Exception(Operator.ToString());

switch (Operator)
{
case '+':
Result = Operand1 + Operand2;
break;

case '-':
Result = Operand1 - Operand2;

C# 3.0 Practical Learning 474


break;

case '*':
Result = Operand1 * Operand2;
break;

case '/':
Result = Operand1 / Operand2;
break;

default:
Console.WriteLine("Bad Operation");
break;
}
Console.WriteLine("\n{0} {1} {2} = {3}", Operand1, Operator, Operand2,
Result);
}
catch (Exception ex)
{
Console.WriteLine("\nOperation Error: {0} is not a valid operator",
ex.Message);
}

return 0;
}
}

Here is an example of running the program:


This program allows you to perform an operation on two numbers
Enter a number: 124.55
Enter an operator: &
Enter a number: 36.85

Operation Error: & is not a valid operator


Press any key to continue . . .

Practical Learning: Throwing an Exception

1. Access the PropertyListing.cs file

2. To throw some exceptions, change the file as follows:


 
using System;

namespace RealEstate3
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

class PropertyListing
C# 3.0 Practical Learning 475
{
. . . No Change

public void CreateListing()


{
. . . No Change

switch ((PropertyType)propType)
{
case PropertyType.SingleFamily:
Type = PropertyType.SingleFamily;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());

if (House.Stories < 1)
{
House.Stories = 1;
throw new OverflowException(
"The number of stories must be positive");
}
}
catch (OverflowException ex)
{
Console.WriteLine(ex.Message);
}

. . . No Change

break;

case PropertyType.Townhouse:
Type = PropertyType.Townhouse;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());

if (House.Stories < 1)
{
House.Stories = 1;
throw new OverflowException(
"The number of stories must be positive");
}
}
catch (OverflowException ex)
{
Console.WriteLine(ex.Message);
}

. . . No Change
}

. . . No Change
}

public void ShowProperty()


{
. . . No Change
C# 3.0 Practical Learning 476
}
}
}

3. Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 2

Enter Property #: 463864

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? -3


The number of levels must be positive
Does it have an indoor car garage (y/n): G
Is the basement finished(y/n): K

How many bedrooms? -4


How many bathrooms? -2
Year built: 2994
Property Value: 425885

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 463864
Property Type: Townhouse
Stories: 1
Has Indoor Car Garage: False
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 1
Bathrooms: 0.00
Year Built: 2994
Market Value: $425,885.00

Press any key to continue . . .

4. Close the DOS window

Catching Various Exceptions

C# 3.0 Practical Learning 477


In the examples above, when we anticipated some type of problem, we instructed the
compiler to use our default catch section. We left it up to the compiler to find out when
there was a problem and we provided a catch section to deal with it. A method with
numerous or complex operations and requests can also produce different types of
errors. With such a type of program, you should be able to face different problems and
deal with them individually, each by its own kind. To do this, you can create different
catch sections, each made for a particular error. The formula used would be:

try {
// Code to Try
}
catch(Arg1)
{
// One Exception
}
catch(Arg2)
{
// Another Exception
}

The compiler would proceed in a top-down:

1. Following the normal flow of the program, the compiler enters the try block

2. If no exception occurs in the try block, the rest of the try block is executed
If an exception occurs in the try block, the compiler registers the type of error that
occurred. If there is a throw line, the compiler registers it also:

a. The compiler gets out of the try section

b. The compiler examines the first catch. If the first catch matches the
thrown error, that catch executes and the exception handling routine may
seize. If the first catch doesn’t match the thrown error, the compiler
proceeds with the next catch

c. The compiler checks the next match, if any, and proceeds as in the first
catch. This continues until the compiler finds a catch that matches the
thrown error

d. If one of the catches matches the thrown error, its body executes. If no
catch matches the thrown error, the compiler calls the Exception class and
uses the default message

Multiple catches are written if or when a try block is expected to throw different types of
errors. Once again, consider the previous program. That program works fine as long as
the user types a valid sequence of values made of a number, a valid arithmetic operator,
and a number. Anything else, such as an invalid number, an unexpected operator, or a
wrong sequence (such as a number then another number instead of an operator), would
cause an error. Obviously various bad things could happen when this program is
running. To handle the exceptions that this program could produce, you can start with
the most likely problem that would occur. Trusting that a user is able to provide the two
numbers that are requested, it is possible that a user would type an invalid operator. For
example, for this program we will perform only the addition (+), the subtraction(-), the
multiplication(*), and the division(/). Therefore, we will first validate the operator. This
can be done as follows:
C# 3.0 Practical Learning 478
using System;

class Program
{
static int Main()
{
double Operand1, Operand2;
double Result = 0.00;
char Operator;

Console.WriteLine("This program allows you to perform an operation on two


numbers");

try
{
Console.Write("Enter a number: ");
Operand1 = double.Parse(Console.ReadLine());
Console.Write("Enter an operator: ");
Operator = char.Parse(Console.ReadLine());
Console.Write("Enter a number: ");
Operand2 = double.Parse(Console.ReadLine());

if (Operator != '+' &&


Operator != '-' &&
Operator != '*' &&
Operator != '/')
throw new Exception(Operator.ToString());

switch (Operator)
{
case '+':
Result = Operand1 + Operand2;
break;

case '-':
Result = Operand1 - Operand2;
break;

case '*':
Result = Operand1 * Operand2;
break;

case '/':
Result = Operand1 / Operand2;
break;

default:
Console.WriteLine("Bad Operation");
break;
}
Console.WriteLine("\n{0} {1} {2} = {3}", Operand1, Operator, Operand2,
Result);
}
catch (Exception ex)
{
Console.WriteLine("\nOperation Error: {0} is not a valid operator",
ex.Message);
}
C# 3.0 Practical Learning 479
return 0;
}
}

When this program runs, if the user provides a valid number followed by a wrong
operator, we call the Exception(string message) constructor and pass it a string
converted from the character that was typed.

Imagine that the user wants to perform a division. You need to tell the compiler what to
do if the user enters the denominator as 0 (or 0.00). If this happens, probably the best
option is to display a message and get out. Fortunately, the .NET Framework provides
the DivideByZeroException class to deal with an exception caused by division by
zero. As done with the message passed to the Exception class, you can compose your
own message and pass it to the DivideByZeroException(string message)
constructor.

Here is an example that catches two types of exceptions:


using System;

class Program
{
static int Main()
{
double Operand1, Operand2;
double Result = 0.00;
char Operator;

Console.WriteLine("This program allows you to perform an operation on two


numbers");

try
{
Console.Write("Enter a number: ");
Operand1 = double.Parse(Console.ReadLine());
Console.Write("Enter an operator: ");
Operator = char.Parse(Console.ReadLine());
Console.Write("Enter a number: ");
Operand2 = double.Parse(Console.ReadLine());

if (Operator != '+' &&


Operator != '-' &&
Operator != '*' &&
Operator != '/')
throw new Exception(Operator.ToString());

if (Operator == '/') if (Operand2 == 0)


throw new DivideByZeroException("Division by zero is not
allowed");

switch (Operator)
{
case '+':
Result = Operand1 + Operand2;
break;

case '-':

C# 3.0 Practical Learning 480


Result = Operand1 - Operand2;
break;

case '*':
Result = Operand1 * Operand2;
break;

case '/':
Result = Operand1 / Operand2;
break;

default:
Console.WriteLine("Bad Operation");
break;
}
Console.WriteLine("\n{0} {1} {2} = {3}", Operand1, Operator,
Operand2, Result);
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("\nOperation Error: {0} is not a valid operator",
ex.Message);
}

return 0;
}
}

When running this program, if the user types a wrong operator, the compiler gets out of
the try block and looks for a catch that takes an Exception as argument. It finds the
second and executes it. If the user enters the right values (a number, an operator, and
another number), then the compiler finds out if the operator entered was a forward
slash “/” used to perform a division. If the user wants to perform a division, the compiler
finds out if the second operand, the denominator, is 0. If it is, we create a
DivideByZeroException instance and pass our own message to it. Based on this
exception, the compiler gets out of the try block and starts looking for a catch block
that takes a DivideByZeroException argument. It finds it in the first catch. Therefore,
the compiler executes it.

Practical Learning: Catching Various Exceptions

1. Change the PropertyListing.cs file as follows:


 
using System;

namespace RealEstate3
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,
C# 3.0 Practical Learning 481
Condominium
}

class PropertyListing
{
private Property prop;
private HouseType hse;
private Condominium cond;
private PropertyType tp;

public Property ListProperty


{
get { return prop; }
set { prop = value; }
}

public HouseType House


{
get { return hse; }
set { hse = value; }
}

public Condominium Condo


{
get { return cond; }
set { cond = value; }
}

public PropertyType Type


{
get { return tp; }
set { tp = value; }
}

public PropertyListing()
{
prop = new Property();
hse = new HouseType();
cond = new Condominium();
}

public void CreateListing()


{
char answer = 'n';
short propType = 1;
short condition = 1;

Console.WriteLine(" =//= Altair Realty =//=");


Console.WriteLine("-=- Property Creation -=-");
try
{
Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.WriteLine("4. Don't Know");
Console.Write("Enter Type of Property: ");
propType = short.Parse(Console.ReadLine());
}
catch (FormatException)
C# 3.0 Practical Learning 482
{
Console.WriteLine("The value you entered is not a valid
number");
}
catch (Exception)
{
Console.WriteLine("Something bad happened and we don't like
it");
}

Console.Write("\nEnter Property #: ");


ListProperty.PropertyNumber = Console.ReadLine();

try
{
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.Write("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
Console.Write("Enter Property Condition: ");
condition = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you typed for the property condition is not
good");
}
catch (Exception)
{
Console.WriteLine("Something unacceptable has just
happened");
}

if (condition == 1)
ListProperty.Condition = PropertyCondition.Excellent;
else if (condition == 2)
ListProperty.Condition = PropertyCondition.Good;
else if (condition == 3)
ListProperty.Condition = PropertyCondition.NeedsRepair;
else if (condition == 4)
ListProperty.Condition = PropertyCondition.BadShape;
else
ListProperty.Condition = PropertyCondition.Unknown;

switch ((PropertyType)propType)
{
case PropertyType.SingleFamily:
Type = PropertyType.SingleFamily;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());

if (House.Stories < 1)
{
House.Stories = 1;
throw new OverflowException("The number of levels must be
positive");
C# 3.0 Practical Learning 483
}
}
catch (OverflowException ex)
{
Console.WriteLine(ex.Message);
}
catch (FormatException)
{
Console.WriteLine("The number you entered for the stories is not
allowed");
}
catch (Exception)
{
Console.WriteLine("This is one of those abnormal behaviors");
}

try
{
Console.Write("Does it have an indoor car garage
(y/n): ");
answer = char.Parse(Console.ReadLine());

if ((answer == 'y') || (answer == 'Y'))


House.IndoorGarage = true;
else
House.IndoorGarage = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Indoor Car Garage
Answer");
}

try
{
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Basement Answer");
}
break;

case PropertyType.Townhouse:
Type = PropertyType.Townhouse;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());

if (House.Stories < 1)
{
House.Stories = 1;
throw new OverflowException("The number of levels must be
positive");
C# 3.0 Practical Learning 484
}
}
catch (OverflowException ex)
{
Console.WriteLine(ex.Message);
}
catch (FormatException)
{
Console.WriteLine("The number you entered for the stories is not
allowed");
}
catch (Exception)
{
Console.WriteLine("This is one of those abnormal
behaviors");
}

Console.Write("Does it have an indoor car garage


(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
break;

case PropertyType.Condominium:
Type = PropertyType.Condominium;
Console.Write("\nIs the building accessible to handicapped
(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
Condo.HandicapAccessible = true;
else
Condo.HandicapAccessible = false;
break;

default:
Type = PropertyType.Unknown;
break;
}

try
{
Console.Write("\nHow many bedrooms? ");
ListProperty.Bedrooms = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine(
"The value you entered for the number of bedrooms is not
acceptable");
}
catch (Exception)
C# 3.0 Practical Learning 485
{
Console.WriteLine("The program has decided to stop");
}

try
{
Console.Write("How many bathrooms? ");
ListProperty.Bathrooms = float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you decided to enter for the bedrooms is
rejected");
}
catch (Exception)
{
Console.WriteLine("The computer doesn't like what is
going on");
}

try
{
Console.Write("Year built: ");
ListProperty.YearBuilt = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You didn't enter a valid number for the year built");
}
catch (Exception)
{
Console.WriteLine("Whatever, whatever, whatever");
}

try
{
Console.Write("Property Value: ");
ListProperty.Value = decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine(
"The value of a property must be a good decimal number");
}
catch (Exception)
{
Console.WriteLine(
"This is where the application draws the line: it stops!");
}
}

public void ShowProperty()


{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
ListProperty.PropertyNumber);
Console.WriteLine("Property Type: {0}", Type);
C# 3.0 Practical Learning 486
switch (Type)
{
case PropertyType.SingleFamily:
case PropertyType.Townhouse:
Type = PropertyType.SingleFamily;
Console.WriteLine("Stories: {0}",
House.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
House.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
House.FinishedBasement);
break;

case PropertyType.Condominium:
Console.WriteLine("Handicapped Accessible Building:
{0}",
Condo.HandicapAccessible);
break;
}

Console.WriteLine("Condition: {0}",
ListProperty.Condition);
Console.WriteLine("Bedrooms: {0}",
ListProperty.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
ListProperty.Bathrooms);
Console.WriteLine("Year Built: {0}",
ListProperty.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
ListProperty.Value);
}
}
}

2. Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 1

Enter Property #: 228046

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 4

How many stories (levels)? -5


The number of levels must be positive
Does it have an indoor car garage (y/n): y
C# 3.0 Practical Learning 487
Is the basement finished(y/n): Not at all
Invalid Basement Answer

How many bedrooms? Apparently 3 or 4


The value you entered for the number of bedrooms is not acceptable
How many bathrooms? 1 can flush, the owner is working on another
The value you decided to enter for the bedrooms is rejected
Year built: Around 1962
You didn't enter a valid number for the year built
Property Value: A little over 420000
The value of a property must be an good decimal number

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 228046
Property Type: SingleFamily
Stories: 1
Has Indoor Car Garage: True
Finished Basement: False
Condition: BadShape
Bedrooms: 1
Bathrooms: 0.00
Year Built: 0
Market Value: $0.00

Press any key to continue . . .

3. Close the DOS window

Exception Nesting

The calculator simulator we have studied so far performs a division as one of its
assignments. We learned that, in order to perform any operation, the compiler must first
make sure that the user has entered a valid operator. Provided the operator is one of
those we are expecting, we also must make sure that the user typed valid numbers.
Even if these two criteria are met, it was possible that the user enter 0 for the
denominator. The block that is used to check for a non-zero denominator depends on
the exception that validates the operators. The exception that could result from a zero
denominator depends on the user first entering a valid number for the denominator.

You can create an exception inside of another. This is referred to as nesting an


exception. This is done by applying the same techniques we used to nest conditional
statements. This means that you can write an exception that depends on, or is subject
to, another exception. To nest an exception, write a try block in the body of the parent
exception. The nested try block must be followed by its own catch(es) clause. To
effectively handle the exception, make sure you include an appropriate throw in the try
block. Here is an example:
using System;

class Program
{
static int Main()
{

C# 3.0 Practical Learning 488


double Operand1, Operand2;
double Result = 0.00;
char Operator;

Console.WriteLine(
"This program allows you to perform an operation on two
numbers");

try
{
Console.Write("Enter a number: ");
Operand1 = double.Parse(Console.ReadLine());
Console.Write("Enter an operator: ");
Operator = char.Parse(Console.ReadLine());
Console.Write("Enter a number: ");
Operand2 = double.Parse(Console.ReadLine());

if (Operator != '+' &&


Operator != '-' &&
Operator != '*' &&
Operator != '/')
throw new Exception(Operator.ToString());

switch (Operator)
{
case '+':
Result = Operand1 + Operand2;
Console.WriteLine("\n{0} + {1} = {2}", Operand1,
Operand2, Result);
break;

case '-':
Result = Operand1 - Operand2;
Console.WriteLine("\n{0} - {1} = {2}", Operand1,
Operand2, Result);
break;

case '*':
Result = Operand1 * Operand2;
Console.WriteLine("\n{0} * {1} = {2}", Operand1,
Operand2, Result);
break;

case '/':
// The following exception is nested in the previous
try
try
{
if (Operand2 == 0)
throw new DivideByZeroException("Division by zero is
not allowed");

Result = Operand1 / Operand2;


Console.WriteLine("\n{0} / {1} = {2}", Operand1, Operand2,
Result);
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
C# 3.0 Practical Learning 489
break;
}
}
catch (Exception ex)
{
Console.WriteLine("\nOperation Error: {0} is not a valid operator",
ex.Message);
}

return 0;
}
}

Here is an example of running the program:


This program allows you to perform an operation on two numbers
Enter a number: 324.53
Enter an operator: /
Enter a number: 0
Division by zero is not allowed
Press any key to continue . . .

Exceptions and Methods

One of the most effective techniques used to deal with code is to isolate assignments.
We learned this when studying methods of classes. For example, the switch statement
that was performing the operations in the “normal” version of our program can be
written as follows:
using System;

class Program
{
static int Main()
{
double Number1, Number2;
double Result = 0.00;
char Operator;

Console.WriteLine(
"This program allows you to perform an operation on two
numbers");

try
{
Console.WriteLine("To proceed, enter");

Console.Write("First Number: ");


Number1 = double.Parse(Console.ReadLine());

Console.Write("An Operator (+, -, * or /): ");


Operator = char.Parse(Console.ReadLine());
if (Operator != '+' && Operator != '-' &&
Operator != '*' && Operator != '/')
throw new Exception(Operator.ToString());

Console.Write("Second Number: ");


Number2 = double.Parse(Console.ReadLine());

C# 3.0 Practical Learning 490


if (Operator == '/')
if (Number2 == 0)
throw new DivideByZeroException("Division by zero is
not allowed");

Result = Calculator(Number1, Number2, Operator);


Console.WriteLine("\n{0} {1} {2} = {3}", Number1, Operator,
Number2, Result);
}
catch (FormatException)
{
Console.WriteLine("The number you typed is not valid");
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(
"\nOperation Error: {0} is not a valid operator",
ex.Message);
}

return 0;
}

static double Calculator(double Value1, double Value2, char Symbol)


{
double Result = 0.00;

switch (Symbol)
{
case '+':
Result = Value1 + Value2;
break;

case '-':
Result = Value1 - Value2;
break;

case '*':
Result = Value1 * Value2;
break;

case '/':
Result = Value1 / Value2;
break;
}

return Result;
}
}

Here is one example of running the program:


This program allows you to perform an operation on two numbers
To proceed, enter
First Number: 248.84
C# 3.0 Practical Learning 491
An Operator (+, -, * or /): *
Second Number: 57.93

248.84 * 57.93 = 14415.3012


Press any key to continue . . .

Here is another example of running the program:


This program allows you to perform an operation on two numbers
To proceed, enter
First Number: 12.55
An Operator (+, -, * or /): [

Operation Error: [ is not a valid operator


Press any key to continue . . .

You can still use regular methods along with methods that handle exceptions. As done in
Main(), any method of a program can take care of its own exceptions that would occur
in its body. Here is an example of an exception handled in a method:
using System;

class Program
{
static int Main()
{
double Number1, Number2;
double Result = 0.00;
char Operator;

Console.WriteLine(
"This program allows you to perform an operation on two
numbers");

try
{
Console.WriteLine("To proceed, enter");

Console.Write("First Number: ");


Number1 = double.Parse(Console.ReadLine());

Console.Write("An Operator (+, -, * or /): ");


Operator = char.Parse(Console.ReadLine());
if (Operator != '+' && Operator != '-' &&
Operator != '*' && Operator != '/')
throw new Exception(Operator.ToString());

Console.Write("Second Number: ");


Number2 = double.Parse(Console.ReadLine());

Result = Calculator(Number1, Number2, Operator);


}
catch (FormatException)
{
Console.WriteLine("The number you typed is not valid");
}
catch (Exception ex)
{
Console.WriteLine(

C# 3.0 Practical Learning 492


"\nOperation Error: {0} is not a valid operator",
ex.Message);
}

return 0;
}

static double Calculator(double Value1, double Value2, char Symbol)


{
double Result = 0.00;

switch (Symbol)
{
case '+':
Result = Value1 + Value2;
Console.WriteLine("\n{0} + {1} = {2}", Value1, Value2,
Result);
break;

case '-':
Result = Value1 - Value2;
Console.WriteLine("\n{0} - {1} = {2}", Value1, Value2,
Result);
break;

case '*':
Result = Value1 * Value2;
Console.WriteLine("\n{0} * {1} = {2}", Value1, Value2,
Result);
break;

case '/':
// The following exception is nested in the previous try
try
{
if (Value2 == 0)
throw new DivideByZeroException("Division by zero is not
allowed");

Result = Value1 / Value2;


Console.WriteLine("\n{0} / {1} = {2}", Value1,
Value2, Result);
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
break;
}

return Result;
}
}

Isolating assignments and handing them to method is an important matter in the area of
application programming. Consider a program that handles a simple exception such as
this one:
using System;

C# 3.0 Practical Learning 493


class Program
{
static int Main()
{
double Number1, Number2;
double Result = 0.00;
char Operator = '/';

Console.WriteLine("This program allows you to perform a division of two


numbers");

try
{
Console.Write("Enter a number: ");
Number1 = double.Parse(Console.ReadLine());
Console.Write("Enter a number: ");
Number2 = double.Parse(Console.ReadLine());

if (Number2 == 0)
throw new DivideByZeroException("Division by zero is not
allowed");

Result = Number1 / Number2;


Console.WriteLine("\n{0} / {1} = {2}", Number1, Number2,
Result);
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}

return 0;
}
}

One of the ways you can use methods in exception routines is to have a central method
that receives variables, and sends them to other external methods. The external method
tests the value of a variable. If an exception occurs, the external method displays or
sends a throw. This throw can be picked up by the method that sent the error. Observe
the following example that implements this scenario:
using System;

class Program
{
static int Main()
{
double Number1, Number2;

Console.WriteLine("This program allows you to perform a division of two


numbers");

try
{
Console.Write("Enter a number: ");
Number1 = double.Parse(Console.ReadLine());
Console.Write("Enter a number: ");
Number2 = double.Parse(Console.ReadLine());

C# 3.0 Practical Learning 494


Division(Number1, Number2);
}
catch(DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}

return 0;
}

static void Division(double a, double b)


{
double Result;

// If an exception occurred,
if( b == 0 ) // then throw a string to the function caller
throw new DivideByZeroException("Division by zero is not
allowed");

Result = a / b;
Console.WriteLine("\n{0} / {1} = {2}", a, b, Result);
}
}

In this program, the Division method receives two values that it is asked to perform a
division with. The Division method analyzes the second argument that represents the
denominator. If this argument is zero, an exception is found and the Division method
throws a DivideByZeroException exception.

A method can also be called to perform more than one test to eventually throw more
than one exception. Such a method can (and should) be programmed to throw different
types of exceptions.

Custom Exceptions
 

Introduction

As seen in the previous lesson and in the above sections, exception handling is a great
part of the .NET Framework. As high as it is supported by various classes of the .NET, it
is possible that you want to further customize the handling of exceptions in your
application. One way you can do this is to create your own exception class.

Creating an Exceptional Class

The Exception class of the .NET Framework is a great tool for handling exceptions in a
C# application. To deal with particular errors, various classes are derived from
Exception. If for some reason the Exception class and none of the Exception-based
classes fulfills your requirement, you can derive a new class from Exception or from
one of the available Exception-based classes.

To derive a class from Exception or from one of its classes, simply follow the rules we
reviewed from class inheritance. Here is an example of a class based on Exception:

C# 3.0 Practical Learning 495


public class CustomException : Exception
{
}

There is no real rule to follow as to what class to derive from but it may be a good idea
to derive your class from one that already addresses your issue but not the way you
want. For example, if you want to create a class that would process numeric values but
you think the FormatException class is not doing what you want, you can derive your
class from FormatException.

After deriving the class, you can add the necessary members as you see fit. Remember
that the primary characteristic of an exception is to present a message to the user. In
Exception-based classes, this message is represented by the Message property.
Therefore, if you want to prepare a custom message for your class, you can override
or new this property. Here is an example:
public class IntegerException : Exception
{
public override string Message
{
get
{
return "The value you entered is not a valid integer";
}
}
}

Once you have created and customized your exceptional class, you can use it the same
way you would another exception class, such as throwing it. Here is an example
using System;

public class DigitException : Exception


{
private char c;

public DigitException(char x)
{
c = x;
}

public override string Message


{
get
{
return "The character you entered is not a valid digit";
}
}
}

class Program
{
static int Main()
{
try
{
char chNumber = '0';

C# 3.0 Practical Learning 496


Console.Write("Enter a digit (0 to 9): ");
chNumber = char.Parse(Console.ReadLine());

if ((chNumber != '0') &&


(chNumber != '1') &&
(chNumber != '2') &&
(chNumber != '3') &&
(chNumber != '4') &&
(chNumber != '5') &&
(chNumber != '6') &&
(chNumber != '7') &&
(chNumber != '8') &&
(chNumber != '9'))
throw new DigitException(chNumber);

Console.WriteLine("Number: {0}\n", chNumber);


}
catch (DigitException ex)
{
Console.WriteLine(ex.Message);
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

return 0;
}
}

Here is an example of running the program:


Enter a digit (0 to 9): 8
Number: 8

Press any key to continue . . .

Here is another example of running the program:


Enter a digit (0 to 9): w
The character you entered is not a valid digit
Press any key to continue . . .

C# 3.0 Practical Learning 497


Introduction to Arrays
 

A Series of Similar Items


 

Introduction

Imagine you want to create a program that would use a series of numbers. In algebra,
we represent such a series as follows: X 1, X2, X3, X4, X5. You can also represent a list of
names as follows:

Alex

Gaston

Hermine

Jerry

So far, to use a series of items, we were declaring a variable for each of them. If the list
was made of numbers, we would declare variables for such numbers as follows:

using System;

public class Exercise


{
static int Main()
{
var Number1 = 12.44;
var Number2 = 525.38;
var Number3 = 6.28;
var Number4 = 2448.32;
var Number5 = 632.04;

return 0;
}
}

Instead of using individual variables that share the same characteristics, you can group
them in an entity like a regular variable. This group is called an array. Therefore, an
array is a series of items of the same kind. It could be a group of numbers, a group of
cars, a group of words, etc but all items of the array must be of the same type.

C# 3.0 Practical Learning 498


Practical Learning: Introducing Arrays

 Start Microsoft Visual C# and create a Console Application named


VideoCollection1

Array Creation

Before creating an array, you must first decide the type its items will be made of. Is it a
group of numbers, a group of chairs, a group of buttons on a remote control? This
information allows the compiler to know how much space each item of the group will
require. This is because each item of the group will occupy its own memory space, just
like any of the variables we have used so far.

After deciding about the type of data of each item that makes up the series, you must
use a common name to identify them. The name is simply the same type of name you
would use for a variable as we have used so far. The name allows you and the compiler
to identify the area in memory where the items are located.

Thirdly, you must specify the number of items that will constitute the group. For the
compiler to be able to allocate an adequate amount of space for the items of the list,
once it knows how much space each item will require, it needs to know the number of
items so an appropriate and large enough amount of space can be reserved. The
number of items of an array is included in square brackets, as in [5].

An array is considered a reference type. Therefore, an array requests its memory using
the new operator. Based on this, one of the formulas to declare an array is:
DataType[] VariableName = new DataType[Number];

Alternatively, you can use the var keyword to create an array. The formula to use would
be:
var VariableName = new DataType[Number];

In these formulas, the DataType factor can be one of the types we have used so far
(char, int, float, double, decimal, string, etc). It can also be the name of a class
as we will learn in Lesson 23. Like a normal variable, an array must have a name,
represented in our formula as VariableName. The square brackets on the left of the
assignment operator are used to let the compiler know that you are declaring an array
instead of a regular variable. The new operator allows the compiler to reserve memory.
The Number factor is used to specify the number of items of the list.

Based on the above formula, here is an example of an array variable:


using System;

public class Exercise


{
static void Main()
{
double numbers = new double[5];
}
}

Using the var keyword, this array can also be declared as follows:
C# 3.0 Practical Learning 499
using System;

public class Exercise


{
static void Main()
{
var Numbers = new double[5];
}
}

Practical Learning: Creating an Array

1. To create arrays, change the Programs.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VideoCollection1
{
public class Program
{
static void Main(string[] args)
{
long[] ShelfNumbers = new long[10];
string[] Titles = new string[10];
string[] Directors = new string[10];
int[] Lengths = new int[10];
string[] Ratings = new string[10];
double[] Prices = new double[10];
}
}
}

2. Save the file

Introduction to Initializing an Array

When creating an array, you can specify the number of items that make up its list. Each
item of the series is referred to as a member or an element of the array. Once the array
has been created, each one of its members is initialized with a 0 value. Most, if not all,
of the time, you will need to change the value of each member to a value of your
choice. This is referred to as initializing the array.

An array is primarily a variable; it is simply meant to carry more than one value. Like
every other variable, an array can be initialized. There are two main techniques you can
use to initialize an array. If you have declared an array as done above, to initialize it,
you can access each one of its members and assign it a desired but appropriate value.

In algebra, if you create a series of values as X 1, X2, X3, X4, and X5, each member of this
series can be identified by its subscript number. In this case the subscripts are 1, 2, 3, 4,
and 5. This subscript number is also called an index. In the case of an array also, each
member can be referred to by an incremental number called an index. A C# (like a C/C+

C# 3.0 Practical Learning 500


+) array is zero-based. This means that the first member of the array has an index of 0,
the second has an index of 1, and so on. In algebra, the series would be represented as
X0, X1, X2, X3, and X4.

In C#, the index of a member of an array is written in its own square brackets. This is
the notation you would use to locate each member. One of the actions you can take
would consist of assigning it a value. Here is an example:
using System;

public class Exercise


{
static void Main()
{
var Numbers = new double[5];

Numbers[0] = 12.44;
Numbers[1] = 525.38;
Numbers[2] = 6.28;
Numbers[3] = 2448.32;
Numbers[4] = 632.04;
}
}

Besides this technique, you can also initialize the array as a whole when declaring it. To
do this, on the right side of the declaration, before the closing semi-colon, type the
values of the array members between curly brackets and separated by a comma. Here is
an example:
using System;

public class Exercise


{
static void Main()
{
var Numbers = new double[5] { 12.44, 525.38, 6.28, 2448.32,
632.04 };
}
}

If you use this second technique, you don't have to specify the number of items in the
series. In this case, you can leave all square brackets empty:
using System;

public class Exercise


{
static void Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};
}
}

If you leave the square brackets empty, the compiler will figure out the number of
items.

Practical Learning: Initializing Some Arrays

C# 3.0 Practical Learning 501


1. To initialize the arrays, change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VideoCollection1
{
class Program
{
static void Main(string[] args)
{
long[] ShelfNumbers = new long[]
{
2985, 8024, 5170, 1304, 9187,
1193, 3082, 8632, 4633, 9623
};
string[] Titles = new string[]
{
"The Distinguished Gentleman",
"A Perfect Murder", "Chalte Chalte",
"Ransom", "Not Another Teen Movie",
"Madhubaala", "Get Shorty",
"Sneakers", "Born Invincible", "Hush"
};
string[] Directors = new string[]
{
"Jonathan Lynn", "Andrew Davis", "Aziz Mirza",
"Ron Howard", "Joel Gallen", "Shivram Yadav",
"Barry Sonnenfeld", "Paul Alden Robinson",
"Unknown", "Jonathan Darby"
};
int[] Lengths = new int[]
{
112, 108, 145, 121, 100, 0, 105, 126, 90, 96
};
string[] Ratings = new string[]
{
"R", "R", "N/R", "R", "Unrated",
"N/R", "R", "PG-13", "N/R", "PG-13"
};
double[] Prices = new double[]
{
14.95D, 19.95D, 22.45D, 14.95D, 9.95D,
17.50D, 9.95D, 9.95D, 5.95D, 8.75D
};
}
}
}

2. Save the file

Other Techniques of Initializing an Array

C# 3.0 Practical Learning 502


We have initialized our arrays so far with values we specified directly in the curly
brackets. If you have declared and initialized some variables of the same type, you can
use them to initialize an array. Here is an example:
using System;

public class Exercise


{
static void Main()
{
var Area = 97394.2204D;
var Distance = 982.84D;
var Level = 27D;
var Quantity = 237957.704D;

var Measures = new double[] { Area, Distance, Level, Quantity };


}
}

The values can also come from constant variables. Here is an example:
using System;

public class Exercise


{
static void Main()
{
const double PI = 3.141592653;
var SqureRootOf2 = 1.414D;
var e = 2.718D;
const double RadiusOfEarth = 6370; // km
var ln2 = 0.6931;

var Measures = new double[] { PI, SqureRootOf2, e, RadiusOfEarth,


ln2 };
}
}

The values can also come from calculations, whether the calculation is from an initialized
variable or made locally in the curly brackets. Here is an example:
using System;

public class Exercise


{
static void Main()
{
const double DensityOfWater = 1000; // kg/m3 ;
var MassOfEarth = 5.98 * 10e24; // kg
var EarthMoonDistance = 2.39 * 10e5; // miles

var Measures = new double[]


{
DensityOfWater, 9.30 * 10.7, MassOfEarth, EarthMoonDistance
};
}
}

The rule to follow is that, at the time the array is created, the compiler must be able to
know exactly the value of each member of the array, no guessing.
C# 3.0 Practical Learning 503
All of the arrays we have declared so far were using only numbers. The numbers we
used were decimal constants. If the array is made of integers, you can use decimal,
hexadecimal values, or a combination of both. Here is an example:
using System;

public class Exercise


{
static void Main()
{
var Red = 0xFF0000;
var SomeColor = 0x800000;

var Colors = new int[] { 2510, Red, 818203, SomeColor, 0xF28AC };


}
}

An array can have types of values of any of the data types we have used so far. The
rule to follow is that all members of the array must be of the same type. For example,
you can declare an array of Boolean values, as long as all values can be evaluated to
true or false. Here is an example:
using System;

public class Exercise


{
static void Main()
{
var FullTimeStudents = new bool[] { true, true, true, false,
true, false };
}
}

As stated already, each values of a Boolean array must be evaluated to true or false.
This means that you can use variables or expressions as members of the array. Here is
an example:
using System;

public class Exercise


{
static void Main()
{
var House1Value = 460885.85D;
var House2Value = 685770.00D;

var Conparisons = new bool[] { 25 < 10, House1Value ==


House2Value, true };
}
}

As we will see when studying arrays and classes, you can use this technique to create
an array of dates, times, or date and time values. Here is an example:
using System;

public class Exercise


{
static void Main()

C# 3.0 Practical Learning 504


{
var DateHired = new DateTime(1998, 10, 08);
var IndependenceDay = new DateTime(1960, 1, 1);

var Dates = new DateTime[] { DateHired, IndependenceDay };


}
}

Accessing the Members of an Array


 

Introduction

After initializing an array, which means after each of its members has been given a
value, you can access a member of the array to get, manipulate or even change its
value. To access a member of the array, you use the square brackets as we saw above.
As done for normal variables, one of the reasons of accessing a member of an array
would be to display its value on the console screen, which can be done by passing it to a
Console.Write() or a Console.WriteLine() method. Here is an example:

using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};

Console.Write(Numbers[3]);

return 0;
}
}

In the same way, you can use the curly brackets notation to display the value of a
member:
using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};

Console.Write("Number: {0} ", Numbers[3]);

return 0;
}
}

In the same way, you can access 1, a few or all members of the array.

Practical Learning: Using the Members of an Array

C# 3.0 Practical Learning 505


1. To show the values of a member of an array, change the Program.cs file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VideoCollection1
{
class Program
{
static void Main(string[] args)
{
long[] ShelfNumbers = new long[]
{
2985, 8024, 5170, 1304, 9187, 1193, 3082, 8632
};

. . . No Change

double[] Prices = new double[]


{
14.95D, 19.95D, 22.45D, 14.95D, 9.95D,
17.50D, 9.95D, 9.95D, 5.95D, 8.75D
};

Console.WriteLine("===============================");
Console.WriteLine("Video Information");
Console.WriteLine("-------------------------------");
Console.WriteLine("Shelf #: {0}", ShelfNumbers[1]);
Console.WriteLine("Title: {0}", Titles[1]);
Console.WriteLine("Director: {0}", Directors[1]);
Console.WriteLine("Length: {0} minutes", Lengths[1]);
Console.WriteLine("Rating: {0}", Ratings[1]);
Console.WriteLine("Price: {0}", Prices[1]);
Console.WriteLine("===============================");
}
}
}

2. Execute the application and test it. Here is an example:


 
===============================
Video Information
-------------------------------
Shelf #: 8024
Title: A Perfect Murder
Director: Andrew Davis
Length: 108 minutes
Rating: R
Price: 19.95
===============================
Press any key to continue . . .

3. Close the DOS window

For an Indexed Member of the Array

C# 3.0 Practical Learning 506


We saw how you can use the square brackets to access each member of the array one
at a time. That technique allows you to access one, a few, or each member. If you plan
to access all members of the array instead of just one or a few, you can use the for
loop. The formula to follow is:
for(DataType Initializer; EndOfRange; Increment) Do What You Want;

In this formula, the for keyword, the parentheses, and the semi-colons are required.
The DataType factor is used to specify how you will count the members of the array.

The Initializer specifies how you would indicate the starting of the count. As seen in
Lesson 12, this initialization could use an initialized int-based variable.

The EndOfRange specifies how you would stop counting. If you are using an array, it
should combine a conditional operation (<, <=, >, >=, or !=) with the number of
members of the array minus 1.

The Increment factor specifies how you would move from one index to the next.

Here is an example:
using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};

for (var i = 0; i < 5; i++)


Console.WriteLine(Numbers[i]);

return 0;
}
}

This would produce:


12.44
525.38
6.28
2448.32
632.04
Press any key to continue . . .

When using a for loop, you should pay attention to the number of items you use. If you
use a number n less than the total number of members - 1, only the first n members of
the array would be accessed. Here is an example:
using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};

C# 3.0 Practical Learning 507


for (var i = 0; i < 3; i++)
Console.WriteLine("Number: {0}", Numbers[i]);

return 0;
}
}

This would produce:


Number: 12.44
Number: 525.38
Number: 6.28
Press any key to continue . . .

On the other hand, if you use a number of items higher than the number of members
minus one, the compiler would throw an IndexOutOfRangeException exception. Here
is an example:
using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};

for (var i = 0; i < 12; i++)


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

return 0;
}
}

This would produce:

C# 3.0 Practical Learning 508


After the nasty dialog box, you would get:

Therefore, when the number of items is higher than the number of members - 1, the
compiler may process all members. Then, when it is asked to process members beyond
the allowed range, it finds out that there is no other array member. So it gets upset.

You could solve the above problem by using exception handling to handle an
IndexOutOfRangeException exception. Here is an example:

using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};

try
{
for (var i = 0; i < 12; i++)
Console.WriteLine("Number: {0}", Numbers[i]);
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("You tried to access values beyond " +
"the allowed range of the members of the
array.");
}
return 0;
}
}

This would produce:


Number: 12.44
Number: 525.38
Number: 6.28
Number: 2448.32
C# 3.0 Practical Learning 509
Number: 632.04
You tried to access values beyond the allowed range of the members of the
array.

Press any key to continue . . .

This solution should not be encouraged. Fortunately, C# and the .NET Framework
provide better solutions.

Practical Learning: Using a for Loop

1. To use a for loop, change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VideoCollection1
{
class Program
{
static void Main(string[] args)
{
. . . No Change

Console.WriteLine("===============================");
Console.WriteLine("Videos Information");
for (int i = 0; i < 10; i++)
{
Console.WriteLine("===============================");
Console.WriteLine("Video {0}", i + 1);
Console.WriteLine("-------------------------------");
Console.WriteLine("Shelf #: {0}", ShelfNumbers[i]);
Console.WriteLine("Title: {0}", Titles[i]);
Console.WriteLine("Director: {0}", Directors[i]);
Console.WriteLine("Length: {0} minutes", Lengths[i]);
Console.WriteLine("Rating: {0}", Ratings[i]);
Console.WriteLine("Price: {0}", Prices[i]);
}
Console.WriteLine("===============================");
}
}
}

2. Execute the application to see the result:


 
===============================
Videos Information
===============================
Video 1
-------------------------------
Shelf #: 2985
Title: The Distinguished Gentleman
Director: Jonathan Lynn
Length: 112 minutes

C# 3.0 Practical Learning 510


Rating: R
Price: 14.95
===============================
Video 2
-------------------------------
Shelf #: 8024
Title: A Perfect Murder
Director: Andrew Davis
Length: 108 minutes
Rating: R
Price: 19.95
===============================
Video 3
-------------------------------
Shelf #: 5170
Title: Chalte Chalte
Director: Aziz Mirza
Length: 145 minutes
Rating: N/R
Price: 22.45
===============================
Video 4
-------------------------------
Shelf #: 1304
Title: Ransom
Director: Ron Howard
Length: 121 minutes
Rating: R
Price: 14.95
===============================
Video 5
-------------------------------
Shelf #: 9187
Title: Not Another Teen Movie
Director: Joel Gallen
Length: 100 minutes
Rating: Unrated
Price: 9.95
===============================
Video 6
-------------------------------
Shelf #: 1193
Title: Madhubaala
Director: Shivram Yadav
Length: 0 minutes
Rating: N/R
Price: 17.5
===============================
Video 7
-------------------------------
Shelf #: 3082
Title: Get Shorty
Director: Barry Sonnenfeld
Length: 105 minutes
Rating: R
Price: 9.95
===============================
Video 8
-------------------------------
Shelf #: 8632
C# 3.0 Practical Learning 511
Title: Sneakers
Director: Paul Alden Robinson
Length: 126 minutes
Rating: PG-13
Price: 9.95
===============================
Video 9
-------------------------------
Shelf #: 4633
Title: Born Invincible
Director: Unknown
Length: 90 minutes
Rating: N/R
Price: 5.95
===============================
Video 10
-------------------------------
Shelf #: 9623
Title: Hush
Director: Jonathan Darby
Length: 96 minutes
Rating: PG-13
Price: 8.75
===============================
Press any key to continue . . .

For Each Member in the Array

In a for loop, you should know the number of members of the array. If you don't, the
C# language allows you to let the compiler use its internal mechanism to get this count
and use it to know where to stop counting. To assist you with this, C# provides the
foreach operator. To use it, the formula to follow is:

foreach (type identifier in expression) statement

The foreach and the in keywords are required.

The first factor of this syntax, type, can be var or the type of the members of the array.
It can also be the name of a class as we will learn in Lesson 23.

The identifier factor is a name of the variable you will use.

The expression factor is the name of the array variable.

The statement is what you intend to do with the identifier or as a result of accessing the
member of the array.

Like a for loop that accesses all members of the array, the foreach operator is used to
access each array member, one at a time. Here is an example:
using System;

public class Exercise


{
static int Main()
{
var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04
};
C# 3.0 Practical Learning 512
foreach(var n in Numbers)
Console.WriteLine("Number: {0} ", n);

return 0;
}
}

This would produce:


Employees Records
Employee Name: Joan Fuller
Employee Name: Barbara Boxen
Employee Name: Paul Kumar
Employee Name: Bertrand Entire

Anonymous Arrays
 

Introduction

In previous sections, when creating an array, we were specifying its type. As seen in our
introduction to variables, a good feature of the var keyword is that, when using it to
declare and initialize a variable, you ask the compiler to figure out what type of data the
variable is holding. This concept is also valid for an array.

An anonymous array is an array variable whose type is left to the compiler to determine,
based on the types of values of the array.

Creating an Anonymous Array

As done for variables so far, when creating an array, you can use the var keyword,
initialize the array, but not specify its data type. The formula to use is:
var ArrayName = new[] { Initialization };

The formula is almost similar to that of a normal array, with keywords and operators you
are already familiar with. The ArrayName factor is the name of the variable. Notice that
the new keyword is directly followed by the square brackets. In the curly brackets, you
must initialize the array by providing the necessary values. For the compiler to be able to
figure out the type and amount of memory to allocate for the array variable, all values
must be of the same type or the same category:

 If each value is a number without a decimal part, the compiler checks their range
and concludes whether the array needs 32 bits or 64 bits. Here is an example:
 
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Naturals = new[] { 2735, 20, 3647597, 3408, 957 };

C# 3.0 Practical Learning 513


var Values = new[] { 0x91FF22, 8168, 0x80080, 0xF822FF, 202684 };

return 0;
}
}

 If the values are numeric but at least one of them includes a decimal part, the
compiler concludes that the array is made of floating-point numbers. If you want to
control their precision (float, double, or decimal), add the appropriate suffix to
each value. This also means that you can use a combination of natural and decimal
numbers, but the presence of at least one number with a decimal part would
convert the array into floating point instead of int-based. Here is an example:
 
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Singles = new[] { 1244F, 525.38F, 6.28F, 2448.32F, 632.04F };
var Doubles = new[] { 3.212D, 3047.098D, 732074.02, 18342.3579 };
var Values = new[] { 17.230M, 4808237M, 222.4203M, 948.002009M };

return 0;
}
}

 If the members are made of true and false values, then compiler will allocate
memory for Boolean values for the array. Here is an example:
 
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Qualifications = new[] { true, true, false, true, false };

return 0;
}
}

 If the members contain values included in single-quotes, the array will be treated
as a series of characters. Here is an example:
 
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Categories = new[] { 'C', 'F', 'B', 'C', 'A' };

C# 3.0 Practical Learning 514


return 0;
}
}

 If the values of the members are included in double-quotes, then the array will be
considered a group of strings. Here is an example:
 
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Friends = new[] { "Mark", "Frank", "Charlotte", "Jerry" };

return 0;
}
}

Accessing the Members of an Anonymous Array

After creating an anonymous array, you can access each member using its index. Here is
an example that uses a for loop:
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Friends = new[] { "Mark", "Frank", "Charlotte", "Jerry" };

for (var i = 0; i < 4; i++)


Console.WriteLine("Friend: {0}", Friends[i]);

return 0;
}
}

This would produce:


Friend: Mark
Friend: Frank
Friend: Charlotte
Friend: Jerry
Press any key to continue . . .

In the same way, you can use a foreach statement to access each member of the
array. Here is an example:
using System;
using System.Linq;

public class Exercise


C# 3.0 Practical Learning 515
{
static int Main()
{
var Friendlies = new[] { "Mark", "Frank", "Charlotte", "Jerry" };

for (var i = 0; i < 4; i++)


Console.WriteLine("Friend: {0}", Friendlies[i]);
Console.WriteLine("-----------------------------------");

var Qualifications = new[] { true, true, false, true, false };

foreach (var qualifies in Qualifications)


Console.WriteLine("The Member Qualifies: {0}", qualifies);
Console.WriteLine("-----------------------------------");

return 0;
}
}

This would produce:


Friend: Mark
Friend: Frank
Friend: Charlotte
Friend: Jerry
-----------------------------------
The Member Qualifies: True
The Member Qualifies: True
The Member Qualifies: False
The Member Qualifies: True
The Member Qualifies: False
-----------------------------------
Press any key to continue . . .

Selecting a Value From an Array


 

Introduction

Because an array is a list of items, it could include values that are not useful in all
scenarios. For example, having an array made of too many values, at one time you may
want to isolate only the first n members of the array, or the last m members of the
array, or a range of members from an index i to an index j. Another operation you may
be interested to perform is to find out if this or that value exists in the array. One more
interesting operation would be to find out what members or how many members of the
array respond to this or that criterion. All these operations are useful and possible with
different techniques.

Using for and foreach

Consider the following program:


using System;
using System.Linq;

public class Exercise


C# 3.0 Practical Learning 516
{
static int Main()
{
var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632,
104 };

for (var i = 0; i < 10; i++)


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

return 0;
}
}

This would produce:


Number: 102
Number: 44
Number: 525
Number: 38
Number: 6
Number: 28
Number: 24481
Number: 327
Number: 632
Number: 104
Press any key to continue . . .

Imagine you want to access only the first n members of the array. To do this, you can
use an if conditional statement nested in a for or a foreach loop. Here is an example
that produces the first 4 values of the array:
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632,
104 };

for (var i = 0; i < 10; i++)


if (i < 4)
Console.WriteLine("Number: {0}", Numbers[i]);

return 0;
}
}

This would produce:


Number: 102
Number: 44
Number: 525
Number: 38
Press any key to continue . . .

You can use the same technique to get the last m members of the array. You can also
use a similar technique to get one or a few values inside of the array, based on a

C# 3.0 Practical Learning 517


condition of your choice. Here is an example that gets the values that are multiple of 5
from the array:
using System;
using System.Linq;

public class Exercise


{
static int Main()
{
var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632,
104 };

for (var i = 0; i < 10; i++)


if (Numbers[i] % 5 == 0)
Console.WriteLine("Number: {0}", Numbers[i]);

return 0;
}
}

This would produce:


Number: 525
Press any key to continue . . .

Practical Learning: Checking a Value From an Array

1. To check a value from an array, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VideoCollection1
{
class Program
{
static void Main(string[] args)
{
long[] ShelfNumbers = new long[]
{
2985, 8024, 5170, 1304, 9187,
1193, 3082, 8632, 4633, 9623
};
string[] Titles = new string[]
{
"The Distinguished Gentleman",
"A Perfect Murder", "Chalte Chalte",
"Ransom", "Not Another Teen Movie",
"Madhubaala", "Get Shorty",
"Sneakers", "Born Invincible", "Hush"
};
string[] Directors = new string[]
{
"Jonathan Lynn", "Andrew Davis", "Aziz Mirza",
"Ron Howard", "Joel Gallen", "Shivram Yadav",
C# 3.0 Practical Learning 518
"Barry Sonnenfeld", "Paul Alden Robinson",
"Unknown", "Jonathan Darby"
};
int[] Lengths = new int[]
{
112, 108, 145, 121, 100, 0, 105, 126, 90, 96
};
string[] Ratings = new string[]
{
"R", "R", "N/R", "R", "Unrated",
"N/R", "R", "PG-13", "N/R", "PG-13"
};
double[] Prices = new double[]
{
14.95D, 19.95D, 22.45D, 14.95D, 9.95D,
17.50D, 9.95D, 9.95D, 5.95D, 8.75D
};

foreach (int Code in ShelfNumbers)


Console.Write("{0}\t", Code);

long ShelfNumber = 0;

Console.Write("Enter the shelf number of the " +


"video you want to check: ");
ShelfNumber = long.Parse(Console.ReadLine());
Console.WriteLine();

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


{
if (ShelfNumbers[i] == ShelfNumber)
{
Console.WriteLine("===============================");
Console.WriteLine("Video Information");
Console.WriteLine("-------------------------------");
Console.WriteLine("Shelf #: {0}", ShelfNumbers[i]);
Console.WriteLine("Title: {0}", Titles[i]);
Console.WriteLine("Director: {0}", Directors[i]);
Console.WriteLine("Length: {0} minutes",
Lengths[i]);
Console.WriteLine("Rating: {0}", Ratings[i]);
Console.WriteLine("Price: {0}", Prices[i]);
}
}
Console.WriteLine("===============================");
}
}
}

2. Execute the application to test it

3. When prompted, enter a shelf number and press Enter. Here is an example:
 
2985 8024 5170 1304 9187 1193 3082 8632 4633
9623
Enter the shelf number of the video you want to check: 8632

===============================
Video Information
C# 3.0 Practical Learning 519
-------------------------------
Shelf #: 8632
Title: Sneakers
Director: Paul Alden Robinson
Length: 126 minutes
Rating: PG-13
Price: 9.95
===============================
Press any key to continue . . .

4. Close the DOS window and return to your programming environment

C# 3.0 Practical Learning 520


Arrays and Classes
 

An Array of a Primitive Type as a Field


 

Introduction

As we have used them so far, an array is primarily a variable. As such, it can be declared
as a member variable of a class. To create a field as an array, you can declare it like a
normal array in the body of the class. Here is an example:
public class CoordinateSystem
{
private int[] Points;
}

Like any field, when an array has been declared as a member variable, it is made
available to all the other members of the same class. You can use this feature to
initialize the array in one method and let other methods use the initialized variable. This
also means that you don't have to pass the array as argument nor do you have to
explicitly return it from a method.

After or when declaring an array, you must make sure you allocate memory for it prior
to using. Unlike C++, you can allocate memory for an array when declaring it. Here is
an example:
public class CoordinateSystem
{
private int[] Points = new int[4];
}

You can also allocate memory for an array field in a constructor of the class. Here is an
example:
public class CoordinateSystem
{
private int[] Points;

public CoordinateSystem()
{
Points = new int[4];
}
}

If you plan to use the array as soon as the program is running, you can initialize it using
a constructor or a method that you know would be called before the array can be used.
Here is an example:
public class CoordinateSystem
C# 3.0 Practical Learning 521
{
private int[] Points;

public CoordinateSystem()
{
Points = new int[4];

Points[0] = 2;
Points[1] = 5;
Points[2] = 2;
Points[3] = 8;
}
}

Practical Learning: Introducing Arrays and Classes

1. Start Microsoft Visual C# and create a Console Application named


RentalProperties1

2. To create a new class, in the Solution Explorer, right-click RenatlProperties1 -> Add
-> Class...

3. Set the Name to RentalProperty and press Enter

4. Change the file as follows:


 

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RentalProperties1
{
public enum PropertyType { SingleFamily, Townhouse,
Apartment, Unknown };

public class RentalProperty


{
private long[] PropertyNumbers;
private PropertyType[] Types;
private short[] Bedrooms;
private float[] Bathrooms;
private double[] MonthlyRent;

public RentalProperty()
{
PropertyNumbers = new long[] {
192873, 498730, 218502, 612739,
457834, 927439, 570520, 734059 };

Types = new PropertyType[] {


PropertyType.SingleFamily, PropertyType.SingleFamily,
PropertyType.Apartment, PropertyType.Apartment,
PropertyType.Townhouse, PropertyType.Apartment,
PropertyType.Apartment, PropertyType.Townhouse };

C# 3.0 Practical Learning 522


Bedrooms = new short[] { 5, 4, 2, 1, 3, 1, 3, 4 };

Bathrooms = new float[] { 3.50F, 2.50F, 1.00F, 1.00F,


2.50F, 1.00F, 2.00F, 1.50F };

MonthlyRent = new double[] {


2250.00D, 1885.00D, 1175.50D, 945.00D,
1750.50D, 1100.00D, 1245.95D, 1950.25D };
}
}
}

5. Save all and accept the suggested name of the project

Presenting the Array

After an array has been created as a field, it can be used by any other member of the
same class. Based on this, you can use a member of the same class to request values
that would initialize it. You can also use another method to explore the array. Here is an
example:
using System;

public class CoordinateSystem


{
private int[] Points;

public CoordinateSystem()
{
Points = new int[4];

Points[0] = 2;
Points[1] = -5;
Points[2] = 2;
Points[3] = 8;
}

public void ShowPoints()


{
Console.WriteLine("Points Coordinates");
Console.WriteLine("P({0}, {1})", Points[0], Points[1]);
Console.WriteLine("Q({0}, {1})", Points[2], Points[3]);
}
}

public class Exercise


{
static int Main()
{
var Coordinates = new CoordinateSystem();

Coordinates.ShowPoints();
return 0;
}
}

This would produce:


Points Coordinates
C# 3.0 Practical Learning 523
P(2, -5)
Q(2, 8)
Press any key to continue . . .

Practical Learning: Presenting an Array

1. To show the values of the array, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RentalProperties1
{
public enum PropertyType { SingleFamily, Townhouse,
Apartment, Unknown };

public class RentalProperty


{
private long[] PropertyNumbers;
private PropertyType[] Types;
private short[] Bedrooms;
private float[] Bathrooms;
private double[] MonthlyRent;

public RentalProperty()
{
PropertyNumbers = new long[] {
192873, 498730, 218502, 612739,
457834, 927439, 570520, 734059 };

Types = new PropertyType[] {


PropertyType.SingleFamily, PropertyType.SingleFamily,
PropertyType.Apartment, PropertyType.Apartment,
PropertyType.Townhouse, PropertyType.Apartment,
PropertyType.Apartment, PropertyType.Townhouse };

Bedrooms = new short[] { 5, 4, 2, 1, 3, 1, 3, 4 };

Bathrooms = new float[] { 3.50F, 2.50F, 1.00F, 1.00F,


2.50F, 1.00F, 2.00F, 1.50F };

MonthlyRent = new double[] {


2250.00D, 1885.00D, 1175.50D, 945.00D,
1750.50D, 1100.00D, 1245.95D, 1950.25D };
}

public void ShowListing()


{
Console.WriteLine("Properties Listing");

Console.WriteLine("=============================================");
Console.WriteLine("Prop # Property Type Beds Baths Monthly
Rent");

Console.WriteLine("---------------------------------------------");
for (int i = 0; i < 8; i++)
C# 3.0 Practical Learning 524
{
Console.WriteLine("{0}\t{1}\t{2} {3:F}{4,12}",
PropertyNumbers[i], Types[i], Bedrooms[i],
Bathrooms[i], MonthlyRent[i]);
}

Console.WriteLine("=============================================");
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RentalProperties1
{
class Program
{
static void Main(string[] args)
{
RentalProperty Property = new RentalProperty();

Property.ShowListing();
}
}
}

3. Execute the application to see the result


 
Properties Listing
=============================================
Prop # Property Type Beds Baths Monthly Rent
---------------------------------------------
192873 SingleFamily 5 3.50 2250
498730 SingleFamily 4 2.50 1885
218502 Apartment 2 1.00 1175.5
612739 Apartment 1 1.00 945
457834 Townhouse 3 2.50 1750.5
927439 Apartment 1 1.00 1100
570520 Apartment 3 2.00 1245.95
734059 Townhouse 4 1.50 1950.25
=============================================
Press any key to continue . . .

4. Close the DOS window and return to your programming environment

Arrays and Methods


 

Introduction

C# 3.0 Practical Learning 525


Each member of an array holds a legitimate value. Therefore, you can pass a single
member of an array as argument. You can pass the name of the array variable with the
accompanying index to a method.

The main purpose of using an array is to use various values grouped under one name.
Still, an array is primarily a variable. As such, it can be passed to a method and it can be
returned from a method.

An Array Passed as Argument

Like a regular variable, an array can be passed as argument. To do this, in the


parentheses of a method, provide the data type, the empty square brackets, and the
name of the argument. Here is an example:
public class CoordinateSystem
{
public void ShowPoints(int[] Points)
{
}
}

When an array has been passed to a method, it can be used in the body of the method
as any array can be, following the rules of array variables. For example, you can display
its values. The simplest way you can use an array is to display the values of its
members. This could be done as follows:
public class CoordinateSystem
{
public void ShowPoints(int[] Points)
{
Console.WriteLine("Points Coordinates");
Console.WriteLine("P({0}, {1})", Points[0], Points[1]);
Console.WriteLine("Q({0}, {1})", Points[2], Points[3]);
}
}

To call a method that takes an array as argument, simply type the name of the array in
the parentheses of the called method. Here is an example:
using System;

public class CoordinateSystem


{
public void ShowPoints(int[] Points)
{
Console.WriteLine("Points Coordinates");
Console.WriteLine("P({0}, {1})", Points[0], Points[1]);
Console.WriteLine("Q({0}, {1})", Points[2], Points[3]);
}
}

public class Exercise


{
static int Main()
{
var Points = new int[] { -3, 3, 6, 3 };
var Coordinates = new CoordinateSystem();

C# 3.0 Practical Learning 526


Coordinates.ShowPoints(Points);
return 0;
}
}

This would produce:


Points Coordinates
P(-3, 3)
Q(6, 3)
Press any key to continue . . .

When an array is passed as argument to a method, the array is passed by reference.


This means that, if the method makes any change to the array, the change would be
kept when the method exits. You can use this characteristic to initialize an array from a
method. Here is an example:
using System;

public class CoordinateSystem


{
public void Initialize(int[] Coords)
{
Coords[0] = -4;
Coords[1] = -2;
Coords[2] = -6;
Coords[3] = 3;
}

public void ShowPoints(int[] Points)


{
Console.WriteLine("Points Coordinates");
Console.WriteLine("P({0}, {1})", Points[0], Points[1]);
Console.WriteLine("Q({0}, {1})", Points[2], Points[3]);
}
}

public class Exercise


{
static int Main()
{
var System = new int[4];
var Coordinates = new CoordinateSystem();

Coordinates.Initialize(System);
Coordinates.ShowPoints(System);

return 0;
}
}

This would produce:


Points Coordinates
P(-4, -2)
Q(-6, 3)
Press any key to continue . . .

C# 3.0 Practical Learning 527


Notice that the CreateNumbers() method receives an un-initialized array but returns it
with new values. To enforce the concept of passing a variable by reference, you can also
accompany an array argument with the ref keyword, both when defining the method
and when calling it. Here is an example:
using System;

public class CoordinateSystem


{
public void Initialize(ref int[] Coords)
{
Coords[0] = -4;
Coords[1] = -2;
Coords[2] = -6;
Coords[3] = 3;
}

public void ShowPoints(int[] Points)


{
Console.WriteLine("Points Coordinates");
Console.WriteLine("P({0}, {1})", Points[0], Points[1]);
Console.WriteLine("Q({0}, {1})", Points[2], Points[3]);
}
}

public class Exercise


{
static int Main()
{
var System = new int[4];
var Coordinates = new CoordinateSystem();

Coordinates.Initialize(ref System);
Coordinates.ShowPoints(System);

return 0;
}
}

Instead of just one, you can create a method that receive more than one array and you
can create a method that receives a combination of one or more arrays and one or more
regular arguments. There is no rule that sets some restrictions.

You can also create a method that takes one or more arrays as argument(s) and returns
a regular value of a primitive type.

Returning an Array From a Method

Like a normal variable, an array can be returned from a method. This means that the
method would return a variable that carries various values. When declaring or defining
the method, you must specify its data type. When the method ends, it would return an
array represented by the name of its variable.

You can create a method that takes an array as argument and returns another array as
argument.

C# 3.0 Practical Learning 528


To declare a method that returns an array, on the left of the method's name, provide
the type of value that the returned array  will be made of, followed by empty square
brackets. Here is an example:
using System;

public class CoordinateSystem


{
public int[] Initialize()
{
}
}

Remember that a method must always return an appropriate value depending on how it
was declared. In this case, if it was specified as returning an array, then make sure it
returns an array and not a regular variable. One way you can do this is to declare and
possibly initialize a local array variable. After using the local array, you return only its
name (without the square brackets). Here is an example:
using System;

public class CoordinateSystem


{
public int[] Initialize()
{
var Coords = new int[] { 12, 5, -2, -2 };

return Coords;
}
}

When a method returns an array, that method can be assigned to an array declared
locally when you want to use it. Remember to initialize a variable with such a method
only if the variable is an array. 

Here is an example:
using System;

public class CoordinateSystem


{
public int[] Initialize()
{
var Coords = new int[] { 12, 5, -2, -2 };

return Coords;
}

public void ShowPoints(int[] Points)


{
Console.WriteLine("Points Coordinates");
Console.WriteLine("P({0}, {1})", Points[0], Points[1]);
Console.WriteLine("Q({0}, {1})", Points[2], Points[3]);
}
}

public class Exercise


{
static int Main()
C# 3.0 Practical Learning 529
{
var System = new int[4];
var Coordinates = new CoordinateSystem();

System = Coordinates.Initialize();
Coordinates.ShowPoints(System);

return 0;
}
}

The method could also be called as follows:


public class Exercise
{
static int Main()
{
var Coordinates = new CoordinateSystem();

var System = Coordinates.Initialize();


Coordinates.ShowPoints(System);

return 0;
}
}

If you initialize an array variable with a method that doesn't return an array, you would
receive an error.

Main()'s Argument
  

Introduction

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. The way this works is that, at the beginning, the compiler looks
for a method called Main. If it doesn't find it, it produces an error. If it finds it, it enters
the Main() method in a top-down approach, starting just after the opening curly
bracket. If it finds a problem and judges that it is not worth continuing, it stops and lets
you know. If, or as long as, it doesn't find a problem, it continues line after line, with the
option to even call or execute a method in the same file or in another file. This process
continues to the closing curly bracket "}". Once the compiler finds the closing bracket,
the whole program has ended and stops.

If you want the user to provide additional information when executing your program,
you can take care of this in the Main() method. Consider the following code written in a
file saved as Exercise.cs:
using System;

public class Exercise


{
static int Main()
{
string FirstName = "James";
C# 3.0 Practical Learning 530
string LastName = "Weinberg";
double WeeklyHours = 36.50;
double HourlySalary = 12.58;

string FullName = LastName + ", " + FirstName;


double WeeklySalary = WeeklyHours * HourlySalary;

Console.WriteLine("Employee Payroll");
Console.WriteLine("Full Name: {0}", FullName);
Console.WriteLine("WeeklySalary: {0}",
WeeklySalary.ToString("C"));
return 0;
}
}

To execute the application, at the Command Prompt and after Changing to the Directory
that contains the file, you would type
csc Exercise.cs

and press Enter. To execute the program, you would type the name Exercise and
press Enter. The program would then prompt you for the information it needs.

Command Request from Main()

To compile a program, you would simply type the csc command at the command
prompt. Then, to execute a program, you would type its name at the prompt. If you
distribute a program, you would tell the user to type the name of the program at the
command prompt. In some cases, you may want the user to type additional information
besides the name of the program. To request additional information from the user, you
can pass a string argument to the Main() method. The argument should be passed as
an array and make sure you provide a name for the argument. Here is an example:
using System;

class ObjectName
{
static int Main(string[] args)
{
return 0;
}
}

The reason you pass the argument as an array is so you can use as many values as you
judge necessary. To provide values at the command prompt, the user types the name of
the program followed by each necessary value. Here is an example:

C# 3.0 Practical Learning 531


The values the user would provide are stored in a zero-based array without considering
the name of the program. The first value (that is, after the name of the program) is
stored at index 0, the second at index 1, etc. Based on this, the first argument is
represented by args[0], the second is represented by args[1], etc.

Each of the values the user types is a string. If any one of them is not a string, you
should/must convert/cast its string first to the appropriate value. Consider the following
source code:
using System;

namespace CSharpLessons
{
public class Exercise
{
static int Main(string[] Argument)
{
string FirstName;
string LastName;
Double WeeklyHours;
Double HourlySalary;

FirstName = Argument[0];
LastName = Argument[1];
WeeklyHours = Double.Parse(Argument[2]);
HourlySalary = Double.Parse(Argument[3]);

string FullName = LastName + ", " + FirstName;


Double WeeklySalary = WeeklyHours * HourlySalary;

Console.WriteLine("Employee Payroll");
Console.WriteLine("Full Name: {0}", FullName);
Console.WriteLine("WeeklySalary: {0}",
WeeklySalary.ToString("C"));

return 0;
}
}
}

C# 3.0 Practical Learning 532


To compile it at the Command Prompt, after switching to the directory that contains the
file, you would type
csc Exercise.cs

and press Enter. To execute the program, you would type Exercise followed by a first
name, a last name, and two decimal values. An example would be Exercise
Catherine Engolo 42.50 20.48

An Array of Objects
 

Introduction

As done for primitive types, you can create an array of values where each member of
the array is based on a formal class. Of course, you must have a class first. You can
use one of the already available classes or you can create your own class. Here is an
example:
using System;

public enum EmploymentStatus


{
FullTime,
PartTime,
Unknown
};
public class Employee
{
private long emplNbr;
private string name;
private EmploymentStatus st;
private double wage;

public long EmployeeNumber


{
get { return emplNbr; }
set { emplNbr = value; }
}

public string EmployeeName


{
get { return name; }

C# 3.0 Practical Learning 533


set { name = value; }
}

public EmploymentStatus Status


{
get { return st; }
set { st = value; }
}

public double HourlySalary


{
get { return wage; }
set { wage = value; }
}
}

Practical Learning: Introducing Arrays of Objects

1. Create a new Console Application named RentalProperties2

2. To create a new class, in the Solution Explorer, right-click RenatlProperties1 -> Add
-> Class...

3. Set the Name to RentalProperty and press Enter

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RentalProperties2
{
public enum PropertyType
{
SingleFamily, Townhouse,
Apartment, Unknown
};

public class RentalProperty


{
private long nbr;
private PropertyType tp;
private short bd;
private float bt;
private double rnt;

public RentalProperty()
{
nbr = 0;
tp = PropertyType.Unknown;
bd = 0;
bt = 0.0F;
rnt = 0D;
}

C# 3.0 Practical Learning 534


public RentalProperty(long PropNbr, PropertyType Type,
short Beds, float Baths, double Rent)
{
PropNbr = nbr;
Type = PropertyType.Unknown;
Beds = bd;
Baths = bt;
Rent = rnt;
}

public long PropertyNumber


{
get { return nbr; }
set { nbr = value; }
}

public PropertyType TypeOfProperty


{
get { return tp; }
set { tp = value; }
}

public short Bedrooms


{
get { return bd; }
set { bd = value; }
}

public float Bathrooms


{
get { return bt; }
set { bt = value; }
}

public double MonthlyRent


{
get { return rnt; }
set { rnt = value; }
}
}
}

5. Save all and accept the suggested name of the project

Creating an Array of Objects

To create an array of objects, you can declare an array variable and use the square
brackets to specify its size. Here is an example:
public static class Exercise
{
static void Main(string[] args)
{
Employee[] StaffMembers = new Employee[3];

return 0;
}
}

C# 3.0 Practical Learning 535


You can also use the var keyword to create the array but omit the first square brackets.
Here is an example:
public static class Exercise
{
static void Main(string[] args)
{
var StaffMembers = new Employee[3];

return 0;
}
}

Initializing an Array of Objects

If you create an array like this, you can then access each member using its index,
allocate memory for it using the new operator, then access each of its fields, still using
its index, to assign it the desired value. Here is an example:
public static class Exercise
{
static void Main(string[] args)
{
var StaffMembers = new Employee[3];

StaffMembers[0] = new Employee();


StaffMembers[0].EmployeeNumber = 20204;
StaffMembers[0].EmployeeName = "Harry Fields";
StaffMembers[0].Status = EmploymentStatus.FullTime;
StaffMembers[0].HourlySalary = 16.85;

StaffMembers[1] = new Employee();


StaffMembers[1].EmployeeNumber = 92857;
StaffMembers[1].EmployeeName = "Jennifer Almonds";
StaffMembers[1].Status = EmploymentStatus.FullTime;
StaffMembers[1].HourlySalary = 22.25;

StaffMembers[2] = new Employee();


StaffMembers[2].EmployeeNumber = 42963;
StaffMembers[2].EmployeeName = "Sharon Culbritt";
StaffMembers[2].Status = EmploymentStatus.PartTime;
StaffMembers[2].HourlySalary = 10.95;

return 0;
}
}

As an alternative, you can also initialize each member of the array when creating it. To
do this, before the semi-colon of creating the array, open the curly brackets, allocate
memory for each member and specify the values of each field. To do this, you must use
a constructor that takes each member you want to initialize, as argument. Here is an
example:
using System;

public enum EmploymentStatus


{
FullTime,
C# 3.0 Practical Learning 536
PartTime,
Unknown
};

public class Employee


{
private long emplNbr;
private string name;
private EmploymentStatus st;
private double wage;

public Employee()
{
}

public Employee(long Number, string Name,


EmploymentStatus EStatus, double Salary)
{
emplNbr = Number;
name = Name;
st = EStatus;
wage = Salary;
}

public long EmployeeNumber


{
get { return emplNbr; }
set { emplNbr = value; }
}

public string EmployeeName


{
get { return name; }
set { name = value; }
}

public EmploymentStatus Status


{
get { return st; }
set { st = value; }
}

public double HourlySalary


{
get { return wage; }
set { wage = value; }
}
}

public static class Exercise


{
static void Main(string[] args)
{
var StaffMembers = new Employee[]
{
new Employee(20204, "Harry Fields",
EmploymentStatus.FullTime, 16.85),
new Employee(92857, "Jennifer Almonds",
EmploymentStatus.FullTime, 22.25),
new Employee(42963, "Sharon Culbritt",
C# 3.0 Practical Learning 537
EmploymentStatus.PartTime, 10.95)
};

return 0;
}
}

If using the var keyword and a constructor to initialize the array, you can omit calling
the name of the class before the square brackets. Here is an example:
public static class Exercise
{
static void Main(string[] args)
{
var StaffMembers = new[]
{
new Employee(20204, "Harry Fields",
EmploymentStatus.FullTime, 16.85),
new Employee(92857, "Jennifer Almonds",
EmploymentStatus.FullTime, 22.25),
new Employee(42963, "Sharon Culbritt",
EmploymentStatus.PartTime, 10.95)
};

return 0;
}
}

Accessing the Members of the Array

After creating and initializing the array, you can use it as you see fit. For example, you
may want to display its values to the user. You can access any member of the array by
its index, then use the same index to get its field(s) and consequently its (their)
value(s). Here is an example:
public static class Exercise
{
static void Main(string[] args)
{
var StaffMembers = new Employee[]
{
new Employee(20204, "Harry Fields",
EmploymentStatus.FullTime, 16.85),
new Employee(92857, "Jennifer Almonds",
EmploymentStatus.FullTime, 22.25),
new Employee(42963, "Sharon Culbritt",
EmploymentStatus.PartTime, 10.95)
};

Console.WriteLine("Employee Record");
Console.WriteLine("---------------------------");
Console.WriteLine("Employee #: {0}",
StaffMembers[2].EmployeeNumber);
Console.WriteLine("Full Name: {0}",
StaffMembers[2].EmployeeName);
Console.WriteLine("Status: {0}", StaffMembers[2].Status);
Console.WriteLine("Hourly Wage {0}",
StaffMembers[2].HourlySalary);

C# 3.0 Practical Learning 538


Console.WriteLine("---------------------------\n");

return 0;
}
}

This would produce:


Employee Record
---------------------------
Employee #: 42963
Full Name: Sharon Culbritt
Status: PartTime
Hourly Wage 10.95
---------------------------

Press any key to continue . . .

Once again, remember that the index you use must be higher than 0 but lower than the
number of members - 1. Otherwise, the compiler would throw an
IndexOutRangeException exception.

In the same way, you can use a for loop to access all members of the array using their
index. Here is an example:
public static class Exercise
{
static void Main(string[] args)
{
var StaffMembers= new Employee[]
{
new Employee(20204, "Harry Fields",
EmploymentStatus.FullTime, 16.85),
new Employee(92857, "Jennifer Almonds",
EmploymentStatus.FullTime, 22.25),
new Employee(42963, "Sharon Culbritt",
EmploymentStatus.PartTime, 10.95)
};

Console.WriteLine("Employees Records");
Console.WriteLine("==========================");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Employee #: {0}",
StaffMembers[i].EmployeeNumber);
Console.WriteLine("Full Name: {0}",
StaffMembers[i].EmployeeName);
Console.WriteLine("Status: {0}", StaffMembers[i].Status);
Console.WriteLine("Hourly Wage {0}",
StaffMembers[i].HourlySalary);
Console.WriteLine("---------------------------");
}

return 0;
}
}

To access each member of the array, you can use the foreach operator that allows you
to use a name for each member and omit the square brackets. Here is an example:

C# 3.0 Practical Learning 539


public static class Exercise
{
static void Main(string[] args)
{
var StaffMembers = new Employee[]
{
new Employee(20204, "Harry Fields",
EmploymentStatus.FullTime, 16.85),
new Employee(92857, "Jennifer Almonds",
EmploymentStatus.FullTime, 22.25),
new Employee(42963, "Sharon Culbritt",
EmploymentStatus.PartTime, 10.95)
};

Console.WriteLine("Employees Records");
Console.WriteLine("==========================");
foreach(var Member in StaffMembers)
{
Console.WriteLine("Employee #: {0}", Member.EmployeeNumber);
Console.WriteLine("Full Name: {0}", Member.EmployeeName);
Console.WriteLine("Status: {0}", Member.Status);
Console.WriteLine("Hourly Wage {0}", Member.HourlySalary);
Console.WriteLine("---------------------------");
}

return 0;
}
}

This would produce:


Employees Records
==========================
Employee #: 20204
Full Name: Harry Fields
Status: FullTime
Hourly Wage 16.85
---------------------------
Employee #: 92857
Full Name: Jennifer Almonds
Status: FullTime
Hourly Wage 22.25
---------------------------
Employee #: 42963
Full Name: Sharon Culbritt
Status: PartTime
Hourly Wage 10.95
---------------------------
Press any key to continue . . .

Practical Learning: Using an Array of Objects

1. Access the Program.cs file and change it file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
C# 3.0 Practical Learning 540
namespace RentalProperties2
{
public class Program
{
static void Main(string[] args)
{
RentalProperty[] Properties = new RentalProperty[8];

Properties[0] = new RentalProperty();


Properties[0].PropertyNumber = 192873;
Properties[0].TypeOfProperty = PropertyType.SingleFamily;
Properties[0].Bedrooms = 5;
Properties[0].Bathrooms = 3.50F;
Properties[0].MonthlyRent = 2250.00D;
Properties[1] = new RentalProperty();
Properties[1].PropertyNumber = 498730;
Properties[1].TypeOfProperty = PropertyType.SingleFamily;
Properties[1].Bedrooms = 4;
Properties[1].Bathrooms = 2.50F;
Properties[1].MonthlyRent = 1885.00D;
Properties[2] = new RentalProperty();
Properties[2].PropertyNumber = 218502;
Properties[2].TypeOfProperty = PropertyType.Apartment;
Properties[2].Bedrooms = 2;
Properties[2].Bathrooms = 1.00F;
Properties[2].MonthlyRent = 1175.50D;
Properties[3] = new RentalProperty();
Properties[3].PropertyNumber = 612739;
Properties[3].TypeOfProperty = PropertyType.Apartment;
Properties[3].Bedrooms = 1;
Properties[3].Bathrooms = 1.00F;
Properties[3].MonthlyRent = 945.00D;
Properties[4] = new RentalProperty();
Properties[4].PropertyNumber = 457834;
Properties[4].TypeOfProperty = PropertyType.Townhouse;
Properties[4].Bedrooms = 3;
Properties[4].Bathrooms = 2.50F;
Properties[4].MonthlyRent = 1750.50D;
Properties[5] = new RentalProperty();
Properties[5].PropertyNumber = 927439;
Properties[5].TypeOfProperty = PropertyType.Apartment;
Properties[5].Bedrooms = 1;
Properties[5].Bathrooms = 1.00F;
Properties[5].MonthlyRent = 1100.00D;
Properties[6] = new RentalProperty();
Properties[6].PropertyNumber = 570520;
Properties[6].TypeOfProperty = PropertyType.Apartment;
Properties[6].Bedrooms = 3;
Properties[6].Bathrooms = 2.00F;
Properties[6].MonthlyRent = 1245.95D;
Properties[7] = new RentalProperty();
Properties[7].PropertyNumber = 734059;
Properties[7].TypeOfProperty = PropertyType.Townhouse;
Properties[7].Bedrooms = 4;
Properties[7].Bathrooms = 1.50F;
Properties[7].MonthlyRent = 1950.25D;

Console.WriteLine("Properties Listing");

C# 3.0 Practical Learning 541


Console.WriteLine("=============================================");
Console.WriteLine("Prop # Property Type Beds Baths Monthly
Rent");

Console.WriteLine("---------------------------------------------");
for (int i = 0; i < 8; i++)
{
Console.WriteLine("{0}\t{1}\t{2} {3:F}{4,12}",
Properties[i].PropertyNumber,
Properties[i].TypeOfProperty,
Properties[i].Bedrooms,
Properties[i].Bathrooms,
Properties[i].MonthlyRent);
}

Console.WriteLine("=============================================");
}
}
}

2. Execute the application to see the result


 
Properties Listing
=============================================
Prop # Property Type Beds Baths Monthly Rent
---------------------------------------------
192873 SingleFamily 5 3.50 2250
498730 SingleFamily 4 2.50 1885
218502 Apartment 2 1.00 1175.5
612739 Apartment 1 1.00 945
457834 Townhouse 3 2.50 1750.5
927439 Apartment 1 1.00 1100
570520 Apartment 3 2.00 1245.95
734059 Townhouse 4 1.50 1950.25
=============================================
Press any key to continue . . .

3. Close the DOS window and return to your programming environment

A Class Array as a Field


 

Introduction

Like a primitive type, an array of objects can be made a field of a class. You can
primarily declare the array and specify its size. Here is an example:
public class CompanyRecords
{
Employee[] Employees = new Employee[2];
}

After doing this, you can then initialize the array from the index of each member.
Alternatively, as we saw for field arrays of primitive types, you can declare the array in

C# 3.0 Practical Learning 542


the body of the class, then use a constructor or another method of the class to allocate
memory for it.

To initialize the array, remember that each member is a value that must be allocated on
the heap. Therefore, apply the new operator on each member of the array to allocate its
memory, and then initialize it. Here is an example:
public class CompanyRecords
{
Employee[] Employees;

public CompanyRecords()
{
Employees = new Employee[2];

Employees[0] = new Employee();


Employees[0].EmployeeNumber = 70128;
Employees[0].EmployeeName = "Frank Dennison";
Employees[0].Status = EmploymentStatus.PartTime;
Employees[0].HourlySalary = 8.65;

Employees[1] = new Employee();


Employees[1].EmployeeNumber = 24835;
Employees[1].EmployeeName = "Jeffrey Arndt";
Employees[1].Status = EmploymentStatus.Unknown;
Employees[1].HourlySalary = 16.05;
}
}

If the class used as field has an appropriate constructor, you can use it to initialize each
member of the array. Here is an example:
public class CompanyRecords
{
Employee[] Employees;

public CompanyRecords()
{
Employees = new Employee[]
{
new Employee(70128, "Justine Hearson",
EmploymentStatus.PartTime, 10.62),
new Employee(24835, "Bertha Hack",
EmploymentStatus.FullTime, 18.94),
new Employee(70128, "Frank Dennison",
EmploymentStatus.Seasonal, 12.48),
new Employee(24835, "Jeffrey Arndt",
EmploymentStatus.PartTime, 16.05),
};
}
}

Using the Array

Once you have created and initialized the array, you can use it as you see fit, such as
displaying its values to the user. You must be able to access each member of the array,
using its index. Once you have accessed member, you can get to its fields or properties.
Here is an example:
C# 3.0 Practical Learning 543
using System;

public enum EmploymentStatus


{
FullTime,
PartTime,
Seasonal,
Unknown
};

public class Employee


{
private long emplNbr;
private string name;
private EmploymentStatus st;
private double wage;

public Employee()
{
}

public Employee(long Number, string Name,


EmploymentStatus EStatus, double Salary)
{
emplNbr = Number;
name = Name;
st = EStatus;
wage = Salary;
}

public long EmployeeNumber


{
get { return emplNbr; }
set { emplNbr = value; }
}

public string EmployeeName


{
get { return name; }
set { name = value; }
}

public EmploymentStatus Status


{
get { return st; }
set { st = value; }
}

public double HourlySalary


{
get { return wage; }
set { wage = value; }
}
}

public class CompanyRecords


{
Employee[] Employees;

public CompanyRecords()
C# 3.0 Practical Learning 544
{
Employees = new Employee[]
{
new Employee(70128, "Justine Hearson",
EmploymentStatus.PartTime, 10.62),
new Employee(24835, "Bertha Hack",
EmploymentStatus.FullTime, 18.94),
new Employee(70128, "Frank Dennison",
EmploymentStatus.Seasonal, 12.48),
new Employee(24835, "Jeffrey Arndt",
EmploymentStatus.PartTime, 16.05),
};
}

public void ShowRecords()


{
Console.WriteLine("Employees Records");
Console.WriteLine("==========================");

foreach (var Member in Employees)


{
Console.WriteLine("Employee #: {0}", Member.EmployeeNumber);
Console.WriteLine("Full Name: {0}", Member.EmployeeName);
Console.WriteLine("Status: {0}", Member.Status);
Console.WriteLine("Hourly Wage {0}", Member.HourlySalary);
Console.WriteLine("---------------------------");
}
}
}

public static class Exercise


{
static void Main(string[] args)
{
var Records = new CompanyRecords();
Records.ShowRecords();

return 0;
}
}

This would produce:


Employees Records
==========================
Employee #: 70128
Full Name: Justine Hearson
Status: PartTime
Hourly Wage 10.62
---------------------------
Employee #: 24835
Full Name: Bertha Hack
Status: FullTime
Hourly Wage 18.94
---------------------------
Employee #: 70128
Full Name: Frank Dennison
Status: Seasonal
Hourly Wage 12.48
---------------------------
C# 3.0 Practical Learning 545
Employee #: 24835
Full Name: Jeffrey Arndt
Status: PartTime
Hourly Wage 16.05
---------------------------
Press any key to continue . . .

Arrays of Objects and Methods


 

Passing an Array of Objects as Argument

As done for an array of a primitive type, you can pass an array of objects as arguments.
You follow the same rules we reviewed; that is, in the parentheses of a method, enter
the class name, the empty square brackets, and the name of the argument. Here is an
example:
public class CompanyRecords
{
public CompanyRecords(Employee[] Employees)
{
}
}

You can then access each member of the argument and do what you judge necessary.
For example, you can display the values that the argument is holding. To call a method
that takes an array of objects, in its parentheses, just enter the name of the array. Here
is an example:
public class CompanyRecords
{
public CompanyRecords(Employee[] Employees)
{
Employees = new Employee[]
{
new Employee(70128, "Justine Hearson",
EmploymentStatus.PartTime, 10.62),
new Employee(24835, "Bertha Hack",
EmploymentStatus.FullTime, 18.94),
new Employee(70128, "Frank Dennison",
EmploymentStatus.Seasonal, 12.48),
new Employee(24835, "Jeffrey Arndt",
EmploymentStatus.PartTime, 16.05),
};
}
}

public static class Exercise


{
static void Main(string[] args)
{
var Values = new Employee[4];

CompanyRecords Records = new CompanyRecords(Values);


Records.ShowRecords();

C# 3.0 Practical Learning 546


return 0;
}
}

As stated for an array of primitive type, an array of objects passed as argument is


treated as a reference. You can use this characteristic of arrays to initialize the array.
You can also indicate that the array is passed by reference by preceding its name with
the ref keyword.

Returning an Array of Objects

An array of objects can be returned from a method. To indicate this when defining the
method, first type the name of the class followed by square brackets. Here is an
example:
public class CompanyRecords
{
public Employee[] RegisterEmployees()
{
}
}

In the body of the method, you can take care of any assignment you want. The major
rule to follow is that, before exiting the method, you must return an array of the class
indicated on the left side of the method name.

To use the method, you can simply call. If you want, since the method returns an array,
you can retrieve that series and store it in a local array value for later use. Here is an
example:
using System;

public enum EmploymentStatus


{
FullTime,
PartTime,
Seasonal,
Unknown
};

public class Employee


{
private long emplNbr;
private string name;
private EmploymentStatus st;
private double wage;

public Employee()
{
}

public Employee(long Number, string Name,


EmploymentStatus EStatus, double Salary)
{
emplNbr = Number;
name = Name;
st = EStatus;
wage = Salary;
C# 3.0 Practical Learning 547
}

public long EmployeeNumber


{
get { return emplNbr; }
set { emplNbr = value; }
}

public string EmployeeName


{
get { return name; }
set { name = value; }
}

public EmploymentStatus Status


{
get { return st; }
set { st = value; }
}

public double HourlySalary


{
get { return wage; }
set { wage = value; }
}
}

public class CompanyRecords


{
public CompanyRecords()
{
}

public Employee[] RegisterEmployees()


{
var Employees = new Employee[]
{
new Employee(70128, "Justine Hearson",
EmploymentStatus.PartTime, 10.62),
new Employee(24835, "Bertha Hack",
EmploymentStatus.FullTime, 18.94),
new Employee(70128, "Frank Dennison",
EmploymentStatus.Seasonal, 12.48),
new Employee(24835, "Jeffrey Arndt",
EmploymentStatus.PartTime, 16.05),
};
return Employees;
}

public void ShowRecords(ref Employee[] Records)


{
Console.WriteLine("Employees Records");
Console.WriteLine("==========================");

foreach (var Staff in Records)


{
Console.WriteLine("Employee #: {0}", Staff.EmployeeNumber);
Console.WriteLine("Full Name: {0}", Staff.EmployeeName);
Console.WriteLine("Status: {0}", Staff.Status);
Console.WriteLine("Hourly Wage {0}", Staff.HourlySalary);
C# 3.0 Practical Learning 548
Console.WriteLine("---------------------------");
}
}
}

public static class Exercise


{
static void Main(string[] args)
{
var Records = new CompanyRecords();

var Contractors = Records.RegisterEmployees();


Records.ShowRecords(ref Contractors);

return 0;
}
}

Practical Learning: Using Array of Objects With Methods

1. To apply what we learned in the last few sections, change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RentalProperties2
{
public class Program
{
private static void ShowProperties(RentalProperty[] Properties)
{
Console.WriteLine("Properties Listing");

Console.WriteLine("=============================================");
Console.WriteLine("Prop # Property Type Beds Baths Monthly
Rent");

Console.WriteLine("---------------------------------------------");
for (int i = 0; i < 8; i++)
{
Console.WriteLine("{0}\t{1}\t{2} {3:F}{4,12}",
Properties[i].PropertyNumber,
Properties[i].TypeOfProperty,
Properties[i].Bedrooms,
Properties[i].Bathrooms,
Properties[i].MonthlyRent);
}

Console.WriteLine("=============================================");
}

private static RentalProperty[] CreateListing()


{
RentalProperty[] HousesToRent = new RentalProperty[8];

HousesToRent[0] = new RentalProperty();


C# 3.0 Practical Learning 549
HousesToRent[0].PropertyNumber = 192873;
HousesToRent[0].TypeOfProperty = PropertyType.SingleFamily;
HousesToRent[0].Bedrooms = 5;
HousesToRent[0].Bathrooms = 3.50F;
HousesToRent[0].MonthlyRent = 2250.00D;
HousesToRent[1] = new RentalProperty();
HousesToRent[1].PropertyNumber = 498730;
HousesToRent[1].TypeOfProperty = PropertyType.SingleFamily;
HousesToRent[1].Bedrooms = 4;
HousesToRent[1].Bathrooms = 2.50F;
HousesToRent[1].MonthlyRent = 1885.00D;
HousesToRent[2] = new RentalProperty();
HousesToRent[2].PropertyNumber = 218502;
HousesToRent[2].TypeOfProperty = PropertyType.Apartment;
HousesToRent[2].Bedrooms = 2;
HousesToRent[2].Bathrooms = 1.00F;
HousesToRent[2].MonthlyRent = 1175.50D;
HousesToRent[3] = new RentalProperty();
HousesToRent[3].PropertyNumber = 612739;
HousesToRent[3].TypeOfProperty = PropertyType.Apartment;
HousesToRent[3].Bedrooms = 1;
HousesToRent[3].Bathrooms = 1.00F;
HousesToRent[3].MonthlyRent = 945.00D;
HousesToRent[4] = new RentalProperty();
HousesToRent[4].PropertyNumber = 457834;
HousesToRent[4].TypeOfProperty = PropertyType.Townhouse;
HousesToRent[4].Bedrooms = 3;
HousesToRent[4].Bathrooms = 2.50F;
HousesToRent[4].MonthlyRent = 1750.50D;
HousesToRent[5] = new RentalProperty();
HousesToRent[5].PropertyNumber = 927439;
HousesToRent[5].TypeOfProperty = PropertyType.Apartment;
HousesToRent[5].Bedrooms = 1;
HousesToRent[5].Bathrooms = 1.00F;
HousesToRent[5].MonthlyRent = 1100.00D;
HousesToRent[6] = new RentalProperty();
HousesToRent[6].PropertyNumber = 570520;
HousesToRent[6].TypeOfProperty = PropertyType.Apartment;
HousesToRent[6].Bedrooms = 3;
HousesToRent[6].Bathrooms = 2.00F;
HousesToRent[6].MonthlyRent = 1245.95D;
HousesToRent[7] = new RentalProperty();
HousesToRent[7].PropertyNumber = 734059;
HousesToRent[7].TypeOfProperty = PropertyType.Townhouse;
HousesToRent[7].Bedrooms = 4;
HousesToRent[7].Bathrooms = 1.50F;
HousesToRent[7].MonthlyRent = 1950.25D;

return HousesToRent;
}

static void Main(string[] args)


{
RentalProperty[] Properties = CreateListing();

ShowProperties(Properties);
}
}
}

C# 3.0 Practical Learning 550


2. Execute the application to see the result 

3. Close the DOS window and return to your programming environment

Arrays and Delegates


 

Introduction

While a regular method can be used to return an array, you can use the features of a
delegate to return an array of methods or to take an array of methods as arguments. Of
course before proceeding, you must first create the necessary delegate. Here is an
example:
using System;

delegate double Measure(double R);

public static class Program


{
static int Main(string[] args)
{
return 0;
}
}

Before creating the array, you must first know or have the methods you would be
referring to. These methods must have a similar signature. This means that they must
return the same type of value, they must have the same number of arguments and they
must  have the  same type(s) of argument(s), if any. Here are examples of such
functions:
using System;

delegate double Measure(double R);

public class Circle


{
const double PI = 3.14159;

double Diameter(double Radius)


{
return Radius * 2;
}

double Circumference(double Radius)


{
return Diameter(Radius) * PI;
}

double Area(double Radius)


{
return Radius * Radius * PI;
}
}

public static class Program


C# 3.0 Practical Learning 551
{
static void Main(string[] args) {
return 0;
}
}

An Array of Delegates

To create an array of delegates, declare a normal array as we have done so far. You can
initialize each member using its index and calling the corresponding method. This can be
done as follows:
using System;

delegate double Measure(double R);

public class Circle


{
const double PI = 3.14159;

public double Diameter(double Radius)


{
return Radius * 2;
}

public double Circumference(double Radius)


{
return Diameter(Radius) * PI;
}

public double Area(double Radius)


{
return Radius * Radius * PI;
}
}

public static class Program


{
static void Main(string[] args) {
double R = 12.55;
Circle circ = new Circle();
Measure[] Calc = new Measure[3];

Calc[0] = new Measure(circ.Diameter);


double D = Calc[0](R);
Calc[1] = new Measure(circ.Circumference);
double C = Calc[1](R);
Calc[2] = new Measure(circ.Area);
double A = Calc[2](R);

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Diameter: {0}", D);
Console.WriteLine("Circumference: {0}", C);
Console.WriteLine("Area: {0}\n", A);

return 0;
}
}

C# 3.0 Practical Learning 552


You can also list the members of the array when creating it. After creating the array,
you can retrieve its value and store it in a variable. Here is an example:
public static class Program
{
static void Main(string[] args) {
double R = 12.55;
Circle circ = new Circle();
Measure[] Calc = new Measure[]
{
new Measure(circ.Diameter),
new Measure(circ.Circumference),
new Measure(circ.Area)
};

double D = Calc[0](R);
double C = Calc[1](R);
double A = Calc[2](R);

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Diameter: {0}", D);
Console.WriteLine("Circumference: {0}", C);
Console.WriteLine("Area: {0}\n", A);

return 0;
}
}

The above code could also be written as follows:


public static class Program
{
static void Main(string[] args)
{
double R = 12.55;
Circle circ = new Circle();
Measure[] Calc = new Measure[]
{
new Measure(circ.Diameter),
new Measure(circ.Circumference),
new Measure(circ.Area)
};

Console.WriteLine("Circle Characteristics");
Console.WriteLine("Diameter: {0}", Calc[0](R));
Console.WriteLine("Circumference: {0}", Calc[1](R));
Console.WriteLine("Area: {0}\n", Calc[2](R));

return 0;
}
}

This would produce:


Circle Characteristics
Diameter: 25.1
Circumference: 78.8539
Area: 494.808

C# 3.0 Practical Learning 553


Multidimensional Arrays
 

Fundamentals of Multidimensional Arrays


 

Introduction

The arrays we used so far were made of a uniform series, where all members consisted
of a simple list, like a column of names on a piece of paper. Also, all items fit in one list.
This type of array is referred to as one-dimensional.

In some cases, you may want to divide the list in delimited sections. For example, if you
create a list of names, you may want part of the list to include family members and
another part of the list to include friends. Instead of creating a second list, you can add
a second dimension to the list. In other words, you would create a list of a list, or one
list inside of another list, although the list is still made of items with common
characteristics.

A multidimensional array is a series of arrays so that each arrays contains its own sub-
array(s).

Practical Learning: Introducing Multidimensional Arrays

1. Create a new Console Application named DepartmentStore3

2. Change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore3
{
public class Program
{
static void Main(string[] args)
{
long ItemID = 0;
string Description = "Unknown";
double Price = 0.00D;

Console.WriteLine("Receipt");
Console.WriteLine("Item Number: {0}", ItemID);
Console.WriteLine("Description: {0}", Description);
Console.WriteLine("Unit Price: {0:C}\n", Price);
C# 3.0 Practical Learning 554
}
}
}

3. Execute the application to see the result. This would produce:


 
Receipt
Item Number: 0
Description: Unknown
Unit Price: $0.00

Press any key to continue . . .

4. Close the DOS window

Creating a Two-Dimensional Array

The most basic multidimensional array is made of two dimensions. This is referred to as
two-dimensional.  To create a two-dimensional array, declare the array variable as we
have done so far but add a comma in the square brackets. The formula you would use
is:
DataType[,] VariableName;

The pair of brackets is empty but must contain a comma. There are various ways you
can initialize a two-dimensional array. If you are declaring the array variable but are not
ready to initialize it, use the following formula:
DataType[,] VariableName = new DataType[Number1,Number2];

Or you can use the var keyword:


var VariableName = new DataType[Number1,Number2];

Either way, in the right pair of square brackets, enter two integers separated by a
comma. Here is an example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = new string[2, 4];

return 0;
}
}

In our declaration, the Members variable contains two lists. Each of the two lists
contains 4 elements. This means that the first list contains 4 elements and the second
list contains 4 elements. Therefore, the whole list is made of 8  elements (2 * 4 = 8).
Because the variable is declared as a string, each of the 8 items must be a string.

You can also create a two-dimensional array that takes more than two lists, such as 3,
4, 5 or more. Here is an example:

C# 3.0 Practical Learning 555


using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Prices = new double[5, 8];

return 0;
}
}

This time, the variable has 5 lists and each list contains 8 elements. This means that the
whole variable contains 5 * 8 = 40 elements.

If you want to declare the array variable using the first formula where you don't know
the sizes of the lists, you must use the data type of the array and you can omit the right
square brackets. Here is an example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
string[,] Members;

return 0;
}
}

In this case also, remember that you need the square brackets. If you use the var
keyword, you don't need the left square brackets but, in the right square brackets, you
must specify the sizes.

You can initialize an array variable when declaring it. To do this, on the right side of the
declaration, before the closing semi-colon, type an opening and a closing curly brackets.
Inside of the brackets, include a pair of an opening and a closing curly brackets for each
internal list of the array. Then, inside of a pair of curly brackets, provide a list of the
values of the internal array, just as you would do for a one-dimensional array. Here is an
example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = new string[2, 4]
{
{"Celeste", "Mathurin", "Alex", "Germain"}, // First List
{"Jeremy", "Mathew", "Anselme", "Frederique"} // Second List
};

return 0;
}
}

C# 3.0 Practical Learning 556


When initializing a two-dimensional array, remember the dimensions. The number on
the left side of the right comma specifies the number of main lists and the number on
the right side of the right comma specifies the number of elements in each list. Here is
an example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Prices = new double[5, 8]
{
{ 10.50, 2.35, 49.75, 202.35, 8.70, 58.20, 34.85, 48.50 },
{ 23.45, 878.50, 26.35, 475.90, 2783.45, 9.50, 85.85,
792.75 },
{ 47.95, 72.80, 34.95, 752.30, 49.85, 938.70, 45.05, 9.80 },
{ 759.25, 73.45, 284.35, 70.95, 82.05, 34.85, 102.30,
84.50 },
{ 29.75, 953.45, 79.55, 273.45, 975.90, 224.75, 108.25, 34.05
}
};

return 0;
}
}

If you use this technique to initialize an array, you can omit specifying the dimension of
the array. That is, you can remove the numbers in the right square brackets. Here is an
example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Members = new string[,]
{
{"Celeste", "Mathurin", "Alex", "Germain"}, // First List
{"Jeremy", "Mathew", "Anselme", "Frederique"} // Second List
};

return 0;
}
}

Practical Learning: Creating a Two-Dimensional Array

1. To create and use a two-dimensional array, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
C# 3.0 Practical Learning 557
namespace DepartmentStore3
{
public class Program
{
static void Main(string[] args)
{
long ItemID = 0;
string Description = "Unknown";
double Price = 0.00D;

// The first list contains women's items


// The other contains non-women items
long[,] ItemNumber = new long[2, 5]
{
{ 947783, 934687, 973947, 987598, 974937 },
{ 739579, 367583, 743937, 437657, 467945 } };

string[,] ItemName = new string[2, 5]


{

{ "Women Double-faced wool coat",

"Women Floral Silk Tank Blouse",

"Women Push Up Bra",

"Women Chiffon Blouse",


"Women Bow Belt Skirtsuit"
},

{ "Men Cotton Polo Shirt",

"Children Cable-knit Sweater ",


"Children Bear Coverall Cotton",
"Baby three-piece Set ",
"Girls Jeans with Heart Belt "
}
};

double[,] UnitPrice = new double[2, 5]


{
{ 275.25D, 180.05D, 50.00D, 265.35D, 245.55D },
{ 45.55D, 25.65D, 28.25D, 48.55D, 19.95D }
};

Console.WriteLine("Receipt");
Console.WriteLine("Item Number: {0}", ItemID);
Console.WriteLine("Description: {0}", Description);
Console.WriteLine("Unit Price: {0:C}\n", Price);
}
}
}

2. Save the file

Accessing the Members of a Two-Dimensional Array

C# 3.0 Practical Learning 558


To use the members of a two-dimensional array, you can access each item individually.
For example, to initialize a two-dimensional array, you can access each member of the
array and assign it a value. The external list is zero-based. In other words, the first list
has an index of 0, the second list has an index of 1. Internally, each list is zero-based
and behaves exactly like a one-dimensional array. To access a member of the list, type
the name of the variable followed by its square brackets. In the brackets, type the index
of the list, a comma, and the internal index of the member whose access you need. If
you create an array without initializing using the curly brackets, you can use this
technique of accessing the members by the square brackets to initialize each member of
the array. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Members = new string[2,4];

Members[0, 0] = "Celeste"; // Member of the First List


Members[0, 1] = "Mathurin"; // Member of the First List
Members[0, 2] = "Alex"; // Member of the First List
Members[0, 3] = "Germain"; // Member of the First List
Members[1, 0] = "Jeremy"; // Member of the Second List
Members[1, 1] = "Mathew"; // Member of the Second List
Members[1, 2] = "Anselme"; // Member of the Second List
Members[1, 3] = "Frederique"; // Member of the Second List

return 0;
}
}

You can use this same technique to retrieve the value of each member of the array.
Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Members = new string[2,4];

Members[0, 0] = "Celeste"; // Member of the First List


Members[0, 1] = "Mathurin"; // Member of the First List
Members[0, 2] = "Alex"; // Member of the First List
Members[0, 3] = "Germain"; // Member of the First List
Members[1, 0] = "Jeremy"; // Member of the Second List
Members[1, 1] = "Mathew"; // Member of the Second List
Members[1, 2] = "Anselme"; // Member of the Second List
Members[1, 3] = "Frederique"; // Member of the Second List

Console.WriteLine(Members[0, 0]);
Console.WriteLine(Members[0, 1]);
Console.WriteLine(Members[0, 2]);
Console.WriteLine(Members[0, 3]);
Console.WriteLine(Members[1, 0]);
Console.WriteLine(Members[1, 1]);

C# 3.0 Practical Learning 559


Console.WriteLine(Members[1, 2]);
Console.WriteLine(Members[1, 3]);

return 0;
}
}

This would produce:


Celeste
Mathurin
Alex
Germain
Jeremy
Mathew
Anselme
Frederique
Press any key to continue . . .

As we described it earlier, a two-dimensional array is list of two array, or two arrays of


arrays. In order words, the second arrays are nested in the first arrays. In the same
way, if you want to access them using a loop, you can nest one for loop inside of a first
for loop. The external loop accesses a member of the main array and the second loop
accesses the internal list of the current array. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Members = new string[2,4];

Members[0, 0] = "Celeste"; // Member of the First List


Members[0, 1] = "Mathurin"; // Member of the First List
Members[0, 2] = "Alex"; // Member of the First List
Members[0, 3] = "Germain"; // Member of the First List
Members[1, 0] = "Jeremy"; // Member of the Second List
Members[1, 1] = "Mathew"; // Member of the Second List
Members[1, 2] = "Anselme"; // Member of the Second List
Members[1, 3] = "Frederique"; // Member of the Second List

for (int External = 0; External < 2; External++)


for (int Internal = 0; Internal < 4; Internal++)
Console.WriteLine(Members[External, Internal]);

return 0;
}
}

To apply a foreach operator, access only each member of the internal list. Here is an
example:
using System;

public static class Exercise


{
static int Main(string[] args)
{

C# 3.0 Practical Learning 560


var Members = new string[2, 4];

Members[0, 0] = "Celeste"; // Member of the First List


Members[0, 1] = "Mathurin"; // Member of the First List
Members[0, 2] = "Alex"; // Member of the First List
Members[0, 3] = "Germain"; // Member of the First List
Members[1, 0] = "Jeremy"; // Member of the Second List
Members[1, 1] = "Mathew"; // Member of the Second List
Members[1, 2] = "Anselme"; // Member of the Second List
Members[1, 3] = "Frederique"; // Member of the Second List

foreach (var Internal in Members)


Console.WriteLine(Internal);

return 0;
}
}

Practical Learning: Accessing the Members

1. To retrieve the values of a two-dimensional array, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore3
{
public class Program
{
static void Main(string[] args)
{
long ItemID = 0;
string Description = "Unknown";
double Price = 0.00D;

// The first list contains women's items


// The other contains non-women items
long[,] ItemNumber = new long[2, 5]
{
{ 947783, 934687, 973947, 987598, 974937 },
{ 739579, 367583, 743937, 437657, 467945 } };

string[,] ItemName = new string[2, 5]


{
{ "Women Double-faced wool coat",
"Women Floral Silk Tank Blouse",

"Women Push Up Bra",

"Women Chiffon Blouse",


"Women Bow Belt Skirtsuit"
},
{ "Men Cotton Polo Shirt",
"Children Cable-knit Sweater ",
"Children Bear Coverall Cotton",
"Baby three-piece Set ",
C# 3.0 Practical Learning 561
"Girls Jeans with Heart Belt "
}
};

double[,] UnitPrice = new double[2, 5]


{
{ 275.25D, 180.05D, 50.00D, 265.35D, 245.55D },
{ 45.55D, 25.65D, 28.25D, 48.55D, 19.95D }
};

// Order Processing
try
{
Console.Write("Enter Item Number: ");
ItemID = long.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine(
"Invalid Number - The program will terminate\n");
}

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


{
for (int j = 0; j < 5; j++)
{
if (ItemID == ItemNumber[i, j])
{
Description = ItemName[i, j];
Price = UnitPrice[i, j];
}
}
}

Console.WriteLine("Receipt");
Console.WriteLine("Item Number: {0}", ItemID);
Console.WriteLine("Description: {0}", Description);
Console.WriteLine("Unit Price: {0:C}\n", Price);
}
}
}

2. Execute the application and test it. Here is an example:


 
Enter Item Number: 739579
Receipt
Item Number: 739579
Description: Men Cotton Polo Shirt
Unit Price: $45.55

Press any key to continue . . .

3. Close the DOS window

4. Execute the application again and enter a different item number. Here is an
example:
 
Enter Item Number: 273644
C# 3.0 Practical Learning 562
Receipt
Item Number: 273644
Description: Unknown
Unit Price: $0.00

Press any key to continue . . .

5. Close the DOS window

Multidimensional Arrays
 

Introduction

Beyond two dimensions, you can create an array variable that represents various lists,
and each list contains various internal lists, and each internal list contains its own
elements. This is referred to as a multidimensional array. One of the rules you must
follow is that, as always, all members of the array must be of the same type.

Creating a Multidimensional Array

To create a multidimensional array, add as many commas in the square brackets as you
judge them necessary. If you only want to declare the variable without indicating the
actual number of lists, you can specify the data type followed by square brackets and
the commas. Here is an example that represents a three-dimensional array that is not
initialized:
using System;

public static class Exercise


{
static int Main(string[] args)
{
double[,,] Number;

return 0;
}
}

If you know the types of members the array will use, you can use the assignment
operator and specify the numbers of lists in the square brackets. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
double[,,] Number = new double[2, 3, 5];

return 0;
}
}

In this case, you can use the var keyword on the left side of the name of the variable:

C# 3.0 Practical Learning 563


using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = new double[2, 3, 5];

return 0;
}
}

In this example, we are creating 2 groups of items. Each of the two groups is made of
three lists. Each list contains 5 numbers. As a result, the array contains 2 * 3 * 5 = 30
members.

Initializing a Multidimensional Array

As always, there are various ways you can initialize an array. To initialize a
multidimensional array when creating it, you use an opening and a closing curly brackets
for each list but they must be nested. The most external pair of curly brackets
represents the main array. Inside of the main curly brackets, the first nested curly
brackets represent a list of the first dimension. Inside of those brackets, you use another
set curly brackets to represent a list that would be nested. You continue this up to the
most internal array. Then, in that last set, you initialize the members of the array by
specifying their values. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = new double[2, 3, 5]
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};

return 0;
}
}

Access to Members of a Multidimensional Array

To access a member of a multidimensional array, type the name of the array followed by
the opening square bracket, followed by the 0-based first dimension, followed by a

C# 3.0 Practical Learning 564


comma. Continue with each dimension and end with the closing square bracket. You can
use this technique to initialize the array if you had only created it. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = new double[2, 3, 5];

Number[0, 0, 0] = 12.44;
Number[0, 0, 1] = 525.38;
Number[0, 0, 2] = -6.28;
Number[0, 0, 3] = 2448.32;
Number[0, 0, 4] = 632.04;
Number[0, 1, 0] = -378.05;
Number[0, 1, 1] = 48.14;
Number[0, 1, 2] = 634.18;
Number[0, 1, 3] = 762.48;
Number[0, 1, 4] = 83.02;
Number[0, 2, 0] = 64.92;
Number[0, 2, 1] = -7.44;
Number[0, 2, 2] = 86.74;
Number[0, 2, 3] = -534.60;
Number[0, 2, 4] = 386.73;
Number[1, 0, 0] = 48.02;
Number[1, 0, 1] = 120.44;
Number[1, 0, 2] = 38.62;
Number[1, 0, 3] = 526.82;
Number[1, 0, 4] = 1704.62;
Number[1, 1, 0] = 56.85;
Number[1, 1, 1] = 105.48;
Number[1, 1, 2] = 363.31;
Number[1, 1, 3] = 172.62;
Number[1, 1, 4] = 128.48;
Number[1, 2, 0] = 906.68;
Number[1, 2, 1] = 47.12;
Number[1, 2, 2] = -166.07;
Number[1, 2, 3] = 4444.26;
Number[1, 2, 4] = 408.62;

return 0;
}
}

This is the same approach you can use to access each member of the array to check or
retrieve its value. Here are examples:
using System;

public static class Exercise


{
static int Main(string[] args)
{
double[, ,] number = new double[2, 3, 5]
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
C# 3.0 Practical Learning 565
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82,1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12,-166.07, 4444.26, 408.62 }
},
};

Console.WriteLine("Number[0][0][0] = {0}", number[0, 0, 0]);


Console.WriteLine("Number[0][0][1] = {0}", number[0, 0, 1]);
Console.WriteLine("Number[0][0][2] = {0}", number[0, 0, 2]);
Console.WriteLine("Number[0][0][3] = {0}", number[0, 0, 3]);
Console.WriteLine("Number[0][0][4] = {0}\n", number[0, 0, 4]);

Console.WriteLine("Number[0][1][0] = {0}", number[0, 1, 0]);


Console.WriteLine("Number[0][1][1] = {0}", number[0, 1, 1]);
Console.WriteLine("Number[0][1][2] = {0}", number[0, 1, 2]);
Console.WriteLine("Number[0][1][3] = {0}", number[0, 1, 3]);
Console.WriteLine("Number[0][1][4] = {0}\n", number[0, 1, 4]);

Console.WriteLine("Number[0][2][0] = {0}", number[0, 2, 0]);


Console.WriteLine("Number[0][2][1] = {0}", number[0, 2, 1]);
Console.WriteLine("Number[0][2][2] = {0}", number[0, 2, 2]);
Console.WriteLine("Number[0][2][3] = {0}", number[0, 2, 3]);
Console.WriteLine("Number[0][2][4] = {0}\n", number[0, 2, 4]);

Console.WriteLine("Number[1][0][0] = {0}", number[1, 0, 0]);


Console.WriteLine("Number[1][0][1] = {0}", number[1, 0, 1]);
Console.WriteLine("Number[1][0][2] = {0}", number[1, 0, 2]);
Console.WriteLine("Number[1][0][3] = {0}", number[1, 0, 3]);
Console.WriteLine("Number[1][0][4] = {0}\n", number[1, 0, 4]);

Console.WriteLine("Number[1][1][0] = {0}", number[1, 1, 0]);


Console.WriteLine("Number[1][1][1] = {0}", number[1, 1, 1]);
Console.WriteLine("Number[1][1][2] = {0}", number[1, 1, 2]);
Console.WriteLine("Number[1][1][3] = {0}", number[1, 1, 3]);
Console.WriteLine("Number[1][1][4] = {0}\n", number[1, 1, 4]);

Console.WriteLine("Number[1][2][0] = {0}", number[1, 2, 0]);


Console.WriteLine("Number[1][2][1] = {0}", number[1, 2, 1]);
Console.WriteLine("Number[1][2][2] = {0}", number[1, 2, 2]);
Console.WriteLine("Number[1][2][3] = {0}", number[1, 2, 3]);
Console.WriteLine("Number[1][2][4] = {0}\n", number[1, 2, 4]);

return 0;
}
}

This would produce:


Number[0][0][0] = 12.44
Number[0][0][1] = 525.38
Number[0][0][2] = -6.28
Number[0][0][3] = 2448.32
Number[0][0][4] = 632.04

Number[0][1][0] = -378.05
Number[0][1][1] = 48.14
Number[0][1][2] = 634.18
C# 3.0 Practical Learning 566
Number[0][1][3] = 762.48
Number[0][1][4] = 83.02

Number[0][2][0] = 64.92
Number[0][2][1] = -7.44
Number[0][2][2] = 86.74
Number[0][2][3] = -534.6
Number[0][2][4] = 386.73

Number[1][0][0] = 48.02
Number[1][0][1] = 120.44
Number[1][0][2] = 38.62
Number[1][0][3] = 526.82
Number[1][0][4] = 1704.62

Number[1][1][0] = 56.85
Number[1][1][1] = 105.48
Number[1][1][2] = 363.31
Number[1][1][3] = 172.62
Number[1][1][4] = 128.48

Number[1][2][0] = 906.68
Number[1][2][1] = 47.12
Number[1][2][2] = -166.07
Number[1][2][3] = 4444.26
Number[1][2][4] = 408.62

Press any key to continue . . .

Since the lists are nested, if you want to use loops to access the members of the array,
you can nest the for loops to incrementally access the values. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = new double[2, 3, 5];

Number[0, 0, 0] = 12.44;
Number[0, 0, 1] = 525.38;
Number[0, 0, 2] = -6.28;
Number[0, 0, 3] = 2448.32;
Number[0, 0, 4] = 632.04;
Number[0, 1, 0] = -378.05;
Number[0, 1, 1] = 48.14;
Number[0, 1, 2] = 634.18;
Number[0, 1, 3] = 762.48;
Number[0, 1, 4] = 83.02;
Number[0, 2, 0] = 64.92;
Number[0, 2, 1] = -7.44;
Number[0, 2, 2] = 86.74;
Number[0, 2, 3] = -534.60;
Number[0, 2, 4] = 386.73;
Number[1, 0, 0] = 48.02;
Number[1, 0, 1] = 120.44;
Number[1, 0, 2] = 38.62;
Number[1, 0, 3] = 526.82;
Number[1, 0, 4] = 1704.62;
C# 3.0 Practical Learning 567
Number[1, 1, 0] = 56.85;
Number[1, 1, 1] = 105.48;
Number[1, 1, 2] = 363.31;
Number[1, 1, 3] = 172.62;
Number[1, 1, 4] = 128.48;
Number[1, 2, 0] = 906.68;
Number[1, 2, 1] = 47.12;
Number[1, 2, 2] = -166.07;
Number[1, 2, 3] = 4444.26;
Number[1, 2, 4] = 408.62;

for(int Outside = 0; Outside < 2; Outside++)


for(int Inside = 0; Inside < 3; Inside++)
for(int Value = 0; Value < 5; Value++)
Console.WriteLine("Number = {0}",
Number[Outside, Inside, Value]);

return 0;
}
}

This would produce:


Number = 12.44
Number = 525.38
Number = -6.28
Number = 2448.32
Number = 632.04
Number = -378.05
Number = 48.14
Number = 634.18
Number = 762.48
Number = 83.02
Number = 64.92
Number = -7.44
Number = 86.74
Number = -534.6
Number = 386.73
Number = 48.02
Number = 120.44
Number = 38.62
Number = 526.82
Number = 1704.62
Number = 56.85
Number = 105.48
Number = 363.31
Number = 172.62
Number = 128.48
Number = 906.68
Number = 47.12
Number = -166.07
Number = 4444.26
Number = 408.62
Press any key to continue . . .

To make the result easier to read, we could use code as follows:


using System;

public static class Exercise

C# 3.0 Practical Learning 568


{
static int Main(string[] args)
{
var Number = new double[2, 3, 5];

. . . No Change

for(int Outside = 0; Outside < 2; Outside++)


for(int Inside = 0; Inside < 3; Inside++)
for (int Value = 0; Value < 5; Value++)
{
Console.WriteLine("Number[{0}][{1}][{2}] = {3}",
Outside, Inside, Value, Number[Outside, Inside,
Value]);

if (Value % 5 == 0)
Console.WriteLine();
}

return 0;
}
}

To use a foreach operator, access only each member to get to it. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[2, 3, 5];

. . . No Change

foreach (var Value in Numbers)


Console.WriteLine("Number: {0}", Value);

return 0;
}
}

Multidimensional Arrays and Classes


 

Introduction

Like an array of a primitive type, a multidimensional array can be made a field of a class.
You can primarily declare it without initializing it. Here is an example:
public class TriangleInCoordinateSystem
{
private int[,] Points;
}

This indicates a two-dimensional array field: the array will contain two lists but we don't
know (yet) how many members each array will contain. Therefore, if you want, when

C# 3.0 Practical Learning 569


creating the array, you can specify its dimension by assigning it a second pair of square
brackets using the new operator and the data type. Here is an example:
public class TriangleInCoordinateSystem
{
private int[,] Points = new int[3, 2];
}

You can also use a method of the class or a constructor to indicate the size of the array.
Here is an example:
public class TriangleInCoordinateSystem
{
private int[,] Points;

public TriangleInCoordinateSystem()
{
Points = new int[3, 2];
}
}

To initialize the array, you can access each member using the square brackets as we
saw in the previous sections. Here is an example:
public class TriangleInCoordinateSystem
{
private int[,] Points;

public TriangleInCoordinateSystem()
{
Points = new int[3, 2];

Points[0, 0] = -2; // A(x, )


Points[0, 1] = -3; // A( , y)
Points[1, 0] = 5; // B(x, )
Points[1, 1] = 1; // B( , y)
Points[2, 0] = 4; // C(x, )
Points[2, 1] = -2; // C( , y)
}
}

After initializing the array, you can use it as you see fit. For example, you can display its
values to the user. Here is an example:
using System;

public class TriangleInCoordinateSystem


{
private int[,] Points;

public TriangleInCoordinateSystem()
{
Points = new int[3, 2];

Points[0, 0] = -2; // A(x, )


Points[0, 1] = -3; // A( , y)
Points[1, 0] = 5; // B(x, )
Points[1, 1] = 1; // B( , y)
Points[2, 0] = 4; // C(x, )
Points[2, 1] = -2; // C( , y)
C# 3.0 Practical Learning 570
}

public void ShowPoints()


{
Console.WriteLine("Coordinates of the Triangle");
Console.WriteLine("A({0}, {1})", Points[0, 0], Points[0, 1]);
Console.WriteLine("B({0}, {1})", Points[1, 0], Points[1, 1]);
Console.WriteLine("C({0}, {1})", Points[2, 0], Points[2, 1]);
}
}

public static class Exercise


{
static int Main(string[] args)
{
var Triangle = new TriangleInCoordinateSystem();

Triangle.ShowPoints();

return 0;
}
}

This would produce:


Coordinates of the Triangle
A(-2, -3)
B(5, 1)
C(4, -2)
Press any key to continue . . .

A Multidimensional Array as Argument

A multidimensional array can be passed as argument. When creating the method, in its
parentheses, enter the data type followed by the square brackets. In the square
brackets, enter one comma for a two-dimensional array, two or more commas, as
necessary, for a three-dimensional arrays as necessary. Here is an example:
public class TriangleInCoordinateSystem
{
public void ShowPoints(int[,] Coords)
{
}
}

When defining the method, in its body, you can use the array as you see fit, such as
displaying its values. Here is an example:
public class TriangleInCoordinateSystem
{
public void ShowPoints(int[,] Coords)
{
Console.WriteLine("Coordinates of the Triangle");
Console.WriteLine("A({0}, {1})", Coords[0, 0], Coords[0, 1]);
Console.WriteLine("B({0}, {1})", Coords[1, 0], Coords[1, 1]);
Console.WriteLine("C({0}, {1})", Coords[2, 0], Coords[2, 1]);
}
}

C# 3.0 Practical Learning 571


To call this type of method, pass only the name of the array.

As indicated with one-dimensional arrays, when passing an multi-dimensional array


argument, the array is treated as a reference. This makes it possible for the method to
modify the array and return it changed. If you want to indicate that the array is passed by
reference, you can precede its name in the parentheses by the the ref keyword. Here is
an example:
using System;

public class TriangleInCoordinateSystem


{
private int[,] Points;

public void CreateTriangle(ref int[,] Points)


{

Points[0, 0] = -2; // A(x, )


Points[0, 1] = -3; // A( , y)
Points[1, 0] = 5; // B(x, )
Points[1, 1] = 1; // B( , y)
Points[2, 0] = 4; // C(x, )
Points[2, 1] = -2; // C( , y)
}

public void ShowPoints(int[,] Coords)


{
Console.WriteLine("Coordinates of the Triangle");
Console.WriteLine("A({0}, {1})", Coords[0, 0], Coords[0, 1]);
Console.WriteLine("B({0}, {1})", Coords[1, 0], Coords[1, 1]);
Console.WriteLine("C({0}, {1})", Coords[2, 0], Coords[2, 1]);
}
}

public static class Exercise


{
static int Main(string[] args)
{
var Coordinates = new int[3, 2];

var Triangle = new TriangleInCoordinateSystem();

Triangle.CreateTriangle(ref Coordinates);
Triangle.ShowPoints(Coordinates);

return 0;
}
}

Returning a Multi-Dimensional Array

You can return a multi-dimensional array from a method. When creating the method,
before its name, specify the data type followed by square brackets. In the square
brackets, enter the necessary number of commas. Here is an example:
using System;

public class TriangleInCoordinateSystem


C# 3.0 Practical Learning 572
{
public int[,] CreateTriangle()
{
}
}

In the body of the method, you can do what you want but, before exiting it, you must
return an array of the same type that was created. When calling the method, you can
assign it to an array of the same type it returns. Here is an example:
using System;

public class TriangleInCoordinateSystem


{
public int[,] CreateTriangle()
{
var Points = new int[3,2];

Points[0, 0] = 6; // A(x, )
Points[0, 1] = 1; // A( , y)
Points[1, 0] = 2; // B(x, )
Points[1, 1] = 3; // B( , y)
Points[2, 0] = 1; // C(x, )
Points[2, 1] = 4; // C( , y)

return Points;
}

public void ShowPoints(int[,] Coords)


{
Console.WriteLine("Coordinates of the Triangle");
Console.WriteLine("A({0}, {1})", Coords[0, 0], Coords[0, 1]);
Console.WriteLine("B({0}, {1})", Coords[1, 0], Coords[1, 1]);
Console.WriteLine("C({0}, {1})", Coords[2, 0], Coords[2, 1]);
}
}

public static class Exercise


{
static int Main(string[] args)
{
var Coordinates = new int[3, 2];

var Triangle = new TriangleInCoordinateSystem();

Coordinates = Triangle.CreateTriangle();
Triangle.ShowPoints(Coordinates);

return 0;
}
}

This would produce:


Coordinates of the Triangle
A(6, 1)
B(2, 3)
C(1, 4)
Press any key to continue . . .

C# 3.0 Practical Learning 573


A Multidimensional Array of Objects
 

A Variable of a Multidimensional Array of Objects

As done for primitive data types, you can create a multi-dimensional array where each
member is of a class type. Of course you can use an existing class or you must first
create a class. Here is an example:
public class Point
{
private int XCoord;
private int YCoord;

public int x
{
get { return XCoord; }
set { XCoord = value; }
}

public int y
{
get { return YCoord; }
set { YCoord = value; }
}
}

To create a multidimensional array of objects without initializing it, you can use the
following formula:
ClassName[,] VariableName;

If you know the number of instances of the class that the array will use, you can use the
following formula:
ClassName[,] VariableName = new ClassName[Number1,Number2];

Or you can use the var keyword in the following formula:


var VariableName = new DataType[Number1,Number2];

The ClassName factor is the name of the class that will make up each member of the
array. The other sections follow the same rules we reviewed for the primitive types. For
example, you can create an array without allocating memory for it as follows:
public static class Exercise
{
static int Main(string[] args)
{
Point[,] Line;

return 0;
}
}

C# 3.0 Practical Learning 574


If you know the number of members that the array will contain, you can use the right
pair of square brackets, in which case you can specify the name of the class or use the
var keyword and omit the left square brackets. Here is an example:

public static class Exercise


{
static int Main(string[] args)
{
var Line = new Point[2, 2];

return 0;
}
}

This declaration creates a two-dimensional array of two Point objects: The array
contains two lists and each list contains two Points.

To initialize a multidimensional array of objects, you can access each array member
using its index, allocate memory for it using the new operator. After allocating memory
for the member, you can then access its fields or properties to initialize it. Here is an
example:
using System;

public class Point


{
private int XCoord;
private int YCoord;

public int x
{
get { return XCoord; }
set { XCoord = value; }
}

public int y
{
get { return YCoord; }
set { YCoord = value; }
}
}

public static class Exercise


{
static int Main(string[] args)
{
var Line = new Point[2, 2];

Line[0, 0] = new Point(); // First Point A


Line[0, 0].x = -3; // A(x, )
Line[0, 0].y = 8; // A( , y)
Line[0, 1] = new Point(); // Second Point B
Line[0, 1].x = 4; // B(x, )
Line[0, 1].y = -5; // B( , y)

return 0;
}
}

C# 3.0 Practical Learning 575


You can also initialize the array when creating it. Before doing this, you would need a
constructor of the class and the constructor must take the argument(s) that would be
used to initialize each member of the array. To actually initialize the array, you would
need a pair of external curly brackets for the main array. Inside of the external curly
brackets, create a pair of curly brackets for each sub-dimension of the array. Inside the
last curly brackets, use the new operator to access an instance of the class and call its
constructor to specify the values of the instance of the class. Here is an example:
public class Point
{
private int XCoord;
private int YCoord;

public Point()
{
}

public Point(int X, int Y)


{
XCoord = X;
YCoord = Y;
}

public int x
{
get { return XCoord; }
set { XCoord = value; }
}

public int y
{
get { return YCoord; }
set { YCoord = value; }
}
}

public static class Exercise


{
static int Main(string[] args)
{
var Line = new Point[,]
{
{
new Point(-3, 8),
new Point(4, -5)
}
};

return 0;
}
}

Accessing the Members of a Multidimensional Array of Objects

To access the members of a multidimensional array of objects, apply the square


brackets to a particular member of the array and access the desired field or property of
the class. Here is an example:
C# 3.0 Practical Learning 576
public static class Exercise
{
public static int Main(string[] args)
{
var Line = new Point[,]
{
{
new Point(-3, 8), new Point(4, -5)
}
};

Console.WriteLine("Line =-=");
Console.WriteLine("From A({0}, {1}) to B({2}, {3})",
Line[0, 0].x, Line[0, 0].y,
Line[0, 1].x, Line[0, 1].y);
return 0;
}
}

This would produce:


Line =-=
From A(-3, 8) to B(4, -5)
Press any key to continue . . .

You can also use a loop to access the members of the array. To do this, create a first
for loop that stops at the first dimension of the array - 1. Then, inside of a first for
loop, nest a for loop for each subsequent dimension. Here is an example:
public static class Exercise
{
public static int Main(string[] args)
{
var Line = new Point[,]
{
{
new Point(-3, 8), new Point(4, -5)
}
};

Console.WriteLine("The points of the line are:");


for(int i = 0; i < 1; i++)
for(int j = 0; j < 2; j++)
Console.Write("({0}, {1})",
Line[i, j].x, Line[i, j].y);
return 0;
}
}

This would produce:


The points of the line are:
(-3, 8)
(4, -5)
Press any key to continue . . .

To apply a foreach operator, access only each member of the internal list. Here is an
example:
public static class Exercise
C# 3.0 Practical Learning 577
{
static int Main(string[] args)
{
var Line = new Point[,]
{
{
new Point(-3, 8), new Point(4, -5)
}
};

Console.WriteLine("The points of the line are:");


foreach (Point pt in Line)
Console.WriteLine("({0}, {1})", pt.x, pt.y);

return 0;
}
}

Multidimensional Arrays of Objects and Classes


 

Introduction

As done for primitive types, a multidimensional array of objects can be made a field of a
class. You can declare the array without specifying its size. Here is an example:
public class Triangle
{
public Point[,] Vertices;
}

If you know the dimensions that the array will have, you can specify them using the new
operator at the same time you are creating the field. Here is an example:
public class Triangle
{
public Point[,] Vertices = new Point[3,2];
}

This creation signals a multidimensional array of Point objects. It will consist of three
lists and each list will contain two Point objects

To initialize the array, access each member by its index to allocate memory for it. Once
you get the member, you access each one of its fields or properties and initialize it with
the desired value. Here is an example:
public class Triangle
{
public Point[,] Vertices = new Point[3, 2];

public Triangle()
{
Vertices[0, 0] = new Point(); // Point A(x, y)
Vertices[0, 0].x = -2; // A(x, )
Vertices[0, 0].y = -4; // A( , y)
Vertices[1, 0] = new Point(); // Point B(x, y)
Vertices[1, 0].x = 3; // B(x, )

C# 3.0 Practical Learning 578


Vertices[1, 0].y = 5; // B( , y)
Vertices[2, 0] = new Point(); // Point C(x, y)
Vertices[2, 0].x = 6; // C(x, )
Vertices[2, 0].y = -2; // C( , y)
}
}

If the class is equipped with the right constructor, you can use it to initialize each
member of the array.

Once the array is ready, you can access each members using its index and manipulate
it. For example you can display its value(s) to the user. Here is an example:
using System;

public class Point


{
private int XCoord;
private int YCoord;

public Point()
{
}

public Point(int X, int Y)


{
XCoord = X;
YCoord = Y;
}

public int x
{
get { return XCoord; }
set { XCoord = value; }
}

public int y
{
get { return YCoord; }
set { YCoord = value; }
}
}

public class Triangle


{
public Point[,] Vertices = new Point[3, 2];

public Triangle()
{
Vertices[0, 0] = new Point(); // Point A(x, y)
Vertices[0, 0].x = -2; // A(x, )
Vertices[0, 0].y = -4; // A( , y)
Vertices[1, 0] = new Point(); // Point B(x, y)
Vertices[1, 0].x = 3; // B(x, )
Vertices[1, 0].y = 5; // B( , y)
Vertices[2, 0] = new Point(); // Point C(x, y)
Vertices[2, 0].x = 6; // C(x, )
Vertices[2, 0].y = -2; // C( , y)
}

C# 3.0 Practical Learning 579


public void Identify()
{
Console.Write("Triangle Vertices: ");
Console.WriteLine("A({0}, {1}), B({2}, {3}), and C({4}, {5})",
Vertices[0, 0].x, Vertices[0, 0].y,
Vertices[1, 0].x, Vertices[1, 0].y,
Vertices[2, 0].x, Vertices[2, 0].y);
}
}

public static class Exercise


{
static int Main(string[] args)
{
Triangle Tri = new Triangle();
Tri.Identify();

return 0;
}
}

This would produce:


Triangle Vertices: A(-2, -4), B(3, 5), and C(6, -2)
Press any key to continue . . .

Passing a Multidimensional Array of Objects

You can pass a multidimensional array of objects as arguments. To do this, in the


parentheses of the method, enter the class name followed by the square brackets. In
the square brackets, type the appropriate number of commas. Here is an example:
public class Triangle
{
public void Create(Point[,] Points)
{
}
}

In the body of the method, use the array as you we have done so far. You can access its
members to get to its values. Here are examples:
public class Triangle
{
public void Create(Point[,] Points)
{
Points[0, 0] = new Point(); // Point A(x, y)
Points[0, 0].x = -2; // A(x, )
Points[0, 0].y = -4; // A( , y)
Points[1, 0] = new Point(); // Point B(x, y)
Points[1, 0].x = 3; // B(x, )
Points[1, 0].y = 5; // B( , y)
Points[2, 0] = new Point(); // Point C(x, y)
Points[2, 0].x = 6; // C(x, )
Points[2, 0].y = -2; // C( , y)
}

public void Identify(Point[,] Coordinate)


{
C# 3.0 Practical Learning 580
Console.Write("Triangle Vertices: ");
Console.WriteLine("A({0}, {1}), B({2}, {3}), and C({4}, {5})",
Coordinate[0, 0].x, Coordinate[0, 0].y,
Coordinate[1, 0].x, Coordinate[1, 0].y,
Coordinate[2, 0].x, Coordinate[2, 0].y);
}
}

public static class Exercise


{
static int Main(string[] args)
{
Triangle Tri = new Triangle();
Point[,] Vertices = new Point[3, 2];

Tri.Create(Vertices);
Tri.Identify(Vertices);

return 0;
}
}

Remember that an array passed as argument is in fact passed by reference. You can
indicate this by preceding it with the ref keyword.

Returning a Multidimensional Array of Objects

A method can return a multidimensional array of objects. If you are creating the
method, before its name, type the name of the class followed by square brackets. Inside
the square brackets, type the desired number of commas to indicate the dimension of
the returned value. Here is an example:
public class Triangle
{
public Point[,] Create()
{
}
}

After implementing the method, before exiting it, make sure it returns the type of array
that it was indicated to produce. Here is an example:
using System;

public class Point


{
private int XCoord;
private int YCoord;

public Point()
{
}

public Point(int X, int Y)


{
XCoord = X;
YCoord = Y;
}

C# 3.0 Practical Learning 581


public int x
{
get { return XCoord; }
set { XCoord = value; }
}

public int y
{
get { return YCoord; }
set { YCoord = value; }
}
}

public class Triangle


{
public Point[,] Create()
{
var Points = new Point[3, 2];

Points[0, 0] = new Point(); // Point A(x, y)


Points[0, 0].x = -2; // A(x, )
Points[0, 0].y = -4; // A( , y)
Points[1, 0] = new Point(); // Point B(x, y)
Points[1, 0].x = 3; // B(x, )
Points[1, 0].y = 5; // B( , y)
Points[2, 0] = new Point(); // Point C(x, y)
Points[2, 0].x = 6; // C(x, )
Points[2, 0].y = -2; // C( , y)

return Points;
}

public void Identify(Point[,] Coordinate)


{
Console.Write("Triangle Vertices: ");
Console.WriteLine("A({0}, {1}), B({2}, {3}), and C({4}, {5})",
Coordinate[0, 0].x, Coordinate[0, 0].y,
Coordinate[1, 0].x, Coordinate[1, 0].y,
Coordinate[2, 0].x, Coordinate[2, 0].y);
}
}

public static class Exercise


{
static int Main(string[] args)
{
Triangle Tri = new Triangle();
Point[,] Vertices = Tri.Create();
Tri.Identify(Vertices);

return 0;
}
}

Introduction to Jagged Arrays


 

C# 3.0 Practical Learning 582


Introduction

A jagged array is an array of arrays, or an array of arrays of arrays, etc. To create a


jagged array, use a combination of square brackets for each dimension. The formula
used is:
DataType[][] VariableName;

Each of the square brackets is used in any of the ways we have introduced arrays so far.
This means that the first square bracket can be used as its own one-dimensional array
or as a multi-dimensional array. Here is an example:
string[2][5] Members;

This declares a variable that represents two arrays and each array internally contains 5
arrays. Because each pair of square brackets is its own array, it can be used to create its
own array with its own multidimensional array. Here is an example that creates a
multidimensional array in the first dimension:
string[2,4][5] Members;

In the same way, the second square bracket can be used as a single or a
multidimensional array. Here is an example:
string[2,4][5,12,8] Members;

Practical Learning: Introducing Jagged Arrays

1. Create a new Console Application named DepartmentStore4

2. Change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore4
{
public class Program
{
static int Main(string[] args)
{
long ItemID = 0;
string Description = "Unknown";
double Price = 0.00D;

Console.WriteLine("Receipt");
Console.WriteLine("Item Number: {0}", ItemID);
Console.WriteLine("Description: {0}", Description);
Console.WriteLine("Unit Price: {0:C}\n", Price);
}
}
}

3. Execute the application to see the result. This would produce:


 
C# 3.0 Practical Learning 583
Receipt
Item Number: 0
Description: Unknown
Unit Price: $0.00

4. Close the DOS window

Initialization of a Jagged Array

When declaring a jagged array, you can allocate memory for it using the new operator
followed by the data type of the array and the same combination of square brackets
used to the left of the assignment operator. The first pair of square brackets on the right
side of the assignment operator must contain the external dimension of the array. The
second pair of square brackets must be left empty. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
string[][] Members = new string[2][];
return 0;
}
}

To initialize a jagged array, when declaring the variable, on the right side of the second
pair of square brackets, provide an opening and a closing curly brackets, then create
each list in its own pair of curly brackets. At the beginning of each list, you must allocate
memory for the list with the new operator. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
string[][] Members = new string[2][]{
new string[]{"Celeste", "Mathurin", "Alex", "Germain"},
new string[]{"Jeremy", "Mathew", "Anselme",
"Frederique"} };

return 0;
}
}

If you initialize the array this way, you can omit specifying the dimension of the external
array. With a jagged array, you can also initialize its internal array individually. To do
this, access each internal array by its zero-based index. Here is an example:
public class Exercise
{
static int Main(string[] args)
{
string[][] Members = new string[2][];

Members[0] = new string[]{"Celeste", "Mathurin", "Alex",


"Germain"};
C# 3.0 Practical Learning 584
Members[1] = new string[]{"Jeremy", "Mathew", "Anselme",
"Frederique"};

return 0;
}
}

Practical Learning: Initializing a Jagged Array

1. To declare and initialize jagged arrays, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore4
{
public class Program
{
static int Main(string[] args)
{
long ItemID = 0;
string Description = "Unknown";
double Price = 0.00D;

// Each of the following variable


// arrays is structured as [2][2][4].
// Each variable represents:
// A/ Two major lists: The first major
// list represents women items,
// the second major list represents men items,
// B/ Two minor lists.
// Each of the major lists contains two minor lists:
// a/ The first minor list of the first major
// list contains adult women items
// The second minor list of the first major
// list contains girls items
// b/ The first minor list of the second major
// list contains adult men items
// The second minor list of the
// second major list contains boys items
// C/ Each minor list contains four items

long[][][] ItemNumber =
new long[][][]
{
new long[][]
{
new long[]{947783, 934687, 973947, 987598, 974937},
new long[]{743765, 747635, 765473, 754026, 730302}
},
new long[][]
{
new long[]{209579, 267583, 248937, 276057, 267945},
new long[]{ 409579, 467583, 448937, 476057, 467945}
}
};
C# 3.0 Practical Learning 585
string[][][] ItemName =
new string[][][]
{
new string[][]
{
new string[]
{
"Double-faced wool coat",
"Floral Silk Tank Blouse",
"Push Up Bra",
"Chiffon Blouse",
"Bow Belt Skirtsuit"
},
new string[]
{
"Cable-knit Sweater",
"Jeans with Heart Belt",
"Fashionable mini skirt",
"Double Dry Pants",
"Romantic Flower Dress"
}
},
new string[][]
{
new string[]
{
"Cotton Polo Shirt",
"Pure Wool Cap",
"Striped Cotton Shirt",
"Two-Toned Ribbed Crewneck",
"Chestnut Italian Shoes"
},
new string[]
{
"Under Collar and Placket Jacket",
"Country Coat Rugged Wear",
"Carpenter Jeans",
"Double-Cushion Tennis Shoes",
"Stitched Center-Bar Belt"
}
}
};

double[][][] UnitPrice =
new double[2][][]
{
new double[][]
{
new double[]
{ 275.25, 180.00, 50.00, 265.00, 245.55 },
new double[]
{ 45.55, 25.65, 34.55, 28.55, 24.95 }
},
new double[][]
{
new double[]
{ 45.75, 25.00, 65.55, 9.75, 165.75 },
new double[]
{ 265.15, 35.55, 24.95, 48.75, 32.50 }
C# 3.0 Practical Learning 586
}
};

Console.WriteLine("Receipt");
Console.WriteLine("Item Number: {0}", ItemID);
Console.WriteLine("Description: {0}", Description);
Console.WriteLine("Unit Price: {0:C}\n", Price);
}
}
}

2. Save the file

Access to Members of a Jagged Array

As done for a multidimensional array, each member of a jagged array can be accessed
with a multiple index, depending on how the array was created. Both the external and
the internal lists are zero-based. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
string[][] Members = new string[2][];

Members[0] = new string[]{"Celeste", "Mathurin", "Alex",


"Germain"};
Members[1] = new string[]{"Jeremy", "Mathew", "Anselme",
"Frederique"};

Console.WriteLine("Member 1: {0}", Members[0][0]);


Console.WriteLine("Member 2: {0}", Members[0][1]);
Console.WriteLine("Member 3: {0}", Members[0][2]);
Console.WriteLine("Member 4: {0}", Members[0][3]);
Console.WriteLine("Member 5: {0}", Members[0][0]);
Console.WriteLine("Member 6: {0}", Members[1][1]);
Console.WriteLine("Member 7: {0}", Members[1][2]);
Console.WriteLine("Member 8: {0}\n", Members[1][3]);

return 0;
}
}

This would produce:


Member 1: Celeste
Member 2: Mathurin
Member 3: Alex
Member 4: Germain
Member 5: Celeste
Member 6: Mathew
Member 7: Anselme
Member 8: Frederique

Press any key to continue . . .

You can also use some loops to access each member of the array. Here is an example:
C# 3.0 Practical Learning 587
using System;

public static class Exercise


{
static int Main(string[] args)
{
string[][] Members = new string[2][];

Members[0] = new string[] { "Celeste", "Mathurin", "Alex",


"Germain" };
Members[1] = new string[] { "Jeremy", "Mathew", "Anselme",
"Frederique" };

for (int External = 0; External < 2; External++)


for (int Internal = 0; Internal < 4; Internal++)
Console.WriteLine("Name: {0}", Members[External]
[Internal]);

return 0;
}
}

 If you want to use a foreach operator, you must access each array by its index. The
external array can be accessed using a-zero based index and remember that you are
accessing a whole array. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
string[][] Members = new string[2][];

Members[0] = new string[] { "Celeste", "Mathurin", "Alex",


"Germain" };
Members[1] = new string[] { "Jeremy", "Mathew", "Anselme",
"Frederique" };

foreach (string Name in Members[0])


Console.WriteLine("Member: {0}", Name);

return 0;
}
}

This would produce:


Member: Celeste
Member: Mathurin
Member: Alex
Member: Germain
Press any key to continue . . .

To access the second array, apply its index as ArrayName[1].

Practical Learning: Using a Jagged Array

C# 3.0 Practical Learning 588


1. To process the members of a jagged array, make the following changes to the file:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DepartmentStore4
{
public class Program
{
static int Main(string[] args)
{
long ItemID = 0;
string Description = "Unknown";
double Price = 0.00D;
string Category = "Category";

// Each of the following variable


// arrays is structured as [2][2][4].
// Each variable represents:
// A/ Two major lists: The first major
// list represents women items,
// the second major list represents men items,
// B/ Two minor lists.
// Each of the major lists contains two minor lists:
// a/ The first minor list of the first major
// list contains adult women items
// The second minor list of the first major
// list contains girls items
// b/ The first minor list of the second major
// list contains adult men items
// The second minor list of the
// second major list contains boys items
// C/ Each minor list contains four items

long[][][] ItemNumber =
new long[][][]
{
new long[][]
{
new long[]{947783, 934687, 973947, 987598, 974937},
new long[]{743765, 747635, 765473, 754026, 730302}
},
new long[][]
{
new long[]{209579, 267583, 248937, 276057, 267945},
new long[]{ 409579, 467583, 448937, 476057, 467945}
}
};

string[][][] ItemName =
new string[][][]
{
new string[][]
{
new string[]
{
"Double-faced wool coat",
C# 3.0 Practical Learning 589
"Floral Silk Tank Blouse",
"Push Up Bra",
"Chiffon Blouse",
"Bow Belt Skirtsuit"
},
new string[]
{
"Cable-knit Sweater",
"Jeans with Heart Belt",
"Fashionable mini skirt",
"Double Dry Pants",
"Romantic Flower Dress"
}
},
new string[][]
{
new string[]
{
"Cotton Polo Shirt",
"Pure Wool Cap",
"Striped Cotton Shirt",
"Two-Toned Ribbed Crewneck",
"Chestnut Italian Shoes"
},
new string[]
{
"Under Collar and Placket Jacket",
"Country Coat Rugged Wear",
"Carpenter Jeans",
"Double-Cushion Tennis Shoes",
"Stitched Center-Bar Belt"
}
}
};

double[][][] UnitPrice =
new double[2][][]
{
new double[][]
{
new double[]
{ 275.25, 180.00, 50.00, 265.00, 245.55 },
new double[]
{ 45.55, 25.65, 34.55, 28.55, 24.95 }
},
new double[][]
{
new double[]
{ 45.75, 25.00, 65.55, 9.75, 165.75 },
new double[]
{ 265.15, 35.55, 24.95, 48.75, 32.50 }
}
};

// Order Processing
try
{
Console.Write("Enter Item Number: ");
ItemID = long.Parse(Console.ReadLine());
}
C# 3.0 Practical Learning 590
catch (FormatException)
{
Console.WriteLine(
"Invalid Number - The program will terminate\n");
}

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


{
for (int j = 0; j < 2; j++)
{
for (int k = 0; k < 5; k++)
{
if (ItemID == ItemNumber[i][j][k])
{
Description = ItemName[i][j][k];
Price = UnitPrice[i][j][k];

if (ItemID >= 900000)


Category = "Women";
else if (ItemID >= 700000)
Category = "Girls";
else if (ItemID >= 400000)
Category = "Boys";
else
Category = "Men";
}
}
}
}

Console.WriteLine("Receipt");
Console.WriteLine("Item Number: {0}", ItemID);
Console.WriteLine("Description: {0}", Description);
Console.WriteLine("Unit Price: {0:C}\n", Price);
}
}
}

2. Execute the application and test it. Here is an example:


 
Enter Item Number: 448937
Receipt
Item Number: 448937
Category: Boys
Description: Carpenter Jeans
Unit Price: $24.95

Press any key to continue . . .

3. Close the DOS window

C# 3.0 Practical Learning 591


C# 3.0 Practical Learning 592
The Array Class
 

Introduction to the Array Class


 

Overview

In the previous lessons, we saw how to create and initialize arrays. To assist with the
use and management of arrays, you can combine the array features of the C#
language and support from the .NET Framework. To support arrays, the .NET
Framework provides a class of the same name. The Array class is defined in the System
namespace of the System.dll assembly.

When you create an array, you are in fact declaring a variable of type Array. Based on
this, since an array variable is an object of a class type, you can use the characteristics
of the Array class to create an array and/or to manipulate the values stored in the
variable. You can create an array using any of the techniques we saw in the previous
lessons, or you can use the Array class.

To assist you with creating an array, the Array class is equipped with the
CreateInstance() method that comes in various versions. To create a one-dimensional
array whose members are zero-based, you can use the following version:
public static Array CreateInstance(Type elementType, int length);

The first argument is used to specify the type of array you want to create. Since it is
declared as Type, you can use the typeof operator to cast your type.

The second argument specifies the number of members of the array. Using the Array
class, you can create an array as follows:
using System;

public class Exercise


{
static int Main(string[] args)
{
Array Numbers = Array.CreateInstance(typeof(double), length);

return 0;
}
}

You can also use the var keyword to declare the variable:
using System;

C# 3.0 Practical Learning 593


public class Exercise
{
static int Main(string[] args)
{
var Numbers = Array.CreateInstance(typeof(double), length);

return 0;
}
}

The Length of an Array

We saw that if you declare a variable for an array but don't initialize it, you must specify
the number of elements of the array. This number is passed inside the second pair of
square brackets, as a constant integer. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[5];

return 0;
}
}

If you use the Array class to create an array, you must pass this constant integer as the
second argument of the CreateInstance() method from the the above version. Here is
an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = Array.CreateInstance(typeof(double), 5);

return 0;
}
}

If the array exists already, that is, if you have already created the array or you are using
an array created by someone else, to find out the number of items it contains, you can
access its Length property. Therefore, the length of an array is the number of elements
it contains.

Alternatively, you can call the Array.GetLength() method. Its syntax is:
public int GetLength(int dimension);

For a one-dimensional array, you must pass the argument as 0. This method returns a
32-bit integer that represents the number of items in the array.

 
C# 3.0 Practical Learning 594
The Rank of an Array

We have seen that the square brackets are used to specify that you are declaring an
array. If you are creating a one-dimensional array, we saw that you could type a
number in the square bracket. If you are creating a two-dimensional array, you type two
numbers separated by a comma in the second pair of square brackets. Each number,
whether it is one, two, or more is a placeholder for what is referred to a dimension. In
other words, a one dimensional array has a dimension of one. A two-dimensional array
has a dimension of 2.

To find out the dimension of an array, the Array class provides the Rank property.
Therefore, to know the dimension of an existing array, you can access its Rank.

Fundamental Operations on an Array


 

Adding Items to an Array

Before using a class, it must have values or members in it. In the previous lesson, we
saw that, to initialize an array, you open the curly brackets and list its members
separated by commas, or you could access each member and assign it the desired
value. To support the ability to add members to an array, the Array is equipped with a
method named SetValue() that comes in different versions. To add a new item to a
the type of array we have used so far, you can call the following version of the
Array.SetValue() method:

public void SetValue(object value, int index);

The first argument is the value to add to the list. The second argument is the index of
the member to be added. The first item has index 1; the second item has index 2, and
so on. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = Array.CreateInstance(typeof(double), 5);

Numbers.SetValue(7628.937, 0);
Numbers.SetValue(6.48, 1);
Numbers.SetValue(574.9, 2);
Numbers.SetValue(293749.064, 3);
Numbers.SetValue(0.70257, 4);

return 0;
}
}

We indicated that whenever you create an array, you are in fact declaring an instance of
the Array class. Therefore, even if you create an array using the square bracket formula

C# 3.0 Practical Learning 595


we used in the previous lesson, you can call the SetValue() method to specify any
member of the array. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[5];

Numbers.SetValue(7628.937, 0);
Numbers.SetValue(6.48, 1);
Numbers.SetValue(574.9, 2);
Numbers.SetValue(293749.064, 3);
Numbers.SetValue(0.70257, 4);

return 0;
}
}

The Array class provides a SetValue() version for each corresponding


CreateInstance() method we reviewed earlier.

Accessing the Members of an Array

Once the array is initialized, you can access its members and do what you want with
their values. To support the ability to retrieve the value of a member of an array, the
Array class is equipped with a method named GetValue that is overloaded with a
version corresponding to each version of the CreateInstance() and the SetValue()
methods. For example, to access the values stored in a one-dimensional array, you can
call call this version:
public object GetValue(int index);

The index argument is the zero-based index of the member whose value you want to
access. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[5];

Numbers.SetValue(7628.937, 0);
Numbers.SetValue(6.48, 1);
Numbers.SetValue(574.9, 2);
Numbers.SetValue(293749.064, 3);
Numbers.SetValue(0.70257, 4);

Console.WriteLine("Number: {0}", Numbers.GetValue(0));

return 0;
}
}

C# 3.0 Practical Learning 596


When calling the Array.GetValue() method, if you pass an invalid value, the compiler
would throw an IndexOutOfRangeException exception.

Just as you can access one member of the array, you can access any member using its
index. Here is an example that uses a for loop and the Length property to know the
number of members of an array:
using System;

public class Exercise


{
static int Main(string[] args)
{
//var Numbers = Array.CreateInstance(typeof(double), 5);
var Numbers = new double[5];

Numbers.SetValue(7628.937, 0);
Numbers.SetValue(6.48, 1);
Numbers.SetValue(574.9, 2);
Numbers.SetValue(293749.064, 3);
Numbers.SetValue(0.70257, 4);

for(int i = 0; i < Numbers.Length; i++)


Console.WriteLine("Number: {0}", Numbers.GetValue(i));

return 0;
}
}

If using the foreach operator, you don't need the GetValue() method. Here is an
example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[5];

Numbers.SetValue(7628.937, 0);
Numbers.SetValue(6.48, 1);
Numbers.SetValue(574.9, 2);
Numbers.SetValue(293749.064, 3);
Numbers.SetValue(0.70257, 4);

foreach(var Number in Numbers)


Console.WriteLine("Number: {0}", Number);

return 0;
}
}

Multidimensional Arrays
 

Two-Dimensional Arrays
C# 3.0 Practical Learning 597
The Array class supports the creation of any of the types of arrays we saw in the
previous lessons. In the previous lesson, we saw that a two-dimensional array was an
array made of two lists:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = new string[List1Length, List2Length];

return 0;
}
}

To create such an array using the Array class, you can use the following version of the
Array.CreateInstance() method:

public static Array CreateInstance(Type elementType, int length1, int


length2)

The first argument is the type of array you want to create. The second argument is the
length of the first list. The third argument is the length of the second list. Here is an
example of using it:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = Array.CreateInstance(typeof(string), 2, 4);

return 0;
}
}

To specify the values of a two-dimensional array, you can use the following version of
the Array.SetValue() method:
public void SetValue(object value, int index1, int index2)

The first argument is the value you want to add. The second argument is the index of
the list. The second argument is the index of the element that is being added. Here is an
example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = Array.CreateInstance(typeof(string), 2, 4);

Members.SetValue("Celeste", 0, 0); // 1st List - 1st Element


Members.SetValue("Mathurin", 0, 1); // 1st List - 2nd Element
Members.SetValue("Alex", 0, 2); // 1st List - 3rd Element

C# 3.0 Practical Learning 598


Members.SetValue("Germain",0, 3); // 1st List - 4th Element

Members.SetValue("Jeremy", 1, 0); // 2nd List - 1st Element


Members.SetValue("Mathew", 1, 1); // 1st List - 2nd Element
Members.SetValue("Anselme", 1, 2); // 1st List - 3rd Element
Members.SetValue("Frederique", 1, 3);// 1st List - 4th Element

return 0;
}
}

Just as mentioned for the one-dimensional array, you can use the square brackets to
create the array but call the SetValue() method to specify the value of each element.

To access a member of a two-dimensional array created with the Array.SetValue()


method, you use the following version of the Array.GetValue() method:
public Object GetValue(int index1, int index2)

This method takes two arguments. The first argument is the index of the list where the
desired member resides. The second argument is the index of the element itself. Here is
an example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = Array.CreateInstance(typeof(string), 2, 4);

Members.SetValue("Celeste", 0, 0); // 1st List - 1st Element


Members.SetValue("Mathurin", 0, 1); // 1st List - 2nd Element
Members.SetValue("Alex", 0, 2); // 1st List - 3rd Element
Members.SetValue("Germain",0, 3); // 1st List - 4th Element

Members.SetValue("Jeremy", 1, 0); // 2nd List - 1st Element


Members.SetValue("Mathew", 1, 1); // 1st List - 2nd Element
Members.SetValue("Anselme", 1, 2); // 1st List - 3rd Element
Members.SetValue("Frederique", 1, 3);// 1st List - 4th Element

Console.WriteLine("Member: {0}", Members.GetValue(0, 2));


return 0;
}
}

To access each member of the list, you can use two for loops. Use the first loop to
access each list. Nest a second loop to it to access each member. To get the dimension
of the main list, you can call the Array.GetLength() method and specify its argument
as 0. For the internal loop, pass 1 as the argument to the Array.GetLength() method.
Here is an example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = Array.CreateInstance(typeof(string), 2, 4);
C# 3.0 Practical Learning 599
Members.SetValue("Celeste", 0, 0); // 1st List - 1st Element
Members.SetValue("Mathurin", 0, 1); // 1st List - 2nd Element
Members.SetValue("Alex", 0, 2); // 1st List - 3rd Element
Members.SetValue("Germain",0, 3); // 1st List - 4th Element

Members.SetValue("Jeremy", 1, 0); // 2nd List - 1st Element


Members.SetValue("Mathew", 1, 1); // 1st List - 2nd Element
Members.SetValue("Anselme", 1, 2); // 1st List - 3rd Element
Members.SetValue("Frederique", 1, 3);// 1st List - 4th Element

for(int List = 0; List < Members.GetLength(0); List++)


for(int Element = 0; Element < Members.GetLength(1); Element+
+)
Console.WriteLine("Member: {0}",
Members.GetValue(List , Element ));

return 0;
}
}

You can also use a foreach operator to access each member of the array. When using it,
there is no need for a counter. Here is an example:
using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Members = Array.CreateInstance(typeof(string), 2, 4);

Members.SetValue("Celeste", 0, 0); // 1st List - 1st Element


Members.SetValue("Mathurin", 0, 1); // 1st List - 2nd Element
Members.SetValue("Alex", 0, 2); // 1st List - 3rd Element
Members.SetValue("Germain",0, 3); // 1st List - 4th Element

Members.SetValue("Jeremy", 1, 0); // 2nd List - 1st Element


Members.SetValue("Mathew", 1, 1); // 1st List - 2nd Element
Members.SetValue("Anselme", 1, 2); // 1st List - 3rd Element
Members.SetValue("Frederique", 1, 3);// 1st List - 4th Element

foreach (string Member in Members)


Console.WriteLine("Member: {0}", Member);

return 0;
}
}

Three-Dimensional Arrays

Instead of two dimensions, you may want to create a three-dimensional arrays. A 3-D
array is an array that, if created with the square brackets, would use two commas. Here
is an example:
using System;

public static class Exercise


{
C# 3.0 Practical Learning 600
static int Main(string[] args)
{
double[,,] Number;

return 0;
}
}

To create such an array using the Array class, you can use the following version of its
CreateInstance() method:
public static Array CreateInstance(Type elementType,
int length1,
int length2,
int length3)

Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = Array.CreateInstance(typeof(double), 2, 3, 5);

return 0;
}
}

To specify the value of each member of the three-dimensional array, you can call the
following version of the Array.SetValue() method:
public void SetValue (
Object value,
int index1,
int index2,
int index3
)

Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = Array.CreateInstance(typeof(double), 2, 3, 5);

Number.SetValue( 12.44, 0, 0, 0);


Number.SetValue( 525.38, 0, 0, 1);
Number.SetValue( -6.28, 0, 0, 2);
Number.SetValue(2448.32, 0, 0, 3);
Number.SetValue( 632.04, 0, 0, 4);
Number.SetValue(-378.05, 0, 1, 0);
Number.SetValue( 48.14, 0, 1, 1);
Number.SetValue( 634.18, 0, 1, 2);
Number.SetValue( 762.48, 0, 1, 3);
Number.SetValue( 83.02, 0, 1, 4);

C# 3.0 Practical Learning 601


Number.SetValue( 64.92, 0, 2, 0);
Number.SetValue( -7.44, 0, 2, 1);
Number.SetValue( 86.74, 0, 2, 2);
Number.SetValue(-534.60, 0, 2, 3);
Number.SetValue( 386.73, 0, 2, 4);
Number.SetValue( 48.02, 1, 0, 0);
Number.SetValue( 120.44, 1, 0, 1);
Number.SetValue( 38.62, 1, 0, 2);
Number.SetValue( 526.82, 1, 0, 3);
Number.SetValue(1704.62, 1, 0, 4);
Number.SetValue( 56.85, 1, 1, 0);
Number.SetValue(105.48, 1, 1, 1);
Number.SetValue( 363.31, 1, 1, 2);
Number.SetValue( 172.62, 1, 1, 3);
Number.SetValue( 128.48, 1, 1, 4);
Number.SetValue( 906.68, 1, 2, 0);
Number.SetValue( 47.12, 1, 2, 1);
Number.SetValue(-166.07, 1, 2, 2);
Number.SetValue(4444.26, 1, 2, 3);
Number.SetValue( 408.62, 1, 2, 4);

return 0;
}
}

To get the value of each member of the three-dimensional array, you can call the
following version of the Array.GetValue() method:
public Object GetValue (
int index1,
int index2,
int index3
)

Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = Array.CreateInstance(typeof(double), 2, 3, 5);

Number.SetValue( 12.44, 0, 0, 0);


Number.SetValue( 525.38, 0, 0, 1);
Number.SetValue( -6.28, 0, 0, 2);
Number.SetValue(2448.32, 0, 0, 3);
Number.SetValue( 632.04, 0, 0, 4);
Number.SetValue(-378.05, 0, 1, 0);
Number.SetValue( 48.14, 0, 1, 1);
Number.SetValue( 634.18, 0, 1, 2);
Number.SetValue( 762.48, 0, 1, 3);
Number.SetValue( 83.02, 0, 1, 4);
Number.SetValue( 64.92, 0, 2, 0);
Number.SetValue( -7.44, 0, 2, 1);
Number.SetValue( 86.74, 0, 2, 2);
Number.SetValue(-534.60, 0, 2, 3);
Number.SetValue( 386.73, 0, 2, 4);
Number.SetValue( 48.02, 1, 0, 0);
C# 3.0 Practical Learning 602
Number.SetValue( 120.44, 1, 0, 1);
Number.SetValue( 38.62, 1, 0, 2);
Number.SetValue( 526.82, 1, 0, 3);
Number.SetValue(1704.62, 1, 0, 4);
Number.SetValue( 56.85, 1, 1, 0);
Number.SetValue(105.48, 1, 1, 1);
Number.SetValue( 363.31, 1, 1, 2);
Number.SetValue( 172.62, 1, 1, 3);
Number.SetValue( 128.48, 1, 1, 4);
Number.SetValue( 906.68, 1, 2, 0);
Number.SetValue( 47.12, 1, 2, 1);
Number.SetValue(-166.07, 1, 2, 2);
Number.SetValue(4444.26, 1, 2, 3);
Number.SetValue( 408.62, 1, 2, 4);

Console.WriteLine("Number: {0}\n", Number.GetValue(0, 2, 4));

return 0;
}
}

This would produce:


Number: 386.73

Press any key to continue . . .

To access each member of the array, you can use three for loops. Here is an example:
using System;

public static class Exercise


{
static int Main(string[] args)
{
var Number = Array.CreateInstance(typeof(double), 2, 3, 5);

Number.SetValue( 12.44, 0, 0, 0);


Number.SetValue( 525.38, 0, 0, 1);
Number.SetValue( -6.28, 0, 0, 2);
Number.SetValue(2448.32, 0, 0, 3);
Number.SetValue( 632.04, 0, 0, 4);
Number.SetValue(-378.05, 0, 1, 0);
Number.SetValue( 48.14, 0, 1, 1);
Number.SetValue( 634.18, 0, 1, 2);
Number.SetValue( 762.48, 0, 1, 3);
Number.SetValue( 83.02, 0, 1, 4);
Number.SetValue( 64.92, 0, 2, 0);
Number.SetValue( -7.44, 0, 2, 1);
Number.SetValue( 86.74, 0, 2, 2);
Number.SetValue(-534.60, 0, 2, 3);
Number.SetValue( 386.73, 0, 2, 4);
Number.SetValue( 48.02, 1, 0, 0);
Number.SetValue( 120.44, 1, 0, 1);
Number.SetValue( 38.62, 1, 0, 2);
Number.SetValue( 526.82, 1, 0, 3);
Number.SetValue(1704.62, 1, 0, 4);
Number.SetValue( 56.85, 1, 1, 0);
Number.SetValue(105.48, 1, 1, 1);
Number.SetValue( 363.31, 1, 1, 2);

C# 3.0 Practical Learning 603


Number.SetValue( 172.62, 1, 1, 3);
Number.SetValue( 128.48, 1, 1, 4);
Number.SetValue( 906.68, 1, 2, 0);
Number.SetValue( 47.12, 1, 2, 1);
Number.SetValue(-166.07, 1, 2, 2);
Number.SetValue(4444.26, 1, 2, 3);
Number.SetValue( 408.62, 1, 2, 4);

for(int External = 0; External < Number.GetLength(0); External++)


for(int Internal = 0; Internal < Number.GetLength(1);
Internal++)
for(int Element = 0; Element < Number.GetLength(2);
Element++)
Console.WriteLine("Number: {0}",
Number.GetValue(External, Internal,
Element));

return 0;
}
}

This would produce:


Number: 12.44
Number: 525.38
Number: -6.28
Number: 2448.32
Number: 632.04
Number: -378.05
Number: 48.14
Number: 634.18
Number: 762.48
Number: 83.02
Number: 64.92
Number: -7.44
Number: 86.74
Number: -534.6
Number: 386.73
Number: 48.02
Number: 120.44
Number: 38.62
Number: 526.82
Number: 1704.62
Number: 56.85
Number: 105.48
Number: 363.31
Number: 172.62
Number: 128.48
Number: 906.68
Number: 47.12
Number: -166.07
Number: 4444.26
Number: 408.62
Press any key to continue . . .

You can also use a foreach loop to access each member of the array. Here is an
example:
using System;

C# 3.0 Practical Learning 604


public static class Exercise
{
static int Main(string[] args)
{
var Number = Array.CreateInstance(typeof(double), 2, 3, 5);

Number.SetValue( 12.44, 0, 0, 0);


Number.SetValue( 525.38, 0, 0, 1);
Number.SetValue( -6.28, 0, 0, 2);
Number.SetValue(2448.32, 0, 0, 3);
Number.SetValue( 632.04, 0, 0, 4);
Number.SetValue(-378.05, 0, 1, 0);
Number.SetValue( 48.14, 0, 1, 1);
Number.SetValue( 634.18, 0, 1, 2);
Number.SetValue( 762.48, 0, 1, 3);
Number.SetValue( 83.02, 0, 1, 4);
Number.SetValue( 64.92, 0, 2, 0);
Number.SetValue( -7.44, 0, 2, 1);
Number.SetValue( 86.74, 0, 2, 2);
Number.SetValue(-534.60, 0, 2, 3);
Number.SetValue( 386.73, 0, 2, 4);
Number.SetValue( 48.02, 1, 0, 0);
Number.SetValue( 120.44, 1, 0, 1);
Number.SetValue( 38.62, 1, 0, 2);
Number.SetValue( 526.82, 1, 0, 3);
Number.SetValue(1704.62, 1, 0, 4);
Number.SetValue( 56.85, 1, 1, 0);
Number.SetValue(105.48, 1, 1, 1);
Number.SetValue( 363.31, 1, 1, 2);
Number.SetValue( 172.62, 1, 1, 3);
Number.SetValue( 128.48, 1, 1, 4);
Number.SetValue( 906.68, 1, 2, 0);
Number.SetValue( 47.12, 1, 2, 1);
Number.SetValue(-166.07, 1, 2, 2);
Number.SetValue(4444.26, 1, 2, 3);
Number.SetValue( 408.62, 1, 2, 4);

foreach(double n in Number)
Console.WriteLine("Number: {0}", n);

return 0;
}
}

Multidimensional Arrays

The Array class supports all dimensions of arrays beyond three. To create a
multidimensional array, the class is equipped with the following version of its
CreateInstance() method:
public static Array CreateInstance(Type elementType, params int[]
lengths)

To add elements to the list, you can use the following equivalent version of the
SetValue() method:

public void SetValue(object value, params int[] indices)

C# 3.0 Practical Learning 605


To get the value of an element, you would call the following version of the GetValue()
method:
public Object GetValue(params int[] indices)

Arranging the List


 

Arranging the Items in Alphabetical or Numerical Order

When you initialize an array, you add the members in an order of your choice. At one
point, when accessing the members of an array, you may want them to be arranged in
alphabetical, in numerical, or in chronological order. To assist you with re-arranging the
elements in an array, the Array class is equipped with a method named Sort that is
overloaded with as many versions as you can possibly need.

To arrange an array of the type we have used so far, you can call the following version
of the Array.Sort() method:
public static void Sort(Array array);

This is a static method that takes as argument the name of the array you want to re-
arrange. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[]
{
7628.937, 6.48, 574.9, 293749.064,
0.70257, 314.905, 80458.01
};

Console.WriteLine("List of Numbers");
foreach(var Number in Numbers)
Console.WriteLine("Number: {0}", Number);

Array.Sort(Numbers);

Console.WriteLine("\nList of Numbers");
foreach (var Number in Numbers)
Console.WriteLine("Number: {0}", Number);

return 0;
}
}

This would produce:


List of Numbers
Number: 7628.937
Number: 6.48
Number: 574.9
C# 3.0 Practical Learning 606
Number: 293749.064
Number: 0.70257
Number: 314.905
Number: 80458.01

List of Numbers
Number: 0.70257
Number: 6.48
Number: 314.905
Number: 574.9
Number: 7628.937
Number: 80458.01
Number: 293749.064
Press any key to continue . . .

Notice that the numbers are arranged in in ascending order. In the same way, if the
array is made of strings, you can call the Array.Sort() method to arrange it in
alphabetical order. If the array is made of dates, you can arrange them in chronological
order.

Reversing the Arrangement

To arrange the members in reverse order, you can call the Array.Reverse() method.
Its syntax is:
public static void Reverse(Array array);

Locating an Element in an Array


 

Locating the Index of an Element

One of the most routine operations you can perform on an array is to find out whether it
contains this or that value. For example, if the array contains a certain member, you
may want to retrieve the index of that member. To assist you with this, the Array class
is equipped with a method named IndexOf() method that comes in various versions.
To apply it on the type of array we have used so far, you can use the following syntax:
public static int IndexOf(Array array, object value);

This method visits each member of the array, looking for the value. Once it finds value
in the array, it stops and returns the index where the first occurrence of value was
found. Here is an example of calling it:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Numbers = new double[]
{
7628.937, 6.48, 574.9, 293749.064,
0.70257, 314.905, 80458.01

C# 3.0 Practical Learning 607


};

Console.WriteLine("List of Numbers");
foreach(var Number in Numbers)
Console.WriteLine("Number: {0}", Number);
Console.WriteLine();

int Index = Array.IndexOf(Numbers, 314.905);

Console.WriteLine("The index of 314.905 is {0}", Index);

return 0;
}
}

If the Array.IndexOf() method finds the value in the array, it returns its position. The
above program produces:
List of Numbers
Number: 7628.937
Number: 6.48
Number: 574.9
Number: 293749.064
Number: 0.70257
Number: 314.905
Number: 80458.01

The index of 314.905 is 5


Press any key to continue . . .

If the array is not found, the method may return -1.

The IndexOf() method actually looks for the first occurrence of an item in an array. If
you prefer to get the last occurrence of that item in the array, you can call the
Array.LastIndexOf() method. It also is overloaded in three versions.

The Bounds of an Array

To better manage an array, the compiler must always be able to locate its highest and
its lowest members. This is particularly important because an array must have a size.

The lowest member of an array can be located using the Array.GetLowerBound()


method. Its syntax is:
public int GetLowerBound(int dimension);

The highest member of an array can be located using the Array.GetUpperBound()


method. Its syntax is:
public int GetUpperBound(int dimension);

In both cases, the dimension argument is the rank of the array. For a single-dimensional
array, as those we have always used so far, this parameter must have the value of 0.

C# 3.0 Practical Learning 608


Strings
 

The Characters of a String


 

Introduction

To represent the values of an application, we primarily use characters, letters, and


symbols from the alphabet or out of the alphabet. To recognize these symbols, the C#
language provides the char data type. The char data type is identified in the . NET
Framework by the Char structure, which gets represented with a 16-bit value.

To declare a variable that can hold one character, a letter, or a symbol, user the char
data type or the var keyword if you are also initializing the variable. To initialize the
variable, include its value between two single-quotes. Here are examples:

using System;

public static class Exercise


{
public static int Main(string[] args)
{
var Gender = 'm';
var MoneySymbol = '$';
var Multiplication = '*';
var NumberOne = '1';

Console.WriteLine("A few characters");


Console.WriteLine("Gender: {0}", Gender);
Console.WriteLine("Money Symbol: {0}", MoneySymbol);
Console.WriteLine("Multiplication: {0}", Multiplication);
Console.WriteLine("Number One: {0}", NumberOne);

return 0;
}
}

This would produce:


A few characters
Gender: m
Money Symbol: $
Multiplication: *
Number One: 1

Press any key to continue...

Practical Learning: Introducing Strings

C# 3.0 Practical Learning 609


1. Start Microsoft Visual C# and create a new Console Application named
RealEstate4

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to Property and press Enter

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate4
{
public enum PropertyCondition
{
Unknown,
Excellent,
Good,
NeedsRepair,
BadShape
}

public class Property


{
private string propNbr;
private PropertyCondition cond;
private short beds;
private float baths;
private int yr;
private decimal val;

public Property()
{
}

public string PropertyNumber


{
get { return propNbr; }
set
{
if (propNbr == "")
propNbr = "N/A";
else
propNbr = value;
}
}

public PropertyCondition Condition


{
get { return cond; }
set { cond = value; }
}

public short Bedrooms


{
get
C# 3.0 Practical Learning 610
{
if (beds <= 1)
return 1;
else
return beds;
}
set { beds = value; }
}

public float Bathrooms


{
get { return (baths <= 0) ? 0.00f : baths; }
set { baths = value; }
}

public int YearBuilt


{
get { return yr; }
set { yr = value; }
}

public decimal Value


{
get { return (val <= 0) ? 0.00M : val; }
set { val = value; }
}
}
}

5. In the Class View, right-click RealEstate4 -> Add -> Class...

6. Set the Name to HouseType and press Enter

7. To derive a class, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate4
{
public class HouseType : Property
{
private short nbrOfStories;
private bool basement;
private bool garage;

public short Stories


{
get { return nbrOfStories; }
set { nbrOfStories = value; }
}

public bool FinishedBasement


{
get { return basement; }
set { basement = value; }
}
C# 3.0 Practical Learning 611
public bool IndoorGarage
{
get { return garage; }
set { garage = value; }
}
}
}

8. To create a new class, in the Solution Explorer, right-click RealEstate4, position the
mouse on Add and click Class...

9. Set the Name to Condominium and click Add

10.To create another class based on the Property class, change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate4
{
public class Condominium : Property
{
private bool handicap;

public bool HandicapAccessible


{
get { return handicap; }
set { handicap = value; }
}
}
}

11. 

12.In the Solution Explorer, right- click RealEstate4 -> Add -> Class...

13.Set the Name to PropertyListing and press Enter

14.Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate4
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

C# 3.0 Practical Learning 612


public class PropertyListing
{
private Property prop;
private HouseType hse;
private Condominium cond;
private PropertyType tp;

public Property ListProperty


{
get { return prop; }
set { prop = value; }
}

public HouseType House


{
get { return hse; }
set { hse = value; }
}

public Condominium Condo


{
get { return cond; }
set { cond = value; }
}

public PropertyType Type


{
get { return tp; }
set { tp = value; }
}

public PropertyListing()
{
prop = new Property();
hse = new HouseType();
cond = new Condominium();
}

public void CreateListing()


{
char answer = 'n';
short propType = 1;
short condition = 1;

Console.WriteLine(" =//= Altair Realty =//=");


Console.WriteLine("-=- Property Creation -=-");
try
{
Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Single Family");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Condominium");
Console.WriteLine("4. Don't Know");
Console.Write("Enter Type of Property: ");
propType = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the type of property is invalid");
C# 3.0 Practical Learning 613
}
catch (Exception)
{
Console.WriteLine("A bad behavior has been detectedd");
}

Console.Write("\nEnter Property #: ");


ListProperty.PropertyNumber = Console.ReadLine();

try
{
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.WriteLine("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
Console.Write("Enter Property Condition: ");
condition = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for the " +
"condition of the property is not valid");
}
catch (Exception)
{
Console.WriteLine("An unacceptable event has just
happened");
}

if (condition == 1)
ListProperty.Condition = PropertyCondition.Excellent;
else if (condition == 2)
ListProperty.Condition = PropertyCondition.Good;
else if (condition == 3)
ListProperty.Condition = PropertyCondition.NeedsRepair;
else if (condition == 4)
ListProperty.Condition = PropertyCondition.BadShape;
else
ListProperty.Condition = PropertyCondition.Unknown;

switch ((PropertyType)propType)
{
case PropertyType.SingleFamily:
Type = PropertyType.SingleFamily;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine(
"The number of stories you entered is not allowed");
}
catch (Exception)
{
Console.WriteLine("An abnormal behavior has
occurred");
C# 3.0 Practical Learning 614
}

try
{
Console.Write(
"Does it have an indoor car garage (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Indoor Car Garage
Answer");
}
try
{
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Basement Answer");
}
break;

case PropertyType.Townhouse:
Type = PropertyType.Townhouse;
try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The number of stories " +
"you entered is not valid");
}
catch (Exception)
{
Console.WriteLine("This is one of " +
"those abnormal behaviors");
}

Console.Write("Does it have an indoor car garage


(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
C# 3.0 Practical Learning 615
House.FinishedBasement = true;
else
House.FinishedBasement = false;
break;

case PropertyType.Condominium:
Type = PropertyType.Condominium;
Console.Write("\nIs the building accessible " +
"to handicapped (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
Condo.HandicapAccessible = true;
else
Condo.HandicapAccessible = false;
break;

default:
Type = PropertyType.Unknown;
break;
}

try
{
Console.Write("\nHow many bedrooms? ");
ListProperty.Bedrooms = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}
catch (Exception)
{
Console.WriteLine("The program has decided to stop");
}

try
{
Console.Write("How many bathrooms? ");
ListProperty.Bathrooms = float.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("The computer has encountered an
error");
}

try
{
Console.Write("Year built: ");
ListProperty.YearBuilt = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have built in that
year");
}
catch (Exception)
{

C# 3.0 Practical Learning 616


Console.WriteLine("The application is experiencing a
problem");
}

try
{
Console.Write("Property Value: ");
ListProperty.Value = decimal.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("This is where the application " +
"draws the line: it stops!");
}
}

public void ShowListing()


{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
ListProperty.PropertyNumber);
Console.WriteLine("Property Type: {0}", Type);

switch (Type)
{
case PropertyType.SingleFamily:
case PropertyType.Townhouse:
Type = PropertyType.SingleFamily;
Console.WriteLine("Stories: {0}",
House.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
House.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
House.FinishedBasement);
break;

case PropertyType.Condominium:
Console.WriteLine("Handicapped Accessible Building:
{0}",
Condo.HandicapAccessible);
break;
}

Console.WriteLine("Condition: {0}",
ListProperty.Condition);
Console.WriteLine("Bedrooms: {0}",
ListProperty.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
ListProperty.Bathrooms);
Console.WriteLine("Year Built: {0}",
ListProperty.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
ListProperty.Value);
}
}
}

C# 3.0 Practical Learning 617


15.Access the Program.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate4
{
public class Program
{
static void Main(string[] args)
{
PropertyListing Listing = new PropertyListing();

Listing.CreateListing();
Console.WriteLine("\n");
Listing.ShowListing();
}
}
}

16.Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 1

Enter Property #: 793742

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? 3


Does it have an indoor car garage (y/n): p
Is the basement finished(y/n): t

How many bedrooms? 4


How many bathrooms? 3.5
Year built: 1994
Property Value: 658225.85

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 793742
Property Type: SingleFamily
C# 3.0 Practical Learning 618
Stories: 3
Has Indoor Car Garage: False
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 4
Bathrooms: 3.50
Year Built: 1994
Market Value: $658,225.85

Press any key to continue . . .

17.Close the DOS window

The String: An Array of Characters

In different programs so far, when we needed a string object, we would declare a


variable of type String. To support strings, the .NET Framework provides the String
class. This class is defined in the C# language as the string data type. Here is an
example of declaring, initializing, and using a string object:
using System;

public class Exercise


{
static int Main(string[] args)
{
var gender = "Female";

Console.WriteLine("Gender: {0}\n", gender);

return 0;
}
}

This would produce:


Gender: Female

Press any key to continue . . .

From what we have studied about arrays, if you observe a value such as "Female", you
may see that it primarily resembles a collection of characters. A string is a group of
characters. This also means that a string is an array of characters. After declaring and
initializing a string, it is considered an array of values where each character occupies a
specific position. The positioned are numbered so that the most left character of the
string occupies index 0; the second character is at index 1, and so on.

To support this idea of an array of characters, the String class is equipped with an
indexed property named Chars. This is also how you can retrieve the character at a
specific index in the string, using the [] operator of arrays. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{

C# 3.0 Practical Learning 619


var gender = "Female";
var gdr = gender[2];

Console.WriteLine("Gender: {0}", gender);


Console.WriteLine("Character: {0}", gdr);

Console.WriteLine();
return 0;
}
}

This would produce:


Gender: Female
Character: m

Press any key to continue . . .

Once (and because) a string is considered a collection of items, you can use the foreach
operator to access each member of the collection. Here is an example:
using System;

class Exercise
{
static int Main(string[] args)
{
var gender = "Female";

Console.WriteLine("Gender: {0}", gender);

Console.WriteLine("\nIndividual Characters");
foreach(char c in gender)
Console.WriteLine("Character: {0}", c);
return 0;
}
}

This would produce:


Gender: Female

Individual Characters
Character: F
Character: e
Character: m
Character: a
Character: l
Character: e
Press any key to continue . . .

Converting Characters to the Opposite Case

The English language uses two character representations: lowercase and uppercase. The
characters in lowercase are: a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, and z. The equivalent characters in uppercase are represented as A, B, C, D, E, F, G,
H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, and Z. Characters used for counting
are called numeric characters; each one of them is called a digit. They are 0, 1, 2, 3, 4,

C# 3.0 Practical Learning 620


5, 6, 7, 8, and 9. There are other characters used to represent things in computer
applications, mathematics, and others. Some of these characters, also called symbols
are ~ , ! @ # $ % ^ & * ( ) _ + { } ` | = [ ] \ : " ; ' < > ? , . / These characters are
used for various reasons and under different circumstances. For example, some of them
are used as operators in mathematics or in computer programming. Regardless of
whether a character is easily identifiable or not, all these symbols are character types
and can be declared using the char data type followed by a name.

An alphabetic character, for any reason judged necessary, can be converted from one
case to another. The other characters, non-alphabetic symbols, and the numbers, do not
have a case and therefore cannot be converted in cases.

To convert a string from lowercase to uppercase, you can call use the ToUpper()
method of the String class. It is overloaded with two versions. One of the versions of
this method uses the following syntax:
public string ToUpper();

This method takes no argument. This method considers each character of the string that
called it. If the character is already in uppercase, it would not change. If the character is
a lowercase alphabetic character, it would be converted to uppercase. If the character is
not an alphabetic character, it would be kept “as-is”. Here is an example:
using System;

public class Program


{
static int Main(string[] args)
{
var strFullName = "Alexander Patrick Katts";
var strConversion = strFullName.ToUpper();

Console.WriteLine("Full Name: " + strFullName);


Console.WriteLine("Full Name: " + strConversion);

return 0;
}
}

This would produce:


Full Name: Alexander Patrick Katts
Full Name: ALEXANDER PATRICK KATTS
Press any key to continue . . .

To convert a string to lowercase, you can call the String.ToLower() method. Its
syntax is:
public string ToLower();

This method follows the same logic as its counterpart: it scans the string that called it,
visiting each character. If the character is not an alphabetic character, it would be kept
“as-is”. If the character is an uppercase alphabetic character, it would be converted to
lowercase. If it is in lowercase, it would not be converted.

Replacing a Character

C# 3.0 Practical Learning 621


If you have a string that contains a wrong character, you can either delete that
character or replace it with another character of your choice. To support this operation,
the String class is equipped with the Replace() method that is overloaded with two
versions. One of the versions of the String.Replace() method uses the following syntax:
public string Replace(char oldChar, char newChar);

The first argument of this method is used to identify the sought character. If and
everywhere that character is found in the string, it would be replaced by the character
passed as the second argument. Here is an example that received a telephone number
from the user and it stripped that phone number with various things to end up with only
the digits:
using System;

public class Program


{
static int Main(string[] args)
{
var PhoneNumber = "";

Console.Write("Enter Phone Number: ");


PhoneNumber = Console.ReadLine();

// Get a telephone number from the user


Console.WriteLine("\nPhone Number: " + PhoneNumber);

// Remove the spaces


PhoneNumber = PhoneNumber.Replace(" ", "");
Console.WriteLine("\nPhone Number: " + PhoneNumber);

// Remove the left parenthesis, if any


PhoneNumber = PhoneNumber.Replace("(", "");
// Remove the right parenthesis, if any
PhoneNumber = PhoneNumber.Replace(")", "");
// Remove the dash, if any
PhoneNumber = PhoneNumber.Replace("-", "");
Console.WriteLine("\nPhone Number: " + PhoneNumber + "\n");
return 0;
}
}

Here is an example of running the program:


Enter Phone Number: (303) 826-4603

Phone Number: (303) 826-4603

Phone Number: (303)826-4603

Phone Number: 3038264603

Press any key to continue . . .

Working With Strings


 

C# 3.0 Practical Learning 622


The Length of a String

In many operations, you will need to know the number of characters a string consists of.
To get the size of a string, The String class provides the Length member variable.
Here is an example of using it:
using System;

public class Exercise


{
static int Main(string[] args)
{
var gender = "Female";

Console.WriteLine("Gender: {0}", gender);


Console.WriteLine("Length: {0} Characters\n", gender.Length);

return 0;
}
}

This would produce:


Gender: Female
Length: 6 Characters

Press any key to continue . . .

In the same way, you can access the Length property when processing the individual
characters of a string. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var gender = "Female";

Console.WriteLine("Gender: {0}", gender);


Console.WriteLine("Length: {0} Characters", gender.Length);

Console.WriteLine("\nIndividual Characters");
for (int c = 0; c < gender.Length; c++)
Console.WriteLine("Index[{0}]: {1}", c, gender[c]);

return 0;
}
}

This would produce:


Gender: Female
Length: 6 Characters

Individual Characters
Index[0]: F
Index[1]: e
Index[2]: m
C# 3.0 Practical Learning 623
Index[3]: a
Index[4]: l
Index[5]: e
Press any key to continue . . .

Practical Learning: Using Characters of a String

1. To create a new file, on the main menu, click Project -> Add New Item...

2. In the Templates list, click Code File

3. Set the Name to NumericExceptions and click Add

4. Change the file as follows:


 
using System;

// This exception is used to check and validate an integer


public class IntegerException : Exception
{
public IntegerException()
{
}

public override string Message


{
get
{
return "The value you entered is not a valid integer";
}
}
}

// This exception can be used to check and/or validate a decimal number


public class FloatingPointException : Exception
{
public FloatingPointException()
{
}

public override string Message


{
get
{
return "The value you entered is not a valid decimal number";
}
}
}

5. Access the PropertyListing.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate4
C# 3.0 Practical Learning 624
{
public enum PropertyType
{
Unknown,
SingleFamily,
Townhouse,
Condominium
}

public class PropertyListing


{
. . . No Change

public void CreateListing()


{
. . . No Change

try
{
Console.Write("How many bathrooms? ");
string strBathrooms = Console.ReadLine();
for (int c = 0; c < strBathrooms.Length; c++)
{
if ((strBathrooms[c] != '0') &&
(strBathrooms[c] != '1') &&
(strBathrooms[c] != '2') &&
(strBathrooms[c] != '3') &&
(strBathrooms[c] != '4') &&
(strBathrooms[c] != '5') &&
(strBathrooms[c] != '6') &&
(strBathrooms[c] != '7') &&
(strBathrooms[c] != '8') &&
(strBathrooms[c] != '9') &&
(strBathrooms[c] != '.'))
throw new FloatingPointException();
}
ListProperty.Bathrooms = float.Parse(strBathrooms);
}
catch (FloatingPointException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception)
{
Console.WriteLine("The computer has encountered an
error");
}

try
{
Console.Write("Year built: ");
ListProperty.YearBuilt = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"been built in that year");
}
catch (Exception)
{
C# 3.0 Practical Learning 625
Console.WriteLine("The application is " +
"experiencing a problem");
}

try
{
Console.Write("Property Value: ");
string strValue = Console.ReadLine();
for (int c = 0; c < strValue.Length; c++)
{
if ((strValue[c] != '0') &&
(strValue[c] != '1') &&
(strValue[c] != '2') &&
(strValue[c] != '3') &&
(strValue[c] != '4') &&
(strValue[c] != '5') &&
(strValue[c] != '6') &&
(strValue[c] != '7') &&
(strValue[c] != '8') &&
(strValue[c] != '9') &&
(strValue[c] != '.'))
throw new FloatingPointException();
}
ListProperty.Value = decimal.Parse(strValue);
}
catch (FloatingPointException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception)
{
Console.WriteLine("This is where the application " +
"draws the line: it stops!");
}
}

. . . No Change
}
}

6. Execute the application and test it. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 1

Enter Property #: 284866

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs
C# 3.0 Practical Learning 626
major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? 3


Does it have an indoor car garage (y/n): m
Is the basement finished(y/n): u

How many bedrooms? 4


How many bathrooms? 3.50
Year built: 1995
Property Value: 735000

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 284866
Property Type: SingleFamily
Stories: 3
Has Indoor Car Garage: False
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 4
Bathrooms: 3.50
Year Built: 1995
Market Value: $735,000.00
Press any key to continue . . .

7. Close the DOS window

8. Execute the application again. Here is an example:


 
=//= Altair Realty =//=
-=- Property Creation -=-

Types of Properties
1. Single Family
2. Townhouse
3. Condominium
4. Don't Know
Enter Type of Property: 1

Enter Property #: 284866

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs
major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? 3


Does it have an indoor car garage (y/n): N
Is the basement finished(y/n): Y

How many bedrooms? 4


How many bathrooms? 3.r0
C# 3.0 Practical Learning 627
The value you entered is not a valid decimal number
Year built: 1995
Property Value: 7.35e5
The value you entered is not a valid decimal number

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 284866
Property Type: SingleFamily
Stories: 3
Has Indoor Car Garage: False
Finished Basement: True
Condition: NeedsRepair
Bedrooms: 4
Bathrooms: 0.00
Year Built: 1995
Market Value: $0.00
Press any key to continue . . .

9. Close the DOS window

Replacing a Sub-String

Inside of a string, if you have a combination of consecutive character you don't want to
keep, you can either remove that sub-string or replace it with an new combination of
consecutive characters of your choice. To support this operation, the String class
provides anopther version of the the Replace() method whose syntax is:
public string Replace(string oldStr, string newStr);

The oldStr argument is the sub-string to look for in the string. Whenever that sub-string
is found in the string, it is replaced by the newStr argument.

Formatting a String

Formatting a string consists of specifying how it would be presented as an object. To


support this operation, the String class is equipped with a static method named Format.
The String.Format() method is overloaded in various versions; the syntax of the
simplest is:
public static string Format(string format, Object arg0);

This method takes two arguments and it follows the same techniques we reviewed in
Lesson 5 for data formatting. This means that the first argument can contain one or a
combination of {} operators that include incrementing numbers. The second argument
contains one or a combination of values that would be added to the {} operators of the
first argument.

Here is an example:
using System;

public class Exercise


C# 3.0 Practical Learning 628
{
static int Main(string[] args)
{
var wage = 22.45;
var strDisplay = string.Format("Hourly Salary: {0}", wage);

Console.WriteLine(strDisplay);

return 0;
}
}

This would produce:


Side: 25.85
Hourly Salary: 22.45
Press any key to continue . . .

Copying a String

After declaring and initializing one String variable, you can assign it to another String
variable using the assignment operator. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var strPerson = "Charles Stanley";

var strSomebody = strPerson;

Console.WriteLine("Full Name: " + strPerson);


Console.WriteLine("Full Name: " + strSomebody);

return 0;
}
}

This would produce:


Full Name: Charles Stanley
Full Name: Charles Stanley
Press any key to continue . . .

Assigning one variable to another is referred to as copying it. To formally support this
operator, the String class is equipped with the Copy() method. Its syntax is:
public static string Copy(string str);

This method takes as argument an existing String object and copies it, producing a
new string. Here is an example:
using System;

class Program
{

C# 3.0 Practical Learning 629


static int Main(string[] args)
{
var strPerson = "Charles Stanley";

var strSomebody = string.Copy(strPerson);

Console.WriteLine("Full Name: " + strPerson);


Console.WriteLine("Full Name: " + strSomebody);

return 0;
}
}

The string.Copy() method is used to copy all characters of one string into another
another. If you want to copy only a few characters, use the string.CopyTo() method.
Its syntax is:
public void CopyTo(int sourceIndex,
char[] destination,
int destinationIndex,
int count);

Operations on Strings
 

String Concatenation

One of the routine operations you can perform on two strings consists of adding one to
another, that is, putting one string to the right of another string, to produce a new string
made of both. There are two techniques you can use.

To add one string to another, you can use the addition operator as done in arithmetic.
Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var strNeed = "Needs";
var strRepair = "Repair";
var strAddition = strNeed + strRepair;

Console.WriteLine(strAddition);

return 0;
}
}

This would produce:


NeedsRepair
Press any key to continue . . .

C# 3.0 Practical Learning 630


In the same way, you can add as many strings as necessary using +. Here is an
example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var strFirstName = "Alexander";
var strMiddleName = "Patrick";
var strLastName = "Katts";
var strFullName = strFirstName + " " +
strMiddleName + " " +
strLastName;

Console.WriteLine("First Name: " + strFirstName);


Console.WriteLine("Middle Name: " + strMiddleName);
Console.WriteLine("Last Name: " + strLastName);
Console.WriteLine("Full Name: " + strFullName + "\n");

return 0;
}
}

This would produce:


First Name: Alexander
Middle Name: Patrick
Last Name: Katts
Full Name: Alexander Patrick Katts

Press any key to continue . . .

Besides the addition operator, to formally support string concatenation, the String class
provides the Concat() method that is overloaded in various versions. One of the
versions of this method takes two String arguments. Its syntax is:
public static string Concat(string str1, string str2);

This versions takes two strings that should be concatenated. The method returns a new
string as the first added to the second. Two imitations of this version use the following
versions:
public static string Concat(string str0,
string str1,
string str2);
public static string Concat(string str0,
string str1,
string str2,
string str3);

In each case, the method takes the number of strings and adds them.

Strings Comparisons
 

Introduction
C# 3.0 Practical Learning 631
String comparison consists of examining the characters of two strings with a character of
one string compared to a character of the other string with both characters at the same
positions. To support this operation, the String class is equipped with the Compare()
method that is overloaded in many versions. One of the versions uses the following
syntax:
public static int Compare(string String1, string String2);

This method is declared static and it takes two arguments. When it starts, the first
character of the first argument is compared to the first character of the second string.
Alphabetically, if the first character of the first string has a lower alphabetical index than
the first character of the second, this method returns a negative value. If the first
character of the first string has a higher alphabetical index than the first character of the
second, this method returns a positive value. If the first characters of both strings are
the same, the method continues with the second character of each string. If both strings
have the exact same characters, the method returns 0. This can be resumed as follows.
The method returns

 A negative value if string1 is less than string2

 0 if string1 and string2 are equal

 A positive value if string1 is greater than string2

Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var FirstName1 = "Andy";
var LastName1 = "Stanley";
var FirstName2 = "Charles";
var LastName2 = "Stanley";

var Value1 = string.Compare(FirstName1, FirstName2);


var Value2 = string.Compare(FirstName2, FirstName1);
var Value3 = string.Compare(LastName1, LastName2);

Console.WriteLine("The result of comparing " +


FirstName1 + " and " + FirstName2 +
" is\t" + Value1.ToString());
Console.WriteLine("The result of comparing " +
FirstName2 + " and " + FirstName1 +
" is\t" + Value2.ToString());
Console.WriteLine("The result of comparing " +
LastName1 + " and " + LastName2 +
" is\t" + Value3.ToString() + "\n");

return 0;
}
}

This would produce:

C# 3.0 Practical Learning 632


The result of comparing Andy and Charles is -1
The result of comparing Charles and Andy is 1
The result of comparing Stanley and Stanley is 0

Press any key to continue...

When using this version of the string.Compare() method, the case (upper or lower) of
each character is considered. If you don't want to consider this factor, the String class
proposes another version of the method. Its syntax is:
public static int Compare(string String1, string String2, bool
ignoreCase);

The third argument allows you to ignore the case of the characters when performing the
comparison.

String Equality

In the previous section, we saw that the indexed-equivalent characters of two strings
can be compared to know whether one is lower or higher than the other's. If you are
only interested to know whether two strings are equivalent, you can call the Equals()
method of the String class. It is overloaded with various versions. Two versions use the
following syntaxes:
public override bool Equals(object obj);
public bool Equals(string value);

When calling one of these versions, use an Object object or a String variable that calls
it. The method takes one argument. The variable that calls the method is compared to
the value passed as argument. If both values are the exact same, the method returns
true. The comparison is performed considering the case of each character. If you don't
want to consider the case, use the following version of the method:
public bool Equals(string value, StringComparison comparisonType);

An alternative to the second syntax is to use a static version of this method whose
syntax is:
public static bool Equals(string a, string b);

This method takes two String arguments and compares them. If they are the same,
the method returns true. This method considers the cases of the characters. If you don't
want this factor taken into consideration, use the following version of the method:
public static bool Equals(string a, string b, StringComparison
comparisonType);

Working With Sub-Strings


 

Introduction

A sub-string is a section or part of a string. To create a sub-string, you first need a string
and can retrieve one or more values from it. To support this, the String class is

C# 3.0 Practical Learning 633


equipped with the Substring() method that is overloaded in two versions. The syntax
of one is:
public string Substring(int startIndex);

The integer argument specifies the position of the first character from the variable that
called the method. The return value is a new String that is made of the characters from
startIndex to the end of the string.

Sub-String Creation

Probably the most consistent way to create a string is to control the beginning and end
retrieved from the original string. To support this, the String class is equipped with
another version of the Substring() method. Its syntax is:
public string Substring(int startIndex, int length);

The first argument specifies the index of the character to start from the String variable
that calls this method. The second argument specifies the length of the string.

C# 3.0 Practical Learning 634


Introduction to Indexers
 

A Property Can Be Indexed


 

Introduction

In the previous sections, we learned how to create an array, how to assign values to its
elements, and how to get the value of each element. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
double[] Numbers = new double[5];

Numbers[0] = 927.93;
Numbers[1] = 45.155;
Numbers[2] = 2.37094;
Numbers[3] = 73475.25;
Numbers[4] = 186.72;

for (int i = 0; i < Numbers.Length; i++)


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

Console.WriteLine();
return 0;
}
}

This would produce:


Number 1: 927,93
Number 2: 45,155
Number 3: 2,37094
Number 4: 73475,25
Number 5: 186,72

Press any key to continue . . .

In the same way, if we declared an array as a member variable of a class, to access the
elements of that member, we had to use an instance of the class, followed by the period
operator, followed by the member variable applied with the square brackets. Instead of
accessing each element through its member variable, you can create a type of property
referred to as an indexer.

C# 3.0 Practical Learning 635


Practical Learning: Introducing Indexed Properties

1. Start a new Console Application named PropertyRental1

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to Property and press Enter

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace PropertyRental1
{
public enum Condition
{
Excellent,
Good,
NeedsRepair,
Unknown
}

public class Property


{
private long propCode;
private Condition cond;
private short beds;
private float baths;
private decimal val;

public long PropertyCode


{
get { return propCode; }
set { propCode = value; }
}

public Condition PropertyCondition


{
get { return cond; }
set { cond = value; }
}

public short Bedrooms


{
get { return beds; }
set { beds = value; }
}

public float Bathrooms


{
get { return (baths <= 0) ? 0.00f : baths; }
set { baths = value; }
}

C# 3.0 Practical Learning 636


public decimal MonthlyRent
{
get { return (val <= 0) ? 0.00M : val; }
set { val = value; }
}

public Property()
{
Random rnd = new Random();
propCode = rnd.Next(100000, 999999);
cond = Condition.Unknown;
beds = 0;
baths = 0.0f;
val = 0.00M;
}
}
}

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to PropertyListing and press Enter

7. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
public class PropertyListing
{
public Property[] props;

public PropertyListing()
{
Random rnd = new Random();
props = new Property[40];

// Create a few properties ready to be rented


props[0] = new Property();
props[0].PropertyCode = rnd.Next(100000, 999999);
props[0].PropertyCondition = Condition.Excellent;
props[0].Bedrooms = 5;
props[0].Bathrooms = 3.5f;
props[0].MonthlyRent = 2650;

props[1] = new Property();


props[1].PropertyCode = rnd.Next(100000, 999999);
props[1].PropertyCondition = Condition.Excellent;
props[1].Bedrooms = 3;
props[1].Bathrooms = 2.5f;
props[1].MonthlyRent = 1750;

props[2] = new Property();


props[2].PropertyCode = rnd.Next(100000, 999999);
props[2].PropertyCondition = Condition.Good;
props[2].Bedrooms = 4;
C# 3.0 Practical Learning 637
props[2].Bathrooms = 2.5f;
props[2].MonthlyRent = 2450;

props[3] = new Property();


props[3].PropertyCode = rnd.Next(100000, 999999);
props[3].PropertyCondition = Condition.Excellent;
props[3].Bedrooms = 1;
props[3].Bathrooms = 1.0f;
props[3].MonthlyRent = 880;

props[4] = new Property();


props[4].PropertyCode = rnd.Next(100000, 999999);
props[4].PropertyCondition = Condition.Excellent;
props[4].Bedrooms = 3;
props[4].Bathrooms = 2.5f;
props[4].MonthlyRent = 1880;

props[5] = new Property();


props[5].PropertyCode = rnd.Next(100000, 999999);
props[5].PropertyCondition = Condition.Good;
props[5].Bedrooms = 2;
props[5].Bathrooms = 1.0f;
props[5].MonthlyRent = 1050;

// Since we don't yet have a complete list of properties


// Create some empty ones
for (int i = 6; i < 40; i++)
{
props[i] = new Property();
}
}
}
}

8. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
public class Program
{
static void Main(string[] args)
{
var properties = new PropertyListing();
var prop = new Property();

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


{

Console.WriteLine("{0}.----------------------------------",
i + 1);
Console.WriteLine("Property #: {0}",
properties .props[i].PropertyCode);
Console.WriteLine("Condition: {0}",
properties .props[i].PropertyCondition);
C# 3.0 Practical Learning 638
Console.WriteLine("Bedrooms: {0}",
properties .props[i].Bedrooms);
Console.WriteLine("Bathrooms: {0}",
properties .props[i].Bathrooms);
Console.WriteLine("Market Value: {0}\n",
properties .props[i].MonthlyRent.ToString("C"));
}
Console.WriteLine("======================================");
}
}
}

9. Press Ctrl + F5 to execute the application. This would produce:


 
1.----------------------------------
Property #: 920119
Condition: Excellent
Bedrooms: 5
Bathrooms: 3.5
Market Value: $2,650.00

2.----------------------------------
Property #: 587917
Condition: Excellent
Bedrooms: 3
Bathrooms: 2.5
Market Value: $1,750.00

3.----------------------------------
Property #: 904376
Condition: Good
Bedrooms: 4
Bathrooms: 2.5
Market Value: $2,450.00

4.----------------------------------
Property #: 421662
Condition: Excellent
Bedrooms: 1
Bathrooms: 1
Market Value: $880.00

5.----------------------------------
Property #: 305196
Condition: Excellent
Bedrooms: 3
Bathrooms: 2.5
Market Value: $1,880.00

6.----------------------------------
Property #: 503836
Condition: Good
Bedrooms: 2
Bathrooms: 1
Market Value: $1,050.00

======================================
Press any key to continue . . .

C# 3.0 Practical Learning 639


10.Close the DOS window

An Indexer

An indexer, also called an indexed property, is a class's property that allows you to
access a member variable of a class using the features of an array. To create an indexed
property, start the class like any other. In the body of the class, create a field that is an
array. Here is an example:
public class Number
{
double[] Numbers = new double[5];
}

Then, in the body of the class, create a property named this with its accessor(s). The
this property must be the same type as the field it will refer to. The property must take
a parameter as an array. This means that it must have square brackets. Inside of the
brackets, include the parameter you will use as index to access the members of the
array.

Traditionally, and as we have seen so far, you usually access the members of an array
using an integer-based index. Therefore, you can use an int type as the index of the
array. Of course, the index' parameter must have a name, such as i. This would be
done as follows:
public class Number
{
double[] Numbers = new double[5];

public double this[int i]


{
}
}

If you want the property to be read-only, include only a get accessor. In the get
accessor, you should return an element of the array field the property refers to, using
the parameter of the property. This would be done as follows:
public class Number
{
double[] Numbers = new double[5];

public double this[int i]


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

Once you have created the indexed property, the class can be used. To start, you can
declare a variable of the class. To access its arrayed field, you can apply the square
brackets directly to it. Here is an example:
using System;

public class Number


{
double[] Numbers;
C# 3.0 Practical Learning 640
public double this[int i]
{
get { return Numbers[i]; }
}

public Number()
{
Numbers = new double[5];
Numbers[0] = 927.93;
Numbers[1] = 45.155;
Numbers[2] = 2.37094;
Numbers[3] = 73475.25;
Numbers[4] = 186.72;
}
}

public class Exercise


{
static int Main(string[] args)
{
var nbr = new Number();

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


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

Console.WriteLine();
return 0;
}
}

Based on this, a type of formula to create and use a basic indexed property is:
class ClassName
{
DataType[] ArrayName = new DataType[Length];

public DataType this[int i]


{
get { return ArrayName[i]; }
}
}

Indexed Properties of Other Primitive Types

In the above example, we created a property that produced double-precision values.


When creating an indexed property, you will decide what type of value the property
must produce or the type it can have. As opposed to an int or a double, you can also
create a property that takes or produces a string. To do this, you can use the above
class template with the desired data type, such as string. Here is an example of a
string-based indexed property:
using System;

public class Philosopher


{
string[] phil = new string[8];

C# 3.0 Practical Learning 641


public string this[int i]
{
get { return phil[i]; }
}

public Philosopher()
{
phil[0] = "Aristotle";
phil[1] = "Emmanuel Kant";
phil[2] = "Tom Huffman";
phil[3] = "Judith Jarvis Thompson";
phil[4] = "Thomas Hobbes";
phil[5] = "Cornell West";
phil[6] = "Jane English";
phil[7] = "James Rachels";
}
}

public class Exercise


{
static int Main(string[] args)
{
var thinker = new Philosopher();

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


Console.WriteLine("Philosopher: {0}", thinker[i]);

Console.WriteLine();
return 0;
}
}

This would produce:


Philosopher: Aristotle
Philosopher: Emmanuel Kant
Philosopher: Tom Huffman
Philosopher: Judith Jarvis Thompson
Philosopher: Thomas Hobbes
Philosopher: Cornell West
Philosopher: Jane English
Philosopher: James Rachels

Press any key to continue . . .

In the same way, you can created a Boolean-based indexed property by simply making
it return a bool type. Here is an example:
using System;

public class DrivingWhileIntoxicated


{
bool[] dwi = new bool[7];

public bool this[int i]


{
get { return dwi[i]; }
}

public DrivingWhileIntoxicated()
C# 3.0 Practical Learning 642
{
dwi[0] = false;
dwi[1] = true;
dwi[2] = true;
dwi[3] = false;
dwi[5] = false;
dwi[6] = false;
}
}

public class Exercise


{
static int Main(string[] args)
{
var driving = new DrivingWhileIntoxicated();

Console.WriteLine("Police Report");
Console.WriteLine("-------------------------------");
for(int i = 0; i < 7; i++)
Console.WriteLine("Driver Was Intoxicated: {0}", driving[i]);

Console.WriteLine();
return 0;
}
}

This would produce:


Police Report
-------------------------------
Driver Was Intoxicated: False
Driver Was Intoxicated: True
Driver Was Intoxicated: True
Driver Was Intoxicated: False
Driver Was Intoxicated: False
Driver Was Intoxicated: False
Driver Was Intoxicated: False

Press any key to continue . . .

Using a Non-Integer-Based Index

In previous lessons, we saw how to create different arrays that are numeric or string
based. Here is an example of a float array:
using System;

public class Exercise


{
static int Main(string[] args)
{
float[] ages = new float[5];

ages[0] = 14.50f;
ages[1] = 12.00f;
ages[2] = 16.50f;
ages[3] = 14.00f;
ages[4] = 15.50f;

C# 3.0 Practical Learning 643


Console.WriteLine("Student Age: {0}", ages[2]);

Console.WriteLine();
return 0;
}
}

When we think of arrays, we usually consider passing an integer-based parameter to the


square brackets of the variable, as done for the above ages array:
float[] ages = new float[5];

When using an indexed property, you can use almost any type of index, such as a real
value or a string. To do this, in the square brackets of the this property, pass the
desired type as the index. Here is an example:
public class StudentAge
{
public float this[string name]
{
}
}

When defining the indexed property, there are two rules you must follow and you are
aware of them already because an indexed property is like a method that takes a
parameter and doesn't return void. Therefore, when implementing an indexed property,
make sure you return the right type of value and make sure you pass the appropriate
index to the return value of the this property. Here is an example:
public class StudentAge
{
public float this[string name]
{
get
{
if( name == "Ernestine Jonas" )
return 14.50f;
else if( name == "Paul Bertrand Yamaguchi" )
return 12.50f;
else if( name == "Helene Jonas" )
return 16.00f;
else if( name == "Chrissie Hanson" )
return 14.00f;
else if( name == "Bernard Hallo" )
return 15.50f;
else
return 12.00f;
}
}
}

Once you have defined the property, you can use it. To access any of its elements, you
must pass the appropriate type of index. In this case, the index must be passed as a
string and not an integer. You can then do whatever you want with the value produced
by the property. For example, you can display it to the user. Here is an example:
using System;

public class StudentAge


C# 3.0 Practical Learning 644
{
public float this[string name]
{
get
{
if( name == "Ernestine Jonas" )
return 14.50f;
else if( name == "Paul Bertrand Yamaguchi" )
return 12.50f;
else if( name == "Helene Jonas" )
return 16.00f;
else if( name == "Chrissie Hanson" )
return 14.00f;
else if( name == "Bernard Hallo" )
return 15.50f;
else
return 12.00f;
}
}
}

public class Exercise


{
static int Main(string[] args)
{
var sa = new StudentAge();
var age = sa["Paul Bertrand Yamaguchi"];

Console.WriteLine("Student Age: {0}", age);

Console.WriteLine();
return 0;
}
}

This would produce:


Student Age: 12.5

Press any key to continue . . .

You can also pass an enumeration as an index. To do this, after defining the
enumerator, type its name and a parameter name in the square brackets of the this
member, then define the property as you see fit. To access the property outside, apply
an enumeration member to the square brackets on an instance of the class. Here is an
example:
using System;

public enum CategoryFee


{
Children,
Adult,
Senior,
Unknown
}

public class GolfClubMembership


{

C# 3.0 Practical Learning 645


double[] fee = new double[4];

public GolfClubMembership()
{
fee[0] = 150.95d;
fee[1] = 250.75d;
fee[2] = 85.65d;
fee[3] = 350.00d;
}

public double this[CategoryFee cat]


{
get
{
if (cat == CategoryFee.Children)
return fee[0];
else if (cat == CategoryFee.Adult)
return fee[1];
else if (cat == CategoryFee.Senior)
return fee[2];
else
return fee[3];
}
}
}

public class Exercise


{
static int Main(string[] args)
{
var mbr = new GolfClubMembership();

Console.WriteLine("Membership Fee: {0}",


mbr[CategoryFee.Senior]);

Console.WriteLine();
return 0;
}
}

This would produce:


Membership Fee: 85.65

Press any key to continue . . .

Practical Learning: Creating an Indexer

1. To create an indexer, access the PropertyListing.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
public class PropertyListing
C# 3.0 Practical Learning 646
{
public Property[] props;

public string this[long code]


{
get {
for(int i = 0; i < props.Length; i++)
if( code == props[i].PropertyCode )
return "Property #: " + props[i].PropertyCode +
"\nCondition: " +
props[i].PropertyCondition +
"\nBedrooms: " + props[i].Bedrooms +
"\nBathrooms: " + props[i].Bathrooms +
"\nMonthly Rent: " +
props[i].MonthlyRent.ToString("C");
return "Unidentifiable Property";
}
}

public PropertyListing()
{
. . . No Change
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
public class Program
{
static void Main(string[] args)
{
var properties = new PropertyListing();
var lngCode = 0L;

Console.WriteLine("Here is a list of our properties by


code");
for (int i = 0; i < 6; i++)
Console.WriteLine("Property Code: {0}",
properties.props[i].PropertyCode);

try
{
Console.Write("Enter Property Code: ");
lngCode = long.Parse(Console.ReadLine());

Console.WriteLine("======================================");
Console.WriteLine("Property Information");

Console.WriteLine("--------------------------------------");
Console.WriteLine(properties[lngCode]);
C# 3.0 Practical Learning 647
Console.WriteLine("======================================");

}
catch (FormatException)
{
Console.WriteLine("=- Invalid Property Code -=");
}
}
}
}

3. Press Ctrl + F5 to execute the application. Here is an example:


 
Here is a list of our properties by code
Property Code: 355443
Property Code: 653004
Property Code: 800118
Property Code: 839375
Property Code: 148561
Property Code: 697001
Enter Property Code: 697001
======================================
Property Information
--------------------------------------
Property #: 697001
Condition: Good
Bedrooms: 2
Bathrooms: 1
Monthly Rent: $1,050.00
======================================
Press any key to continue . . .

4. Close the DOS window

Topics on Indexed Properties


 

Multi-Parameterized Indexed Properties

The indexed properties we have used so far were taking only one parameter. You can
create an indexed property whose array uses more than one dimension. To start an
indexed property that would use various parameters, first declare the array as we saw in
Lesson 24. After declaring the array, create a this property that takes the parameters.
Here is an example for an indexed property that relates to a two-dimensional array:
public class Numbers
{
double[,] nbr;

public double this[int x, int y]


{
}
}

C# 3.0 Practical Learning 648


In the body of an accessor ( get or set), use the parameter as appropriately as you see
fit. At a minimum, for a get accessor, you can return the value of the array using the
parameters based on the rules of a two-dimensional array. This can be done as follows:
public class Numbers
{
double[,] nbr;

public double this[int x, int y]


{
get { return nbr[x, y]; }
}
}

After creating the property, you can access each element of the array by applying the
square brackets to an instance of the class. Here is an example:
using System;

public class Numbers


{
double[,] nbr;

public double this[int x, int y]


{
get { return nbr[x, y]; }
}

public Numbers()
{
nbr = new double[2,4];
nbr[0, 0] = 927.93;
nbr[0, 1] = 45.155;
nbr[0, 2] = 2.37094;
nbr[0, 3] = 73475.25;
nbr[1, 0] = 186.72;
nbr[1, 1] = 82.350;
nbr[1, 2] = 712734.95;
nbr[1, 3] = 3249.0057;
}
}

public class Exercise


{
static int Main(string[] args)
{
var nbr = new Numbers();

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


{
for (int j = 0; j < 4; j++)
{
double value = nbr[i, j];
Console.WriteLine("Number [{0}][{1}]: {2}", i, j, value);
}
}

Console.WriteLine();
return 0;

C# 3.0 Practical Learning 649


}
}

Remember that one of the most valuable features of an indexed property is that, when
creating it, you can make it return any primitive type and you can make it take any
parameter of your choice. Also, the parameters of a multi-parameter indexed property
don't have to be the same type. One can be a character while the other is a bool type;
one can be a double while the other is a short, one can be an integer while the other
is a string. When defining the property, you must apply the rules of both the methods
and the arrays. Here is an example of a property that takes an integer and a string:
using System;

public class Catalog


{
long[] nbrs;
string[] names;

public double this[long nbr, string name]


{
get
{
if ((nbr == nbrs[0]) && (name == names[0]))
return 275.25;
else if ((nbr == nbrs[1]) && (name == names[1]))
return 18.75;
else if ((nbr == nbrs[2]) && (name == names[2]))
return 50.00;
else if ((nbr == nbrs[3]) && (name == names[3]))
return 65.35;
else if ((nbr == nbrs[4]) && (name == names[4]))
return 25.55;
else
return 0.00;
}
}

public Catalog()
{
nbrs = new long[5];
nbrs[0] = 273974;
nbrs[1] = 539759;
nbrs[2] = 710234;
nbrs[3] = 220685;
nbrs[4] = 192837;
names = new string[5];

names[0] = "Women Double-faced wool coat";

names[1] = "Men Cotton Polo Shirt";

names[2] = "Children Cable-knit Sweater";

names[3] = "Women Floral Silk Tank Blouse";

names[4] = "Girls Jeans with Heart Belt";


}
}

C# 3.0 Practical Learning 650


public class Exercise
{
static int Main(string[] args)
{
var cat = new Catalog();

var itemNumber = 539759;


var itemDescription = "Men Cotton Polo Shirt";
var price = cat[itemNumber, itemDescription];

Console.WriteLine("Item #: {0}", itemNumber);


Console.WriteLine("Description: {0}", itemDescription);
Console.WriteLine("Unit Price: {0}", price);

Console.WriteLine();
return 0;
}
}

This would produce:


Item #: 539759
Description: Men Cotton Polo Shirt
Unit Price: 18.75

Press any key to continue . . .

In the above example, we first declared the variables to be passed as parameters to the
indexed property. You can also pass the parameter(s) directly on the instance of the
class. Here is an example:
public class Exercise
{
static int Main(string[] args)
{
var cat = new Catalog();

var price = cat[220685, "Women Floral Silk Tank Blouse"];

Console.WriteLine("Item #: 220685");
Console.WriteLine("Description: Women Floral Silk Tank Blouse");
Console.WriteLine("Unit Price: {0}", price);

Console.WriteLine();
return 0;
}
}

Just as you can create a two-dimensional indexed property, you can also create a
property that takes more than two parameters. Once again, it is up to you to decide
what type of parameter would be positioned where in the square brackets. Here is an
example of an indexed property that takes three parameters:
using System;

public class Catalog


{
public string this[long nbr, string name, double price]
{
get
C# 3.0 Practical Learning 651
{
return "Item #: " + nbr.ToString() + "\n" +
"Description: " + name + "\n" +
"Unit Price: " + price.ToString("C");
}
}
}

public class Exercise


{
static int Main(string[] args)
{
var cat = new Catalog();

Console.WriteLine("Item Description");
Console.WriteLine(cat[220685, "Women Floral Silk Tank Blouse",
50.00]);

Console.WriteLine();
return 0;
}
}

Overloading an Indexed Property

An indexer borrows various characteristics of a method. One of them is the ability to


create various indexers in the same class but all of them must have the same name:
this. Still, the various indexers of a class can return the same type of value. Because of
this, when creating the indexers, you must find a way to distinguish them. One way you
can do this, as seen with method overloading, consists of passing a different type of
parameter to each indexer. This is referred to as overloading.

To overload the this property, if two indexed properties take only one parameter, each
must take a different (data) type of parameter than the other. Here is an example:
using System;

public class StudentIdentifications


{
int[] studentIDs;
string[] fullnames;

// This property takes a student ID, as an integer,


// and it produces his/her name
public string this[int id]
{
get
{
for (int i = 0; i < studentIDs.Length; i++)
if (id == studentIDs[i])
return fullnames[i];

return "Unknown Student";


}
}

// This property takes a student name, as a string,


// and it produces his/her student ID
C# 3.0 Practical Learning 652
public int this[string name]
{
get
{
for (int i = 0; i < fullnames.Length; i++)
if (name == fullnames[i])
return studentIDs[i];

return 0;
}
}

public StudentIdentifications()
{
studentIDs = new int[6];
studentIDs[0] = 39472;
studentIDs[1] = 13957;
studentIDs[2] = 73957;
studentIDs[3] = 97003;
studentIDs[4] = 28947;
studentIDs[5] = 97395;

fullnames = new string[6];


fullnames[0] = "Paul Bertrand Yamaguchi";
fullnames[1] = "Ernestine Ngovayang";
fullnames[2] = "Patricia L Katts";
fullnames[3] = "Helene Mukoko";
fullnames[4] = "Joan Ursula Hancock";
fullnames[5] = "Arlette Mimosa";
}
}

public class Exercise


{
static int Main(string[] args)
{
var std = new StudentIdentifications();

Console.WriteLine("Student Identification");
Console.WriteLine("Student ID: 39472");
Console.WriteLine("Full Name: {0}\n", std[39472]);

Console.WriteLine("Student Identification");
Console.WriteLine("Full Name: Joan Ursula Hancock");
Console.WriteLine("Student ID: {0}\n", std["Joan Ursula
Hancock"]);

return 0;
}
}

This would produce:


Student Identification
Student ID: 39472
Full Name: Paul Bertrand Yamaguchi

Student Identification
Full Name: Joan Ursula Hancock
Student ID: 28947
C# 3.0 Practical Learning 653
Press any key to continue . . .

An indexer combines the features of an array and those of a method that takes one or
more parameters. As an array, an indexer can use one or more dimensions as we have
seen so far. Borrowing the features of a method, an indexer can take one or more
parameters and it can return a value. Besides passing different types of parameters to
various indexers, you can create some of them that take more than one parameter.
Here is an example:
using System;

public class Catalog


{
//double[] item;
long[] nbrs;
string[] names;
double[] prices;

// This property produces the name of an item, as a string,


// if it is given the item #, as a number
public string this[long nbr]
{
get
{
for (int i = 0; i < nbrs.Length; i++)
if (nbr == nbrs[i])
return names[i];

return "Unknown Item";


}
}

// This property produces the price of the item, as a number,


// if it is given the item name and its number
public double this[string name, long nbr]
{
get
{
for (int i = 0; i < 5; i++)
if ((nbr == nbrs[i]) && (name == names[i]))
return prices[i];

return 0.00;
}
}

public Catalog()
{
nbrs = new long[5];
nbrs[0] = 273974;
nbrs[1] = 539759;
nbrs[2] = 710234;
nbrs[3] = 220685;
nbrs[4] = 192837;

names = new string[5];


names[0] = "Women Double-faced wool coat";
names[1] = "Men Cotton Polo Shirt";

C# 3.0 Practical Learning 654


names[2] = "Children Cable-knit Sweater";
names[3] = "Women Floral Silk Tank Blouse";

names[4] = "Girls Jeans with Heart Belt";

prices = new double[5];


prices[0] = 275.25;
prices[1] = 18.75;
prices[2] = 50.00;
prices[3] = 65.35;
prices[4] = 25.55;
}
}

public class Exercise


{
static int Main(string[] args)
{
var cat = new Catalog();

Console.WriteLine("Item Identification");
Console.WriteLine("Item #: 539759");
Console.WriteLine("Unit Price: {0}\n", cat[539759]);

Console.WriteLine("Item Identification");
Console.WriteLine("Item #: 192837");
Console.WriteLine("Description: Girls Jeans with Heart Belt");
Console.WriteLine("Unit Price: {0}\n",
cat["Girls Jeans with Heart Belt", 192837]);

return 0;
}
}

This would produce:


Item Identification
Item #: 539759
Unit Price: Men Cotton Polo Shirt

Item Identification
Item #: 192837
Description: Girls Jeans with Heart Belt
Unit Price: 25.55

Press any key to continue . . .

Read/Write Indexed Properties


 

Introduction

So far, we have purposely used indexed properties that only produced a value. This type
is used when you are (always) in charge of specifying the values of the elements of the
array: the only action you would expect from the user is to retrieve the value of the
property. This is referred to as a read-only property. In some cases, you will use a

C# 3.0 Practical Learning 655


property created by someone else. You may want to specify the value of an element of
the array. In the same way, you may create an indexed property and you want the
users of that property to be able to specify the value of the array.

If you want an indexed property to be read/write, besides the get accessor as we have
been using it so far, you should also include a set accessor.

A Read/Write Property of a Primitive Type

To create a read/write indexed property, you should include a set accessor for the
property. In the set accessor, assign the value contextual keyword to the field indexed
with the this parameter. Here is an example of a read/write indexed property that
includes a set accessor:
public class Number
{
double[] Numbers;

public double this[int i]


{
get { return Numbers[i]; }
set { Numbers[i] = value; }
}
}

After creating the read/write property, you can assign its values outside of the class. In
other words, clients of the class can change the values to its elements. Remember that
the advantage of an indexed property is that each element of the arrayed field can be
accessed from the instance of the class by directly applying the square brackets and the
(appropriate) index to it. Here is an example:
using System;

public class Number


{
double[] Numbers = new double[5];

public double this[int i]


{
get { return Numbers[i]; }
set { Numbers[i] = value; }
}
}

public class Program


{
static int Main(string[] args)
{
var nbr = new Number();

nbr[2] = 2.37094;

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


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

Console.WriteLine();
return 0;
C# 3.0 Practical Learning 656
}
}

This would produce:


Number 1: 0
Number 2: 0
Number 3: 2.37094
Number 4: 0
Number 5: 0

Press any key to continue . . .

Based on this, a type of formula to create and use a basic indexed property is:
class ClassName
{
DataType[] ArrayName = new DataType[Index];

public DataType this[int i]


{
get { return ArrayName[i]; }
set { ArrayName[i] = value; }
}
}

class Program
{
static int Main(string[] args)
{
ClassName Variable = new ClassName();

Variable[Low-Index] = Value1;
. . .
Variable[High-Index] = Value_n;

return 0;
}
}

We saw that the index of a property could be a value other than an integer-based. For
example, we created an index that was a string type. For such a property, if you make it
read/write, you can assign its values outside of the class. Here is an example of a
read/write string-based indexed property:
using System;

public class Philosopher


{
string[] phil = new string[8];

public string this[int i]


{
get { return phil[i]; }
set { phil[i] = value; }
}
}

public class Program


{
C# 3.0 Practical Learning 657
static int Main(string[] args)
{
var thinker = new Philosopher();

thinker[5] = "Stuart Rachels";

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


Console.WriteLine("Philosopher: {0}", thinker[i]);

Console.WriteLine();
return 0;
}
}

This would produce:


Philosopher:
Philosopher:
Philosopher:
Philosopher:
Philosopher:
Philosopher: Stuart Rachels
Philosopher:
Philosopher:

Press any key to continue . . .

The same rules would apply to a read/write indexed property that can receive Boolean
or decimal values.

C# 3.0 Practical Learning 658


Classes and Indexers
 

Fundamentals of Indexed Properties and Classes


 

Introduction

In the previous lesson, we learned to create and use indexer that were taking
parameters of primitive types. Just as we did with primitive types, you can create an
indexer that is of a class type. For example, you can create a class so that one of the its
fields declared as an array can be accessed with an index directly applied to an instance
of the class.

Practical Learning: Introducing Indexers and Classes

1. Start a new Console Application named PropertyRental2

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to Property and press Enter

4. Change the file as follows:


 
C# 3.0 Practical Learning 659
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental2
{
public enum Condition
{
Excellent,
Good,
NeedsRepair,
Unknown
}

public class Property


{
private long propCode;
private Condition cond;
private short beds;
private float baths;
private decimal val;

public long PropertyCode


{
get { return propCode; }
set { propCode = value; }
}

public Condition PropertyCondition


{
get { return cond; }
set { cond = value; }
}

public short Bedrooms


{
get { return beds; }
set { beds = value; }
}

public float Bathrooms


{
get { return (baths <= 0) ? 0.00f : baths; }
set { baths = value; }
}

public decimal MonthlyRent


{
get { return (val <= 0) ? 0.00M : val; }
set { val = value; }
}

public Property()
{
Random rnd = new Random();
propCode = rnd.Next(100000, 999999);
cond = Condition.Unknown;
beds = 0;
baths = 0.0f;
C# 3.0 Practical Learning 660
val = 0.00M;
}

public override string ToString()


{
return "Property #: " + PropertyCode +
"\nCondition: " + PropertyCondition +
"\nBedrooms: " + Bedrooms +
"\nBathrooms: " + Bathrooms +
"\nMonthly Rent: " + MonthlyRent.ToString("C");
}
}
}

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to PropertyListing and press Enter

7. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental2
{
public class PropertyListing
{
public Property[] props;

public string this[long code]


{
get
{
for (int i = 0; i < props.Length; i++)
if (code == props[i].PropertyCode)
return "Property #: " + props[i].PropertyCode +
"\nCondition: " +
props[i].PropertyCondition +
"\nBedrooms: " + props[i].Bedrooms +
"\nBathrooms: " + props[i].Bathrooms +
"\nMonthly Rent: " +
props[i].MonthlyRent.ToString("C");
return "Unidentifiable Property";
}
}

public PropertyListing()
{
Random rnd = new Random();
props = new Property[40];

// Create a few properties ready to be rented


props[0] = new Property();
props[0].PropertyCode = rnd.Next(100000, 999999);
props[0].PropertyCondition = Condition.Excellent;
props[0].Bedrooms = 5;
props[0].Bathrooms = 3.5f;
C# 3.0 Practical Learning 661
props[0].MonthlyRent = 2650;

props[1] = new Property();


props[1].PropertyCode = rnd.Next(100000, 999999);
props[1].PropertyCondition = Condition.Excellent;
props[1].Bedrooms = 3;
props[1].Bathrooms = 2.5f;
props[1].MonthlyRent = 1750;

props[2] = new Property();


props[2].PropertyCode = rnd.Next(100000, 999999);
props[2].PropertyCondition = Condition.Good;
props[2].Bedrooms = 4;
props[2].Bathrooms = 2.5f;
props[2].MonthlyRent = 2450;

props[3] = new Property();


props[3].PropertyCode = rnd.Next(100000, 999999);
props[3].PropertyCondition = Condition.Excellent;
props[3].Bedrooms = 1;
props[3].Bathrooms = 1.0f;
props[3].MonthlyRent = 880;

props[4] = new Property();


props[4].PropertyCode = rnd.Next(100000, 999999);
props[4].PropertyCondition = Condition.Excellent;
props[4].Bedrooms = 3;
props[4].Bathrooms = 2.5f;
props[4].MonthlyRent = 1880;

props[5] = new Property();


props[5].PropertyCode = rnd.Next(100000, 999999);
props[5].PropertyCondition = Condition.Good;
props[5].Bedrooms = 2;
props[5].Bathrooms = 1.0f;
props[5].MonthlyRent = 1050;

// Since we don't yet have a complete list of properties


// Create some empty ones
for (int i = 6; i < 40; i++)
{
props[i] = new Property();
}
}
}
}

8. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental2
{
public class Program
{
static void Main(string[] args)
C# 3.0 Practical Learning 662
{
PropertyListing properties = new PropertyListing();
long lngCode;

Console.WriteLine("Here is a list of our properties by


code");
for (int i = 0; i < 6; i++)
Console.WriteLine("Property Code: {0}",
properties.props[i].PropertyCode);

try
{
Console.Write("Enter Property Code: ");
lngCode = long.Parse(Console.ReadLine());

Console.WriteLine("======================================");
Console.WriteLine("Property Information");

Console.WriteLine("--------------------------------------");
Console.WriteLine(properties[lngCode]);

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

}
catch (FormatException)
{
Console.WriteLine("=- Invalid Property Code -=");
}
}
}
}

9. Press Ctrl + F5 to execute the application. Here is an example:


 
Here is a list of our properties by code
Property Code: 355443
Property Code: 653004
Property Code: 800118
Property Code: 839375
Property Code: 148561
Property Code: 697001
Enter Property Code: 697001
======================================
Property Information
--------------------------------------
Property #: 697001
Condition: Good
Bedrooms: 2
Bathrooms: 1
Monthly Rent: $1,050.00
======================================
Press any key to continue . . .

10.Close the DOS window

An Integer-Based Indexed Property

C# 3.0 Practical Learning 663


Before designing an indexer that is class-based, first create the class that will be used as
the data type. The class can be simple or complex as you judge it necessary. Here is an
example of a simple class:
public class Student
{
public string FirstName;
public string LastName;
public int Gender;
}

When creating the class that will host the indexed property, declare an array field for the
class. Then, create the this property with the desired accessor(s). Here is an example:
public class Student
{
public string FirstName;
public string LastName;
public int Gender;
}

public class SchoolRegistration


{
Student[] std = new Student[5];

public Student this[int i]


{
get { return std[i]; }
}
}

After creating the indexing class, you can use it and access the indexer; for example,
you can retrieve its value(s). Here is an example:
using System;

public class Student


{
public string FirstName;
public string LastName;
public int Gender;
}

public class SchoolRegistration


{
Student[] std = new Student[5];

public Student this[int i]


{
get { return std[i]; }
}

public SchoolRegistration()
{
std[0] = new Student();
std[0].FirstName = "Alfredo";
std[0].LastName = "Olmos";
std[0].Gender = 2;

std[1] = new Student();


C# 3.0 Practical Learning 664
std[1].FirstName = "Patricia";
std[1].LastName = "Katts";
std[1].Gender = 1;

std[2] = new Student();


std[2].FirstName = "Josiane";
std[2].LastName = "Euler";
std[2].Gender = 1;

std[3] = new Student();


std[3].FirstName = "Joan";
std[3].LastName = "Jones";
std[3].Gender = 3;

std[4] = new Student();


std[4].FirstName = "George";
std[4].LastName = "Paulson";
std[4].Gender = 2;
}
}

public class Exercise


{
static int Main(string[] args)
{
var pupils = new SchoolRegistration();

for (var i = 0; i < 5; i++)


{
Student pupil = pupils[i];

Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine("First Name: {0}", pupil.FirstName);
Console.WriteLine("Last Name: {0}", pupil.LastName);
Console.WriteLine("Gender: {0}\n",
(pupil.Gender == 1 ? "Female" :
(pupil.Gender == 2 ? "Male" : "Unknown")));
}

return 0;
}
}

This would produce:


Student Information
---------------------
First Name: Alfredo
Last Name: Olmos
Gender: Male

Student Information
---------------------
First Name: Patricia
Last Name: Katts
Gender: Female

Student Information
---------------------
C# 3.0 Practical Learning 665
First Name: Josiane
Last Name: Euler
Gender: Female

Student Information
---------------------
First Name: Joan
Last Name: Jones
Gender: Unknown

Student Information
---------------------
First Name: George
Last Name: Paulson
Gender: Male

Press any key to continue . . .

Practical Learning: Using an Integer-Based Indexer

1. To create an indexer that takes an integer and returns an object, access the
PropertyListing.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
public class PropertyListing
{
public Property[] props;

public Property this[int i]


{
get { return props[i]; }
}

public PropertyListing()
{
. . . No Change
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental2
{
public class Program
{
C# 3.0 Practical Learning 666
static void Main(string[] args)
{
PropertyListing properties = new PropertyListing();

Console.WriteLine("Here is a list of our properties");


for (int i = 0; i < 6; i++)
{
Property prop = properties[i];

Console.WriteLine("Property Information");

Console.WriteLine("--------------------------------------");
Console.WriteLine("Property #: {0}",
prop.PropertyCode);
Console.WriteLine("Condition: {0}",
prop.PropertyCondition);
Console.WriteLine("Bedrooms: {0}", prop.Bedrooms);
Console.WriteLine("Bathrooms: {0}", prop.Bathrooms);
Console.WriteLine("Monthly Rent: {0}",
prop.MonthlyRent.ToString("C"));

Console.WriteLine("======================================");
}
}
}
}

3. Press Ctrl + F5 to execute the application

4. Close the DOS window

An Indexed Property Using Another Primitive Type

The above implementation of the SchoolRegistration class easily allowed us to locate an


element of the array by specifying its integer-based index. As done for primitive types,
an indexer can take a parameter other than an integer. In some cases, you may use
your class or a class created by someone else and need to access an element of the
array without information other than its index. Consider the following program:
public enum Classification
{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;

public override string ToString()


{
string str = "Student ID: " + StudentID +
"\nFirst Name: " + FirstName +
"\nLast Name: " + LastName +

C# 3.0 Practical Learning 667


"\nGender: " + Gender;
return str;
}
}

public class SchoolRegistration


{
Student[] std = new Student[50];

public Student this[...]


{
}
}

Previously, we saw that you could create an indexer that takes a type than an integer.
For example, we saw that a string could be used as an index.

By now, we know that a basic indexed property produces (or all the indexed properties
we have studied so far produce) only one value. If you have a class that has only one
field, this would be enough. In reality, most of the time, a class has many fields. In such
a case, when you create an indexer , you need to be able to refer to one exact element
of the array. To make this possible, you must define a way to point to the particular
element you want. One way you can do this is to use one field of the class as a
reference. This is better if that field holds unique values among the other elements of
the array. For our Student class, we could use the StudentID field (because we will
make sure that each student has a unique ID). You can start the property as follows:
public class SchoolRegistration
{
Student[] std = new Student[5];

public Student this[long id]


{
}
}

When a user uses this property, he or she must provide a value that uniquely identifies
an element of the array. You in turn, when you get this value, you can search for it in
the array. If you find it and the array has a get accessor, you can then return the
desired but appropriate value. Here is how this can be done:
public class SchoolRegistration
{
Student[] students = new Student[50];

public Student this[long id]


{
get
{
for (int i = 0; i < students.Length; i++)
{
if (students[i].StudentID == id)
return students[i];
}
// Unknown student or the number was not found
return null;
}
}

C# 3.0 Practical Learning 668


}

After creating the indexer, you can use it. Once again, you must follow the rules of a
method that takes an argument and returns a value other than void. In this case, the
indexer must take a string and it must return a Student object. Here is an example:
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;

public override string ToString()


{
string str = "Student ID: " + StudentID +
"\nFirst Name: " + FirstName +
"\nLast Name: " + LastName +
"\nGender: " + Gender;
return str;
}
}

public class SchoolRegistration


{
Student[] students = new Student[50];

public Student this[long id]


{
get
{
for (int i = 0; i < students.Length; i++)
{
if (students[i].StudentID == id)
return students[i];
}
// Unknown student or the number was not found
return null;
}
}

public SchoolRegistration()
{
students[0] = new Student();
students[0].StudentID = 917294;
students[0].FirstName = "Helene";
students[0].LastName = "Mukoko";
students[0].Gender = Classification.Female;

students[1] = new Student();


students[1].StudentID = 283764;
C# 3.0 Practical Learning 669
students[1].FirstName = "Patrice";
students[1].LastName = "Katts";
students[1].Gender = Classification.Unknown;

students[2] = new Student();


students[2].StudentID = 192046;
students[2].FirstName = "Armand";
students[2].LastName = "Essono";
students[2].Gender = Classification.Male;

students[3] = new Student();


students[3].StudentID = 618268;
students[3].FirstName = "Bertrand";
students[3].LastName = "Yamaguchi";
students[3].Gender = Classification.Male;

students[4] = new Student();


students[4].StudentID = 820648;
students[4].FirstName = "Hortense";
students[4].LastName = "McNeal";
students[4].Gender = Classification.Female;
}
}

public class Exercise


{
static int Main(string[] args)
{
var pupils = new SchoolRegistration();
var pupil = pupils[820648];

Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine("First Name: {0}", pupil.FirstName);
Console.WriteLine("Last Name: {0}", pupil.LastName);
Console.WriteLine("Gender: {0}\n", pupil.Gender);

pupil = pupils[192046];

Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine("First Name: {0}", pupil.FirstName);
Console.WriteLine("Last Name: {0}", pupil.LastName);
Console.WriteLine("Gender: {0}\n", pupil.Gender);

return 0;
}
}

This would produce:


Student Information
---------------------
First Name: Hortense
Last Name: McNeal
Gender: Female

Student Information
---------------------
First Name: Armand
C# 3.0 Practical Learning 670
Last Name: Essono
Gender: Male

Press any key to continue . . .

Topics on Indexed Properties and Classes


 

A Class as Index

As opposed to returning a class, an indexer can use a class as its index. When creating
such a property, the primary action you must take is to include a class and its name as a
parameter to the this property. You can start such a class as follows:
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;
}

public class SchoolRegistration


{
public string this[Student std]
{
}
}

When implementing the class, you should proceed the same way we have done so far
following the rules of a method that takes an argument and returns a value other than
void. Here is an example:

public class SchoolRegistration


{
Student[] students = new Student[50];

public string this[Student std]


{
get
{
for (int i = 0; i < students.Length; i++)
{
if (std.StudentID == students[i].StudentID)

return "Student ID: " + students[i].StudentID +


"\nFirst Name: " + students[i].FirstName +

C# 3.0 Practical Learning 671


"\nLast Name: " + students[i].LastName +
"\nGender: " + students[i].Gender;
}

// Unknown student or the number was not found


return "";
}
}
}

After creating the property, you can use it. To do this, you must pass an object that is
the type of the index. You can then use the returned value as you see fit. Here is an
example:
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;
}

public class SchoolRegistration


{
Student[] students = new Student[50];

public string this[Student std]


{
get
{
for (int i = 0; i < students.Length; i++)
{
if (std.StudentID == students[i].StudentID)

return "Student ID: " + students[i].StudentID +


"\nFirst Name: " + students[i].FirstName +
"\nLast Name: " + students[i].LastName +
"\nGender: " + students[i].Gender;
}

// Unknown student or the number was not found


return "";
}
}

public SchoolRegistration()
{
students[0] = new Student();
students[0].StudentID = 917294;
students[0].FirstName = "Helene";
students[0].LastName = "Mukoko";
C# 3.0 Practical Learning 672
students[0].Gender = Classification.Female;

students[1] = new Student();


students[1].StudentID = 283764;
students[1].FirstName = "Patrice";
students[1].LastName = "Katts";
students[1].Gender = Classification.Unknown;

students[2] = new Student();


students[2].StudentID = 192046;
students[2].FirstName = "Armand";
students[2].LastName = "Essono";
students[2].Gender = Classification.Male;

students[3] = new Student();


students[3].StudentID = 618268;
students[3].FirstName = "Bertrand";
students[3].LastName = "Yamaguchi";
students[3].Gender = Classification.Male;

students[4] = new Student();


students[4].StudentID = 820648;
students[4].FirstName = "Hortense";
students[4].LastName = "McNeal";
students[4].Gender = Classification.Female;

students[5] = new Student();


students[5].StudentID = 917394;
students[5].FirstName = "Alfredo";
students[5].LastName = "Olmos";
students[5].Gender = Classification.Unknown;

students[6] = new Student();


students[6].StudentID = 163864;
students[6].FirstName = "Josiane";
students[6].LastName = "Euler";
students[6].Gender = Classification.Female;

students[7] = new Student();


students[7].StudentID = 826384;
students[7].FirstName = "Joan";
students[7].LastName = "Jones";
students[7].Gender = Classification.Female ;
}
}

public class Exercise


{
static int Main(string[] args)
{
var pupils = new SchoolRegistration();

var pupil = new Student();


pupil.StudentID = 820648;

var strStudent = pupils[pupil];


Console.WriteLine("=====================");
Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine(strStudent);
C# 3.0 Practical Learning 673
//pupil = new Student();
pupil.StudentID = 192046;
strStudent = pupils[pupil];

Console.WriteLine("=====================");
Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine(strStudent);

Console.WriteLine("=====================\n");
return 0;
}
}

This would produce:


=====================
Student Information
---------------------
Student ID: 820648
First Name: Hortense
Last Name: McNeal
Gender: Female
=====================
Student Information
---------------------
Student ID: 192046
First Name: Armand
Last Name: Essono
Gender: Male
=====================

Press any key to continue . . .

You can also directly pass an instance of the class in the square brackets of the object
that holds the indexed property, as long as you specify the object. Here is an example:
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;

public Student()
{
}

public Student(long id)


{
C# 3.0 Practical Learning 674
this.StudentID = id;
}
}

public class SchoolRegistration


{
Student[] students = new Student[50];

public string this[Student std]


{
. . . No Change
}

public SchoolRegistration()
{
. . . No Change
}
}

public class Exercise


{
static int Main(string[] args)
{
var pupils = new SchoolRegistration();

var strStudent = pupils[new Student(618268)];

Console.WriteLine("=====================");
Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine(strStudent);

Console.WriteLine("=====================\n");
return 0;
}
}

This would produce:


=====================
Student Information
---------------------
Student ID: 618268
First Name: Bertrand
Last Name: Yamaguchi
Gender: Male
=====================

Press any key to continue . . .

Overloading a Class-Based Indexed Property

As mentioned for indexers that return primitive types, you can overload an indexed
property that produces a class. You do this following the same rules applied to method
overloading and arrays:

 If two indexed properties take only one parameter, each must take a different type
of parameter than the other. The parameter can be a primitive type or a class. Here

C# 3.0 Practical Learning 675


are examples:
 
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Major


{
public string Name;
public int CreditsRequired;
}

public class Student


{
public long StudentNumber;
public string FullName;
public Classification Gender;

public override string ToString()


{
string str = "Student #: " + StudentNumber.ToString() +
"\nFull Name: " + FullName +
"\nGender: " + Gender;
return str;
}
}

public class StudentRegistration


{
private Student[] std = new Student[5];

public StudentRegistration()
{
std[0] = new Student();
std[0].StudentNumber = 304850;
std[0].FullName = "Helene Mukoko";
std[0].Gender = Classification.Female;

std[1] = new Student();


std[1].StudentNumber = 926304;
std[1].FullName = "Patrice Katts";
std[1].Gender = Classification.Unknown;

std[2] = new Student();


std[2].StudentNumber = 330647;
std[2].FullName = "Armand Essono";
std[2].Gender = Classification.Male;

std[3] = new Student();


std[3].StudentNumber = 631846;
std[3].FullName = "Bertrand Yamaguchi";
std[3].Gender = Classification.Male;

std[4] = new Student();


C# 3.0 Practical Learning 676
std[4].StudentNumber = 209374;
std[4].FullName = "Anselme Bongos";
std[4].Gender = Classification.Male;
}

// This property takes a string and produces a Student object


public Student this[string strFullName]
{
get
{
for (int i = 0; i < std.Length; i++)
{
if (std[i].FullName == strFullName)
return std[i];
}
return null;
}
}

// This property takes a number and produces a Student object


public Student this[long nbr]
{
get
{
for (int i = 0; i < std.Length; i++)
{
if( nbr == std[i].StudentNumber )
return std[i];
}
return null;
}
}

// This property takes a major produces its definition


public string this[Major maj]
{
get
{
return "Major: " + maj.Name +
" - " + maj.CreditsRequired +
" Credits Required";
}
}
}

public class Exercise


{
static int Main(string[] args)
{
var pupils = new StudentRegistration();

var m1 = new Major();


m1.Name = "Computer Sciences";
m1.CreditsRequired = 120;

var m2 = new Major();


m2.Name = "Informtation Technology";
m2.CreditsRequired = 120;

Console.WriteLine("=-= Student Identification =-=");


C# 3.0 Practical Learning 677
Console.WriteLine(pupils["Helene Mukoko"]);
Console.WriteLine(pupils[m1]);

Console.WriteLine("--------------------------------------------------");

Console.WriteLine("=-= Student Identification =-=");


Console.WriteLine(pupils[330647]);
Console.WriteLine(pupils[m2]);

Console.WriteLine("--------------------------------------------------");
Console.WriteLine();

return 0;
}
}

This would produce:


=-= Student Identification =-=
Student #: 304850
Full Name: Helene Mukoko
Gender: Female
Major: Computer Sciences - 120 Credits Required
--------------------------------------------------
=-= Student Identification =-=
Student #: 330647
Full Name: Armand Essono
Gender: Male
Major: Information Technology - 120 Credits Required
--------------------------------------------------

Press any key to continue . . .

 If one property takes only one parameter, the other(s) can take more than one
parameter. An indexed property can take different parameters of primitive types as
seen in the previous lesson. An indexer can also take two or more classes as
parameters. An indexed property can also take a mix of primitive and class types as
parameters.
Here are examples:
 
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;

public Student()
{

C# 3.0 Practical Learning 678


}

public Student(long id)


{
this.StudentID = id;
}

public override string ToString()


{
return "Student ID: " + StudentID +
"\nFirst Name: " + FirstName +
"\nLast Name: " + LastName +
"\nGender: " + Gender;
}
}

public enum CourseDelivery


{
FaceToFace,
Online,
Both // Student Choose
}

public class Course


{
public string ShortName;
public string LongName;
public string Description;
public int Credits;
public CourseDelivery DeliveryMode;

public Course()
{
}

public Course(string name)


{
ShortName = name;
}

public override string ToString()


{
return "Course: " + ShortName +
"\nFull Name: " + LongName +
"\nCredits: " + Credits +
"\nDescription: " + Description +
"\nDelivery: " + DeliveryMode;
}
}

public class SchoolRegistration


{
Student[] students = new Student[50];
Course[] classes = new Course[3];

// This indexer takes a student id and


// returns the student information
public Student this[long id]
{
get
C# 3.0 Practical Learning 679
{
for (int i = 0; i < students.Length; i++)
{
if (id == students[i].StudentID)
return students[i];
}
// Unknown student or the number was not found
return null;
}
}

// This indexer takes a course short name and


// it produces a summary of the course information
public Course this[string name]
{
get
{
for (int i = 0; i < classes.Length; i++)
{
if (name == classes[i].ShortName)
return classes[i];
}

// Unknown course
return null;
}
}

public string this[Course ToAttend, Student registrant]


{
get
{
// First check that the class exists
for (int i = 0; i < classes.Length; i++)
{
if (ToAttend.ShortName == classes[i].ShortName)
{
// If the class exists, then check if the student
exists
for (int j = 0; j < students.Length; j++)
{
if (registrant.StudentID ==
students[j].StudentID)
{
return "Student Identification --\n " +
"Student ID: " +
students[j].StudentID +
"\n Full Name: " +
students[j].LastName +
", " + students[j].FirstName +
"\nClass to Attend --\n Course:
" +
classes[i].ShortName + " - " +
classes[i].LongName + " (" +
classes[i].Credits + ")" +
"\n Delivery: " +
classes[i].DeliveryMode;
}
}
}
C# 3.0 Practical Learning 680
}

return "Invalid Registration - You may have to start over";


}
}

// This property takes information used to register


// a student to a course
// It also specifies whether the student is willing
// to get in the waiting list in case another students drops out
public string this[Student stud, Course Class, bool WaitingList]
{
get
{
// Check that the student information is valie
for (int j = 0; j < students.Length; j++)
{
if (stud.StudentID == students[j].StudentID)
{
// Now that the student information has been found,
// check if the course information is correct
for (int i = 0; i < classes.Length; i++)
{
if (Class.ShortName == classes[i].ShortName)
{
// If the class exists, then check
// if the student exists
return "Student Identification --\n " +
"Student ID: " +
students[j].StudentID +
"\n Full Name: " +
students[j].LastName +
", " + students[j].FirstName +
"\nClass to Attend --\n Course:
" +
classes[i].ShortName + " - " +
classes[i].LongName + " (" +
classes[i].Credits + ")" +
"\n Delivery: " +
classes[i].DeliveryMode +
"\nStudent is willing to get " +
"on the waiting list: "
+ WaitingList;
}
}
}
}

return "Invalid Registration - You may have to start over";


}
}

public SchoolRegistration()
{
students[0] = new Student();
students[0].StudentID = 917294;
students[0].FirstName = "Helene";
students[0].LastName = "Mukoko";
students[0].Gender = Classification.Female;

C# 3.0 Practical Learning 681


students[1] = new Student();
students[1].StudentID = 283764;
students[1].FirstName = "Patrice";
students[1].LastName = "Katts";
students[1].Gender = Classification.Unknown;

students[2] = new Student();


students[2].StudentID = 192046;
students[2].FirstName = "Armand";
students[2].LastName = "Essono";
students[2].Gender = Classification.Male;

students[3] = new Student();


students[3].StudentID = 618268;
students[3].FirstName = "Bertrand";
students[3].LastName = "Yamaguchi";
students[3].Gender = Classification.Male;

students[4] = new Student();


students[4].StudentID = 820648;
students[4].FirstName = "Hortense";
students[4].LastName = "McNeal";
students[4].Gender = Classification.Female;

classes[0] = new Course();


classes[0].ShortName = "PHIL140";
classes[0].LongName = "Philosophy - Contemporary Moral Issues";
classes[0].Credits = 3;
classes[0].Description = "An exploration of how " +
"philosophical analysis can be " +
"\n\t\ta foundation for thinking " +
"clearly about moral issues. " +
"\n\t\tProblems analyzed include such "
+
"widely debated issues " +
"\n\t\tas abortion, euthanasia, " +
"the death penalty, " +
"\n\t\thomosexuality, pornography, " +
"reverse discrimination, " +
"\n\t\tbusiness ethics, sexual " +
"equality, and economic equity.";
classes[1] = new Course();
classes[1].ShortName = "MATH140";
classes[1].LongName = "Calculus I";
classes[1].Credits = 4;
classes[1].Description = "An introduction to calculus. " +
"Topics include functions, " +
"\n\t\tthe sketching of graphs of " +
"functions, limits, continuity, " +
"\n\t\tderivatives and applications of "
+
"the derivative, definite " +
"\n\t\tand indefinite integrals, " +
"and calculation of area.";
classes[2] = new Course();
classes[2].ShortName = "ASTR100";
classes[2].LongName = "Introduction to Astronomy";
classes[2].Credits = 3;
classes[2].Description = "A discussion of the major areas " +
"of astronomy. Topics " +
C# 3.0 Practical Learning 682
"\n\t\tinclude the solar system, " +
"stars and stellar evolution, " +
"\n\t\tand galaxies. Current topics " +
"in astronomy are also " +
"\n\t\tdiscussed.";
}
}

public class Exercise


{
static int Main(string[] args)
{
var pupils = new SchoolRegistration();

Student std = new Student(917294);


Course crs = new Course("MATH140");

Console.WriteLine("================================================");
Console.WriteLine("Student Registration");
Console.WriteLine("------------------------------------------");
Console.WriteLine(pupils[crs, std]);

std = new Student(820648);


crs = new Course("PHIL140");

Console.WriteLine("================================================");
Console.WriteLine("Student Registration");
Console.WriteLine("------------------------------------------");
Console.WriteLine(pupils[std, crs, true]);

Console.WriteLine("================================================\n");
return 0;
}
}

This would produce:


================================================
Student Registration
------------------------------------------
Student Identification --
Student ID: 917294
Full Name: Mukoko, Helene
Class to Attend --
Course: MATH140 - Calculus I (4)
Delivery: FaceToFace
================================================
Student Registration
------------------------------------------
Student Identification --
Student ID: 820648
Full Name: McNeal, Hortense
Class to Attend --
Course: PHIL140 - Philosophy - Contemporary Moral Issues (3)
Delivery: FaceToFace
Student is willing to get on the waiting list: True
================================================

Press any key to continue . . .


C# 3.0 Practical Learning 683
Practical Learning: Overloading an Indexer

1. To overload the indexer, access the PropertyListing.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
public class PropertyListing
{
public Property[] props;

public Property this[int i]


{
get
{
if ((i >= 0) && (i < 40))
return props[i];
else return null;
}
}

public Property this[long code]


{
get
{
for (int i = 0; i < props.Length; i++)
if (code == props[i].PropertyCode)
return props[i];
return null;
}
}

public PropertyListing()
{
. . . No Change
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental2
{
public class Program
{
static void Main(string[] args)
{
PropertyListing properties = new PropertyListing();
C# 3.0 Practical Learning 684
long lngCode;

Console.WriteLine("Here is a list of our properties by


code");
for (int i = 0; i < 6; i++)
Console.WriteLine("Property Code: {0}",
properties.props[i].PropertyCode);

try
{
Console.Write("Enter Property Code: ");
lngCode = long.Parse(Console.ReadLine());

Console.WriteLine("======================================");
Console.WriteLine("Property Information");

Console.WriteLine("--------------------------------------");
Console.WriteLine(properties[lngCode]);

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

}
catch (FormatException)
{
Console.WriteLine("=- Invalid Property Code -=");
}
}
}
}

3. Press Ctrl + F5 to execute the application 

4. Close the DOS window

Read/Write Indexed Properties

As done for a primitive type, you can allow the clients of your indexer to assign values to
the array's elements. Once again, when defining the property, you should include a set
accessor to it. In the set accessor, you should assign the value keyword to an element
of the array. Here is an example:
public class SchoolRegistration
{
Student[] std = new Student[5];

public Student this[int i]


{
get { return std[i]; }
set { std[i] = value; }
}
}

After doing this, you can create an element of the array by applying the square brackets
to the instance of the class and assigning the desired value to it. The problem with the
class is that, since it may have many fields (or properties), to completely define each
element, you must provide a value to the member variables of the class itself. Here is an
example:
C# 3.0 Practical Learning 685
using System;

public enum Classification


{
Female,
Male,
Unknown
}

public class Student


{
public long StudentID;
public string FirstName;
public string LastName;
public Classification Gender;

public override string ToString()


{
string str = "Student ID: " + StudentID +
"\nFirst Name: " + FirstName +
"\nLast Name: " + LastName +
"\nGender: " + Gender;
return str;
}
}

public class SchoolRegistration


{
Student[] std = new Student[5];

public Student this[int i]


{
get { return std[i]; }
set { std[i] = value; }
}
}

public class Exercise


{
static int Main(string[] args)
{
var registration = new SchoolRegistration();

var stud = new Student();


stud.StudentID = 604057;
stud.FirstName = "Gertrude";
stud.LastName = "Monayong";
stud.Gender = Classification.Female;
registration[2] = stud;

Console.WriteLine("Student Information");
Console.WriteLine("---------------------");
Console.WriteLine("First Name: {0}", registration[2].FirstName);
Console.WriteLine("Last Name: {0}", registration[2].LastName);
Console.WriteLine("Gender: {0}\n",registration[2].Gender);

return 0;
}
}

C# 3.0 Practical Learning 686


This would produce:
Student Information
---------------------
First Name: Gertrude
Last Name: Monayong
Gender: Female

Press any key to continue . . .

C# 3.0 Practical Learning 687


Introduction to Collections
 

Array-Based Lists
 

Introduction

A collection, also called a list, is many items of the same kind grouped into one entity.
The collection can be based on simple numbers, basic symbols, dates, strings, times.
The collection can also be made of objects that each is made of internal values. This
means that a collection can be made of such objects as houses, people, cars, countries,
electronic devices. The primary rule to observe is that all items included in a list must be
described using the same characteristics. Based on this, if the collection is made of cars,
it should contain only cars, not cars and countries.

There are various types of lists or collections. An array-based list is one whose number
of items is known in advance. For example, an array-based collection of 10 cars contains
10 cars, may-be less but not more (in reality, the Array class of the .NET Frameword
provides a method used to expand an array).

Setting Up a Collection

To use a collection as an entity, you can create a class for it. This class would be used to
add items in the collection, to remove items in the list, or to perform other necessary
operations. You can start a simple class as follows:
class Collection
{
public Collection()
{
}
}

After creating the class for a collection, the collection becomes an object and its class
can be used like any other. This means that, before using the collection, you can declare
a variable for it. Here is an example:

using System;

class Collection
{
public Collection()
{
}
}

C# 3.0 Practical Learning 688


public class Exercise
{
static int Main(string[] args)
{
var list = new Collection();

return 0;
}
}

The Number of Items in a Collection

For an array-based list, because you must specify the number of items that the list will
contain, you can declare an array as a field. Here is an example:
class Collection
{
// This collection will be a list of decimal numbers
private double[] Item = new double[20];

// Our default constructor, used to initialize the collection


public Collection()
{
}
}

Although you can initialize an array in a C# class, remember that you can also use a
constructor to initialize it. Here is an example:
class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;

#region This section is used to set up the collection


// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
}
#endregion
}

A primary accessory you need when using a list is a count of the number of items in the
list when/as they are added or deleted. This accessory is primarily a private field as a
simple natural number. When the class is declared, this member variable should be set
to 0 to indicate that the list is primarily empty:
class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;
// This is the size of the collection
private int size;

C# 3.0 Practical Learning 689


#region This section is used to set up the collection
// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
this.size = 0;
}
#endregion
}

Since the size field was declared private, if you plan to get the count of items in the list
from outside the class, you should (must) provide a property to take care of this. This
can simply be done as follows:
using System;

class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;
// This is the size of the collection
private int size;

#region This section is used to set up the collection


// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
this.size = 0;
}

// This represents the number of items in the collection


public int Count
{
get { return this.size; }
}
#endregion
}

public class Exercise


{
static int Main(string[] args)
{
var list = new Collection();

Console.WriteLine("Number of Items: {0}", list.Count);


return 0;
}
}

This would produce:


Number of Items: 0
Press any key to continue . . .

Routine Operations on an Array-Based List


C# 3.0 Practical Learning 690
 

Adding an Item

Creating a collection consists of adding items to it. Items are usually added one at a
time. The easiest way to do this is to add an item at the end of the existing collection.

To add an item to the collection, because an array has (or is supposed to have) a fixed
number of items, you should first check whether the list is already full. For an array-
based list, the collection is full if its count of items is equal to the maximum number of
items it can hold. If the collection can still receive at least one item, you can add the
item at the end of the list and increase the count by one. Here is how this can be done:
class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;
// This is the size of the collection
private int size;

#region This section is used to set up the collection


// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
this.size = 0;
}

// This represents the number of items in the collection


public int Count
{
get { return this.size; }
}
#endregion

#region Operations on the collection


// Adds a new item to the list if the list is not full
// Increases the number of items in the list
// Returns true if the item was added, otherwise returns false
public bool Add(double item)
{
// Make sure the list is not yet full
if (this.size < 20)
{
// Since the list is not full, add the item at the end
this.Item[this.size] = item;
// Increase the count and return the new position
this.size++;

// Indicate that the item was successfully added


return true;
}

// If the item was not added, return false;


return false;
}
C# 3.0 Practical Learning 691
#endregion
}

Once you have a means of adding items to the list, you can effectively create a list of
items. Here is an example:
public class Exercise
{
static int Main(string[] args)
{
var list = new Collection();

Console.WriteLine("Number of Items: {0}", list.Count);

list.Add(224.52);
list.Add(60.48);
list.Add(1250.64);
list.Add(8.86);
list.Add(1005.36);

Console.WriteLine("Number of Items: {0}", list.Count);


return 0;
}
}

This would produce:


Number of Items: 0
Number of Items: 5
Press any key to continue . . .

Getting an Item From a List

After adding items to a collection, you can retrieve them to do what you intended the list
for. To retrieve an item, you can locate it by its position, the same way you would do for
an array. Having this index, you can check whether the position specified is negative or
higher than the current count of items. If it is, there is nothing much to do since the
index would be wrong. If the index is in the right range, you can retrieve its
corresponding item. The method to do this can be implemented as follows:
using System;

class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;
// This is the size of the collection
private int size;

#region This section is used to set up the collection


// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
this.size = 0;
}

C# 3.0 Practical Learning 692


// This represents the number of items in the collection
public int Count
{
get { return this.size; }
}
#endregion

#region Operations on the collection


// Adds a new item to the list if the list is not full
// Increases the number of items in the list
// Returns true if the item was added, otherwise returns false
public bool Add(double item)
{
// Make sure the list is not yet full
if (size < MaxCount)
{
// Since the list is not full, add the "item" at the end
this.Item[this.size] = item;
// Increase the count and return the new position
this.size++;

// Indicate that the item was successfully added


return true;
}

// If the item was not added, return false;


return false;
}

// Retrieves an item from the list based on the specified index


public double Retrieve(int pos)
{
// Make sure the index is in the range
if (pos >= 0 && pos <= size)
return this.Item[pos];

// If the index was wrong, return 0


return 0;
}
#endregion
}

public class Exercise


{
static int Main(string[] args)
{
var list = new Collection();

Console.WriteLine("Number of Items: {0}", list.Count);

list.Add(224.52);
list.Add(60.48);
list.Add(1250.64);
list.Add(8.86);
list.Add(1005.36);

for (int i = 0; i < list.Count; i++)


Console.WriteLine("Item {0}: {1}\n", i + 1,
list.Retrieve(i));
C# 3.0 Practical Learning 693
Console.WriteLine("Number of Items: {0}", list.Count);

return 0;
}
}

This would produce:


Number of Items: 0
Item 1: 224.52
Item 2: 60.48
Item 3: 1250.64
Item 4: 8.86
Item 5: 1005.36
Number of Items: 5

Press any key to continue . . .

Inserting an Item in the List

Inserting a new item in the collection allows you to add one at a position of your choice.
To insert an item in the list, you must provide the new item and the desired position.
Before performing this operation, you must check two things. First, the list must not be
empty because if it is, then there is no way to insert an item (you insert something
between two things, not something between nothing). Second, the specified position
must be in the allowed range.

The method can be implemented as follows:


using System;

class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;
// This is the size of the collection
private int size;

#region This section is used to set up the collection


// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
this.size = 0;
}

// This represents the number of items in the collection


public int Count
{
get { return this.size; }
}
#endregion

#region Operations on the collection


// Adds a new item to the list if the list is not full
C# 3.0 Practical Learning 694
// Increases the number of items in the list
// Returns true if the item was added, otherwise returns false
public bool Add(double item)
{
// Make sure the list is not yet full
if (size < MaxCount)
{
// Since the list is not full, add the "item" at the end
this.Item[this.size] = item;
// Increase the count and return the new position
this.size++;

// Indicate that the item was successfully added


return true;
}

// If the item was not added, return false;


return false;
}

// Retrieves an item from the list based on the specified index


public double Retrieve(int pos)
{
// Make sure the index is in the range
if (pos >= 0 && pos <= size)
return this.Item[pos];

// If the index was wrong, return 0


return 0;
}

// Before performing this operation, check that


// 1. The list is not full
// 2. The specified position is in an allowable range
// Insert a new item at a specified position in the list.
// After the new item is inserted, the count is increased
public bool Insert(double itm, int pos)
{
// Check that the item can be added to the list
if (size < 20 && pos >= 0 && pos <= size)
{
// Since there is room,
// starting from the end of the list to the new position,
// push each item to the next or up
// to create room for the new item
for (int i = size; i > pos - 1; i--)
this.Item[i + 1] = this.Item[i];

// Now that we have room, put the new item in the position
created
this.Item[pos] = itm;

// Since we have added a new item, increase the count


this.size++;

// Indicate that the operation was successful


return true;
}

// Since the item could not be added, return false


C# 3.0 Practical Learning 695
return false;
}
#endregion
}

public class Exercise


{
static int Main(string[] args)
{
var list = new Collection();

Console.WriteLine("Number of Items: {0}", list.Count);

list.Add(224.52);
list.Add(60.48);
list.Add(1250.64);
list.Add(8.86);
list.Add(1005.36);

for (var i = 0; i < list.Count; i++)


Console.WriteLine("Item {0}: {1}", i + 1, list.Retrieve(i));
Console.WriteLine("Number of Items: {0}\n", list.Count);

list.Insert(-707.16, 2);

for (var i = 0; i < list.Count; i++)


Console.WriteLine("Item {0}: {1}", i + 1, list.Retrieve(i));
Console.WriteLine("Number of Items: {0}\n", list.Count);

return 0;
}
}

This would produce:


Number of Items: 0
Item 1: 224.52
Item 2: 60.48
Item 3: 1250.64
Item 4: 8.86
Item 5: 1005.36
Number of Items: 5

Item 1: 224.52
Item 2: 60.48
Item 3: -707.16
Item 4: 1250.64
Item 5: 8.86
Item 6: 1005.36
Number of Items: 6

Press any key to continue . . .

Removing an Item From the List

Another operation you can perform on a collection consists of deleting an item. This is
also referred to as removing the item. To delete an item from the collection, you can

C# 3.0 Practical Learning 696


provide its position. Before performing the operation, you can (should/must) first check
that the specified position is valid. The method to perform this operation can be
implemented as follows:
using System;

class Collection
{
public int MaxCount = 20;

// This collection will be a list of decimal numbers


private double[] Item;
// This is the size of the collection
private int size;

#region This section is used to set up the collection


// Our default constructor, used to initialize the collection
public Collection()
{
this.Item = new double[MaxCount];
this.size = 0;
}

// This represents the number of items in the collection


public int Count
{
get { return this.size; }
}
#endregion

#region Operations on the collection


// Adds a new item to the list if the list is not full
// Increases the number of items in the list
// Returns true if the item was added, otherwise returns false
public bool Add(double item)
{
// Make sure the list is not yet full
if (size < MaxCount)
{
// Since the list is not full, add the "item" at the end
this.Item[this.size] = item;
// Increase the count and return the new position
this.size++;

// Indicate that the item was successfully added


return true;
}

// If the item was not added, return false;


return false;
}

// Retrieves an item from the list based on the specified index


public double Retrieve(int pos)
{
// Make sure the index is in the range
if (pos >= 0 && pos <= size)
return this.Item[pos];

C# 3.0 Practical Learning 697


// If the index was wrong, return 0
return 0;
}

// Before performing this operation, check that


// 1. The list is not full
// 2. The specified position is in an allowable range
// Inserts a new item at a specified position in the list
// After the new item is inserted, the count is increased
public bool Insert(double itm, int pos)
{
// Check that the item can be added to the list
if (size < 20 && pos >= 0 && pos <= size)
{
// Since there is room,
// starting from the end of the list to the new position,
// push each item to the next or up
// to create room for the new item
for (int i = size; i > pos - 1; i--)
this.Item[i + 1] = this.Item[i];

// Now that we have room, put the new item in the position
created
this.Item[pos] = itm;

// Since we have added a new item, increase the count


this.size++;

// Indicate that the operation was successful


return true;
}

// Since the item could not be added, return false


return false;
}

// Removes an item from the list


// First check that the specified position is valid
//-- Delete the item at that position and decrease the count --//
public bool Delete(int pos)
{
// Make sure the position specified is in the range
if (pos >= 0 && pos <= size)
{
// Since there is room, starting at the specified position,
// Replace each item by the next
for (int i = pos; i < this.size; i++)
this.Item[i] = this.Item[i + 1];

// Since an item has been removed, decrease the count


this.size--;

// Indicate that the operation was successful


return true;
}

// Since the position was out of range, return false


return false;
}
#endregion
C# 3.0 Practical Learning 698
}

public class Exercise


{
static int Main(string[] args)
{
var list = new Collection();

Console.WriteLine("Number of Items: {0}", list.Count);

list.Add(224.52);
list.Add(60.48);
list.Add(1250.64);
list.Add(8.86);
list.Add(1005.36);

for (var i = 0; i < list.Count; i++)


Console.WriteLine("Item {0}: {1}", i + 1, list.Retrieve(i));
Console.WriteLine("Number of Items: {0}\n", list.Count);

list.Insert(-707.16, 2);
list.Insert(-369952.274, 4);

for (var i = 0; i < list.Count; i++)


Console.WriteLine("Item {0}: {1}", i + 1, list.Retrieve(i));
Console.WriteLine("Number of Items: {0}\n", list.Count);

list.Delete(5);
list.Delete(3);

for (var i = 0; i < list.Count; i++)


Console.WriteLine("Item {0}: {1}", i + 1, list.Retrieve(i));
Console.WriteLine("Number of Items: {0}\n", list.Count);

return 0;
}
}

This would produce:


Number of Items: 0
Item 1: 224.52
Item 2: 60.48
Item 3: 1250.64
Item 4: 8.86
Item 5: 1005.36
Number of Items: 5

Item 1: 224.52
Item 2: 60.48
Item 3: -707.16
Item 4: 1250.64
Item 5: -369952.274
Item 6: 8.86
Item 7: 1005.36
Number of Items: 7

Item 1: 224.52
Item 2: 60.48
C# 3.0 Practical Learning 699
Item 3: -707.16
Item 4: -369952.274
Item 5: 1005.36
Number of Items: 5

Press any key to continue . . .

A Collection of Items
 

Introduction

We have learned how to create an array as a list of items. Like an array, a collection is a
series of items of the same type. The particularity with creating an array is that you
must know in advance the number of items that will make up the list (in reality, in
the .NET Framework, you just have to specify an initial count, such as 5; then, before
adding a new item, you can check if there is room, if there is no room, you can provide
room first, then add the new item). There are times when you don't know, you can't
know, or you can't predict the number of items of the list. For this reason, you may want
to create the list for which you don't specify the maximum number of items but you
allow the user of the list to add, locate, or remove items at will.

Before creating a list, you probably should first decide or define what the list would be
made of. As different as collections are, one list can be made of numeric values, such as
a list that will be made of numbers. You may want a list that is made of names. Such a
list can be created from a class that includes a string member variable. Another type of
list can contain complex objects.

Practical Learning: Introducing Collections

1. Start Microsoft Visual C# and create a new Console Application named


FlowerShop4

2. To save the project, on the Standard toolbar, click the Save All button

3. Accept all defaults and click Save

4. To create a new class, in the Solution Explorer, right-click FlowerShop4 -> Add ->
Class...

5. Set the Name of the class to Flower and click Add

6. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public enum FlowerType
{

C# 3.0 Practical Learning 700


Roses = 1,
Lilies,
Daisies,
Carnations,
LivePlant,
Mixed
}

public enum FlowerColor


{
Red = 1,
White,
Yellow,
Pink,
Orange,
Blue,
Lavender,
Mixed
}

public enum FlowerArrangement


{
Bouquet = 1,
Vase,
Basket,
Any
}

public sealed class Flower


{

private decimal pc;

public FlowerType Type;

public FlowerColor Color;

public FlowerArrangement Arrangement;

public Flower()
{
Type = FlowerType.Mixed;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
pc = 0.00M;
}

public Flower(FlowerType type, FlowerColor color,


FlowerArrangement argn, decimal price)
{
Type = type;
Color = color;
Arrangement = argn;
pc = price;
}

public decimal UnitPrice


{
get { return pc; }
set { pc = value; }
C# 3.0 Practical Learning 701
}
}
}

7. To create a new class, in the Solution Explorer, right-click FlowerShop4 -> Add ->
Class...

8. Set the Name of the class to OrderProcessing and click Add

9. Complete the OrderProcessing.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public class OrderProcessing
{
public Flower FlowerOrder;
private int qty;

public int Quantity


{
get { return qty; }
set { qty = value; }
}

public OrderProcessing()
{
FlowerOrder = new Flower();
}

public decimal TotalPrice


{
get { return Quantity * FlowerOrder.UnitPrice; }
}

internal void GetFlowerType()


{
int choice = 0;

do
{
try
{
Console.WriteLine("Enter the Type of Flower Order");
Console.WriteLine("1. Roses");
Console.WriteLine("2. Lilies");
Console.WriteLine("3. Daisies");
Console.WriteLine("4. Carnations");

Console.WriteLine("5. Live Plant");

Console.WriteLine("6. Mixed");
Console.Write("Your Choice: ");
C# 3.0 Practical Learning 702
choice = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You failed to enter an " +
"appropriate number!");
}

if ((choice < 1) || (choice > 6))


Console.WriteLine("Invalid Value: Please enter " +
"a value between 1 and 6");
} while ((choice < 1) || (choice > 6));

switch (choice)
{
case 1:
FlowerOrder.Type = FlowerType.Roses;
break;
case 2:
FlowerOrder.Type = FlowerType.Lilies;
break;
case 3:
FlowerOrder.Type = FlowerType.Daisies;
break;
case 4:
FlowerOrder.Type = FlowerType.Carnations;
break;
case 5:
FlowerOrder.Type = FlowerType.LivePlant;
break;
default:
FlowerOrder.Type = FlowerType.Mixed;
break;
}
}

internal void GetFlowerColor()


{
int choice = 0;

do
{
try
{
Console.WriteLine("Enter the Color");
Console.WriteLine("1. Red");
Console.WriteLine("2. White");
Console.WriteLine("3. Yellow");
Console.WriteLine("4. Pink");
Console.WriteLine("5. Orange");
Console.WriteLine("6. Blue");
Console.WriteLine("7. Lavender");
Console.WriteLine("8. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You didn't enter an " +
"appropriate number!");
C# 3.0 Practical Learning 703
}

if ((choice < 1) || (choice > 8))


Console.WriteLine("Invalid Value: Please " +
"enter a value between 1 and 8");
} while ((choice < 1) || (choice > 8));

switch (choice)
{
case 1:
FlowerOrder.Color = FlowerColor.Red;
break;
case 2:
FlowerOrder.Color = FlowerColor.White;
break;
case 3:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 4:
FlowerOrder.Color = FlowerColor.Pink;
break;
case 5:
FlowerOrder.Color = FlowerColor.Yellow;
break;
case 6:
FlowerOrder.Color = FlowerColor.Blue;
break;
case 7:
FlowerOrder.Color = FlowerColor.Lavender;
break;
default:
FlowerOrder.Color = FlowerColor.Mixed;
break;
}
}

internal void GetFlowerArrangement()


{
int choice = 0;

do
{
try
{
Console.WriteLine("Enter the Type of Arrangement");
Console.WriteLine("1. Bouquet");
Console.WriteLine("2. Vase");
Console.WriteLine("3. Basket");
Console.WriteLine("4. Mixed");
Console.Write("Your Choice: ");
choice = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You didn't provide an " +
"acceptable number!");
}

if ((choice < 1) || (choice > 4))


Console.WriteLine("Invalid Value: Please enter " +
C# 3.0 Practical Learning 704
"a value between 1 and 4");
} while ((choice < 1) || (choice > 4));

switch (choice)
{
case 1:
FlowerOrder.Arrangement = FlowerArrangement.Bouquet;
break;
case 2:
FlowerOrder.Arrangement = FlowerArrangement.Vase;
break;
case 3:
FlowerOrder.Arrangement = FlowerArrangement.Basket;
break;
default:
FlowerOrder.Arrangement = FlowerArrangement.Any;
break;
}
}

internal void ProcessOrder()


{
GetFlowerType();
GetFlowerColor();
GetFlowerArrangement();

try
{
Console.Write("Enter the Unit Price: ");
FlowerOrder.UnitPrice =
Math.Abs(decimal.Parse(Console.ReadLine()));
}
catch (FormatException)
{
Console.WriteLine("You didn't specify a valid price!");
}

try
{
Console.Write("Enter Quantity: ");
Quantity = Math.Abs(int.Parse(Console.ReadLine()));
}
catch (FormatException)
{
Console.WriteLine("The quantity you entered " +
"is not acceptable!");
}
}

internal void ShowOrder()


{
Console.WriteLine("=======================");
Console.WriteLine("==-=-=Flower Shop=-=-==");
Console.WriteLine("-----------------------");
Console.WriteLine("Flower Type: {0}",
FlowerOrder.Type);
Console.WriteLine("Flower Color: {0}",
FlowerOrder.Color);
Console.WriteLine("Arrangement: {0}",
FlowerOrder.Arrangement);
C# 3.0 Practical Learning 705
Console.WriteLine("Price: {0:C}",
FlowerOrder.UnitPrice);
Console.WriteLine("Quantity: {0}", Quantity);
Console.WriteLine("Total Price: {0:C}", TotalPrice);
Console.WriteLine("=======================");
}
}
}

10.Access the Program.cs file and complete it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public class Program
{
static void Main(string[] args)
{
var order = new OrderProcessing();

order.ProcessOrder();
Console.WriteLine();

order.ShowOrder();
Console.WriteLine();
}
}
}

11.Execute the application and test it. Here is an example:


 
Enter the Type of Flower Order
1. Roses
2. Lilies
3. Daisies
4. Carnations
5. Live Plant
6. Mixed
Your Choice: 3
Enter the Color
1. Red
2. White
3. Yellow
4. Pink
5. Orange
6. Blue
7. Lavender
8. Mixed
Your Choice: 8
Enter the Type of Arrangement
1. Bouquet
2. Vase
3. Basket
4. Mixed
C# 3.0 Practical Learning 706
Your Choice: 1
Enter the Unit Price: 45.50
Enter Quantity: 3

=======================
==-=-=Flower Shop=-=-==
-----------------------
Flower Type: Daisies
Flower Color: Mixed
Arrangement: Bouquet
Price: $45.50
Quantity: 3
Total Price: $136.50
=======================

Press any key to continue . . .

12.Close the DOS window

Implementing a Collection

After deciding what each item of the list would be made of, you can create a class that
would manage the list. This class would be responsible for all operations that can be
performed on the list. If the list will be made of primitive values, you can directly create
a field of the desired type. Here is an example:
using System;

public class Numbers


{
public double Number;
}

public class Exercise


{
static int Main(string[] args)
{
Numbers nbrs = new Numbers();

return 0;
}
}

If the list will be made of objects, you can first create a class that specifies those types
of items and then declare its variable in the list class. Here is an example of a simple
class that holds a double-precision value:
using System;

public class Number


{
public double Item;
}

C# 3.0 Practical Learning 707


public class Numbers
{
Number Sample;
}

public class Exercise


{
static int Main(string[] args)
{
Numbers nbrs = new Numbers();

return 0;
}
}

When creating a list, one of the aspects you should pay attention to is to keep track of
the number of items in the list. To do this, you can create a property that holds the
number. The value of this property would increase as the items are added to the list and
the value would decrease as the items are removed from the list. Here is how this can
be done:
using System;

public class Number


{
public double Item;
}

public class Numbers


{
int size;
Number Sample;

public Numbers()
{
size = 0;
}

public int Count


{
get { return size; }
}
}

public class Exercise


{
static int Main(string[] args)
{
var nbrs = new Numbers();

Console.WriteLine("Number of Items: {0}", nbrs.Count);

return 0;
}
}

This would produce:


Number of Items: 0
Press any key to continue . . .
C# 3.0 Practical Learning 708
Practical Learning: Creating a Class Collection

1. To create a new class, in the Class View, right-click FlowerShop4 -> Add -> Class...

2. Set the Name to FlowerInventory and click Add

3. Change the class as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public abstract class AFlower
{
protected int items;

public AFlower()
{
items = 0;
}

public int Count


{
get { return items; }
}
}

public class FlowerInventory : AFlower


{
public Flower Inventory;

public FlowerInventory()
{
}
}
}

4. Save the file

The Beginning of a Collection

A good collection is a list that can grow or shrink as the user wishes. When creating the
list, you don't need to predict the maximum number of items that will be added to the
list. When a list starts, it is empty or at least it must be considered like that, before any
item is added to it. To specify this, you should declare a primary member variable.
Although you can call it anything, it is usually called Head:

C# 3.0 Practical Learning 709


The head member can be made private if you don't intend to access it outside of the
class. If you want clients of the class to access it, you can make it public. Here is an
example:
public class Numbers
{
int listSize;
Number Sample;

public Numbers()
{
size = 0;
Head = null;
}

public int Count


{
get { return listSize; }
}

public Number Head;


}

Linking the Items of a Collection

We saw that when using an array, each member could be accessed using its index. If
the items of a collection are not indexed, you must provide a mechanism to locate an
item. To do this, you can use a starting point that determines the beginning of the list.
Then, to locate an item, you can check whether another item follows that starting point:

If no item follows an item, either you are at the end of the list or the list is empty.

To be able to scan a list from one item to another, you can declare a field. Although this
member variable can be called anything, for the sake of clarify, you should call it Next.
The field is the same type as its class. Here is an example:
C# 3.0 Practical Learning 710
public class Number
{
public double Item;
public Number Next;
}

Practical Learning: Creating a List's Monitor

1. Access the Flower.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
. . . No Change

public sealed class Flower


{
. . . No Change

public decimal UnitPrice


{
get { return pc; }
set { pc = value; }
}

public Flower Next;


}
}

2. Access the FlowerInventory.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public abstract class AFlower
{
protected int items;

public AFlower()
{
items = 0;
}

public int Count


{
get { return items; }
}
}

C# 3.0 Practical Learning 711


public class FlowerInventory : AFlower
{
public Flower Head;
public Flower Inventory;

public FlowerInventory()
{
Head = null;
}
}
}

3. Save all

Operations on a Collection
 

Adding an Item

Since a list is fundamentally empty when it starts, the primary operation you can
perform on a list is to add a new item to it. In order to indicate that you want to add an
item to the list, you can create a method that receives an item as argument. For the
return type, you have two main options. Because the main job of this method is to add a
new item, which it hardly fails to do if you implement it right, it can be defined as void.
Alternatively, you can make it return the position of the new item in the list. Here is an
example:
public class Numbers
{
int size;
Number Sample;
public Number Head;

public Numbers()
{
size = 0;
Head = null;
}

public int Count


{
get { return size; }
}

public int Add(Number NewItem)


{
Number Sample = new Number();

Sample = NewItem;
Sample.Next = Head;
Head = Sample;
return size++;
}
}

Practical Learning: Adding Items to a Collection


C# 3.0 Practical Learning 712
1. Change the FlowerInventory.cs file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public abstract class AFlower
{
protected int items;

public AFlower()
{
items = 0;
}

public int Count


{
get { return items; }
}

public abstract int Add(Flower obj);


}

public class FlowerInventory : AFlower


{
public Flower Head;
public Flower Inventory;

public FlowerInventory()
{
Head = null;
}

public override int Add(Flower NewFlower)


{
Flower Sample = new Flower();

Sample = NewFlower;
Sample.Next = Head;
Head = Sample;
return items++;
}
}
}

2. Access the Program.cs and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
C# 3.0 Practical Learning 713
public class Program
{
static void Main(string[] args)
{
var flowers = new FlowerInventory();
var nice = new Flower();

nice.Type = FlowerType.Lilies;
nice.Color = FlowerColor.White;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 39.95M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Mixed;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 40.50M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Carnations;
nice.Color = FlowerColor.Lavender;
nice.Arrangement = FlowerArrangement.Any;
nice.UnitPrice = 34.85M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Roses;
nice.Color = FlowerColor.Pink;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 29.95M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Yellow;
nice.Arrangement = FlowerArrangement.Vase;
nice.UnitPrice = 29.95M;
flowers.Add(nice);
}
}
}

3. Save all

Retrieving an Item

Once a list exists, the user can explore it. One of the operations performed on a
collection is to locate and retrieve an item. To do this, you can create a method that
takes as argument an index. The method would examine the argument with regards to
the number of items in the list to make sure the argument's value is in the range of the
current items of the list. If the number is too low or too high, the method can return null
or 0. If the number is in the range, the method can return the item at that position.
Here is an example:

C# 3.0 Practical Learning 714


public class Numbers
{
int size;
Number Sample;
public Number Head;

public Numbers()
{
size = 0;
Head = null;
}

public int Count


{
get { return size; }
}

public int Add(Number NewItem)


{
Number Sample = new Number();

Sample = NewItem;
Sample.Next = Head;
Head = Sample;
return size++;
}

public Number Retrieve(int Position)


{
Number Current = Head;

for (int i = Count - 1; i > Position && Current != null; i--)


Current = Current.Next;
return Current;
}
}

Practical Learning: Retrieving the Items of a Collection

1. Access the FlowerInventory.cs file and add the following method:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public abstract class AFlower
{
protected int items;

public AFlower()
{
items = 0;
}

public int Count


C# 3.0 Practical Learning 715
{
get { return items; }
}

public abstract int Add(Flower obj);


public abstract Flower Get(int index);
}

public class FlowerInventory : AFlower


{
public Flower Head;
public Flower Inventory;

public FlowerInventory()
{
Head = null;
}

public override int Add(Flower NewFlower)


{
Flower Sample = new Flower();

Sample = NewFlower;
Sample.Next = Head;
Head = Sample;
return items++;
}

public override Flower Get(int index)


{
Flower Current = Head;

for(int i = Count - 1;
i > index && Current != null;
i--)
Current = Current.Next;
return Current;
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public class Program
{
static void Main(string[] args)
{
var flowers = new FlowerInventory();
var nice = new Flower();

nice.Type = FlowerType.Lilies;
nice.Color = FlowerColor.White;
C# 3.0 Practical Learning 716
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 39.95M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Mixed;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 40.50M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Carnations;
nice.Color = FlowerColor.Lavender;
nice.Arrangement = FlowerArrangement.Any;
nice.UnitPrice = 34.85M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Roses;
nice.Color = FlowerColor.Pink;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 29.95M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Yellow;
nice.Arrangement = FlowerArrangement.Vase;
nice.UnitPrice = 42.75M;
flowers.Add(nice);

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
Console.WriteLine("Total: {0} flower items in current
inventory",
flowers.Count);

Console.WriteLine("--------------------------------------------");
Console.WriteLine("Inventory Summary");
for (int i = 0; i < flowers.Count; i++)
{
Console.WriteLine("------------------------");
Console.WriteLine("Flower Information");
Console.WriteLine("Type: {0}",
flowers.Get(i).Type);
Console.WriteLine("Color: {0}",
flowers.Get(i).Color);
Console.WriteLine("Arrangement: {0}",
flowers.Get(i).Arrangement);
Console.WriteLine("Unit Price: {0:F}",
flowers.Get(i).UnitPrice);
}

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
}
}
}

C# 3.0 Practical Learning 717


3. Execute the application to view the result:
 
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Total: 5 flower items in current inventory
--------------------------------------------
Inventory Summary
------------------------
Flower Information
Type: Lilies
Color: White
Arrangement: Bouquet
Unit Price: 39.95
------------------------
Flower Information
Type: Daisies
Color: Mixed
Arrangement: Bouquet
Unit Price: 40.50
------------------------
Flower Information
Type: Carnations
Color: Lavender
Arrangement: Any
Unit Price: 34.85
------------------------
Flower Information
Type: Roses
Color: Pink
Arrangement: Bouquet
Unit Price: 29.95
------------------------
Flower Information
Type: Daisies
Color: Yellow
Arrangement: Vase
Unit Price: 42.75
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Press any key to continue . . .

4. Close the DOS window

Removing an Item

Deleting an item consists of removing it from the list. There are two main approaches
you can use. You can simply ask the class to delete an item. In this case, it is usually the
item at the end that gets deleted. If you do this, make sure you perform other routine
operations such as decrementing the count of items in the list. Here is an example:
public class Numbers
{
. . . No Change

public bool Delete()


{
if (Head == null)
{
Console.WriteLine("The list is empty");

C# 3.0 Practical Learning 718


return false;
}

Number Current;

Current = Head.Next;
Head.Next = Current.Next;
size--;
return true;
}
}

Another technique used to delete an item consists of specifying the position of the item
to be deleted. To do this, you can pass an argument as the desired position. The
method would check the range of values of the current list. If the specified position is
beyond the appropriate range, the method can return false, 0, or null, depending on
how you create it.

Practical Learning: Retrieving the Items of a Collection

1. Access the FlowerInventory.cs file and add the following method:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public abstract class AFlower
{
protected int items;

public AFlower()
{
items = 0;
}

public int Count


{
get { return items; }
}

public abstract int Add(Flower obj);


public abstract Flower Get(int index);
public abstract bool Delete();
}

public class FlowerInventory : AFlower


{
public Flower Head;
public Flower Inventory;

public FlowerInventory()
{
Head = null;
}
C# 3.0 Practical Learning 719
public override int Add(Flower NewFlower)
{
Flower Sample = new Flower();

Sample = NewFlower;
Sample.Next = Head;
Head = Sample;
return items++;
}

public override Flower Get(int index)


{
Flower Current = Head;

for(int i = Count - 1;
i > index && Current != null;
i--)
Current = Current.Next;
return Current;
}

public override bool Delete()


{
if (Head == null)
{
Console.WriteLine("The inventory is empty");
return false;
}

Flower Current;

Current = Head.Next;
Head.Next = Current.Next;
items--;
return true;
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop4
{
public class Program
{
static void Main(string[] args)
{
var flowers = new FlowerInventory();
var nice = new Flower();

nice.Type = FlowerType.Lilies;
nice.Color = FlowerColor.White;
nice.Arrangement = FlowerArrangement.Bouquet;
C# 3.0 Practical Learning 720
nice.UnitPrice = 39.95M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Mixed;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 40.50M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Carnations;
nice.Color = FlowerColor.Lavender;
nice.Arrangement = FlowerArrangement.Any;
nice.UnitPrice = 34.85M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Roses;
nice.Color = FlowerColor.Pink;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 29.95M;
flowers.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Yellow;
nice.Arrangement = FlowerArrangement.Vase;
nice.UnitPrice = 42.75M;
flowers.Add(nice);

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
Console.WriteLine("Total: {0} flower items in current
inventory",
flowers.Count);

Console.WriteLine("--------------------------------------------");
Console.WriteLine("Inventory Summary");
for (var i = 0; i < flowers.Count; i++)
{
Console.WriteLine("------------------------");
Console.WriteLine("Flower Information");
Console.WriteLine("Type: {0}",
flowers.Get(i).Type);
Console.WriteLine("Color: {0}",
flowers.Get(i).Color);
Console.WriteLine("Arrangement: {0}",
flowers.Get(i).Arrangement);
Console.WriteLine("Unit Price: {0:F}",
flowers.Get(i).UnitPrice);
}

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");

flowers.Delete();
flowers.Delete();

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
C# 3.0 Practical Learning 721
Console.WriteLine("Total: {0} flower items in current
inventory",
flowers.Count);

Console.WriteLine("--------------------------------------------");
Console.WriteLine("Inventory Summary");
for (var i = 0; i < flowers.Count; i++)
{
Console.WriteLine("------------------------");
Console.WriteLine("Flower Information");
Console.WriteLine("Type: {0}",
flowers.Get(i).Type);
Console.WriteLine("Color: {0}",
flowers.Get(i).Color);
Console.WriteLine("Arrangement: {0}",
flowers.Get(i).Arrangement);
Console.WriteLine("Unit Price: {0:F}",
flowers.Get(i).UnitPrice);
}

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
}
}
}

3. Execute the application to view the result:


 
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Total: 5 flower items in current inventory
--------------------------------------------
Inventory Summary
------------------------
Flower Information
Type: Lilies
Color: White
Arrangement: Bouquet
Unit Price: 39.95
------------------------
Flower Information
Type: Daisies
Color: Mixed
Arrangement: Bouquet
Unit Price: 40.50
------------------------
Flower Information
Type: Carnations
Color: Lavender
Arrangement: Any
Unit Price: 34.85
------------------------
Flower Information
Type: Roses
Color: Pink
Arrangement: Bouquet
Unit Price: 29.95
------------------------
Flower Information
Type: Daisies
Color: Yellow
C# 3.0 Practical Learning 722
Arrangement: Vase
Unit Price: 42.75
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Total: 3 flower items in current inventory
--------------------------------------------
Inventory Summary
------------------------
Flower Information
Type: Lilies
Color: White
Arrangement: Bouquet
Unit Price: 39.95
------------------------
Flower Information
Type: Daisies
Color: Mixed
Arrangement: Bouquet
Unit Price: 40.50
------------------------
Flower Information
Type: Daisies
Color: Yellow
Arrangement: Vase
Unit Price: 42.75
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Press any key to continue . . .

4. Close the DOS window

Locating an Item

One of the operations hardly performed on a list is to find an item. This is because if you
ask a list to locate a particular item, you must provide as much information as possible.
Probably the most expedient way you can do this is to completely define an item and
pass it to the list. Only if the (exact) item is found in the list would it be recognized.

Here is an example:
using System;

public class Number


{
public double Item;
public Number Next;
}

public class Numbers


{
int size;
Number Sample;
public Number Head;

public Numbers()
{
size = 0;
Head = null;
}

C# 3.0 Practical Learning 723


public int Count
{
get { return size; }
}

public int Add(Number NewItem)


{
Number Sample = new Number();

Sample = NewItem;
Sample.Next = Head;
Head = Sample;
return size++;
}

public Number Retrieve(int Position)


{
Number Current = Head;

for (int i = Count - 1; i > Position && Current != null; i--)


Current = Current.Next;
return Current;
}

public bool Delete()


{
if (Head == null)
{
Console.WriteLine("The list is empty");
return false;
}

Number Current;

Current = Head.Next;
Head.Next = Current.Next;
size--;
return true;
}

public bool Find(Number toFind)


{
Number Current = new Number();

if (toFind == null)
return false;

for (Current = Head; Current != null; Current = Current.Next)


{
if( Current.Item == toFind.Item )
return true;
}

return false;
}
}

public class Exercise


{
C# 3.0 Practical Learning 724
static int Main(string[] args)
{
Number real;
Numbers reals = new Numbers();

real = new Number();


real.Item = 2974.03;
reals.Add(real);

real = new Number();


real.Item = 748.25;
reals.Add(real);

real = new Number();


real.Item = 50883.82;
reals.Add(real);

real = new Number();


real.Item = 29.24;
reals.Add(real);

real = new Number();


real.Item = 772.85;
reals.Add(real);

real = new Number();


real.Item = 106628.06;
reals.Add(real);

Console.WriteLine("Number of items: {0}", reals.Count);

for (int i = 0; i < reals.Count; i++)


{
Number nbr = reals.Retrieve(i);
Console.WriteLine("Number[{0}] = {1}", i, nbr.Item);
}

reals.Delete();

Console.WriteLine("\nNumber of items: {0}", reals.Count);

for (int i = 0; i < reals.Count; i++)


{
Number nbr = reals.Retrieve(i);
Console.WriteLine("Number[{0}] = {1}", i, nbr.Item);
}

Number nbrToFind = new Number();


nbrToFind.Item = 26486.56;

bool Found = reals.Find(nbrToFind);


if (Found == true)
Console.WriteLine("\nThe number {0} was found in the list",
nbrToFind.Item);
else
Console.WriteLine("\nThe number {0} was NOT found in the
list",
nbrToFind.Item);

nbrToFind = new Number();


C# 3.0 Practical Learning 725
nbrToFind.Item = 50883.82;

Found = reals.Find(nbrToFind);
if (Found == true)
Console.WriteLine("The number {0} was found in the list\n",
nbrToFind.Item);
else
Console.WriteLine("The number {0} was NOT found in the
list\n",
nbrToFind.Item);

return 0;
}
}

This would produce:


Number of items: 6
Number[0] = 2974.03
Number[1] = 748.25
Number[2] = 50883.82
Number[3] = 29.24
Number[4] = 772.85
Number[5] = 106628.06

Number of items: 5
Number[0] = 2974.03
Number[1] = 748.25
Number[2] = 50883.82
Number[3] = 29.24
Number[4] = 106628.06

The number 26486.56 was NOT found in the list


The number 50883.82 was found in the list

Press any key to continue . . .

Iterating Through a
Collection
 

Enumerating the Members of a Collection


C# 3.0 Practical Learning 726
 

Introduction to System Collections

When studying arrays, we saw that you could use a for loop to visit each member of an
array. This was also done with the help of the [] operator. In previous lessons, we saw
that, when creating a collection, you should provide a method that allows you to retrieve
a member of the collection. In both cases, you can list the members of an array or a
collection through a technique called an enumeration. Enumerating a collection consists
of visiting each member of the list, for any reason judged necessary. For example, you
can enumerate a collection to display a list of its members. You can enumerate a
collection when looking for a member that responds to a certain criterion.

Besides, or instead of, a for loop, the .NET Framework provides another and better
support for enumeration. In the C# language, you can enumerate a collection using the
foreach operator, but the collection must be prepared for it: you cannot just use
foreach for any collection. This support is provided through two main interfaces:
IEnumerator and IEnumerable. These two interfaces are defined in the
System.Collection namespace. Therefore, if you intend to use them, you can include
this namespace in your source file.

Practical Learning: Introducing Built-In Collections

1. Start Microsoft Visual C# and create a new Console Application named


FlowerShop5

2. To create a new file, on the main menu, click Project -> Add New Item...

3. In the Templates list, click Code File

4. Set the Name to FlowerAccessories and click Add

5. In the empty file, type the following:


 
public enum FlowerType
{
Roses = 1, // Why
Lilies = 102, // these
Daisies = 104, // fancy
Carnations = 112, // numbers?
LivePlant = 220, // Just
Orchids = 234, // for
Tulips = 242, // the
Iris = 250, // fun
Mixed = 462, // of
Other = 464 // it
}

public enum FlowerColor


{
Red = 1,
White,
C# 3.0 Practical Learning 727
Yellow,
Pink,
Orange,
Blue,
Lavender,
Mixed
}

public enum FlowerArrangement


{
Bouquet = 1,
Balloon,
Vase,
Basket,
Bundle,
Any
}

6. To create a new class, in the Solution Explorer, right-click FlowerShop5 -> Add ->
Class...

7. Set the Name to Flower and press Enter

8. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop5
{
public class Flower
{

private decimal pc;

public Flower Next;


public FlowerType Type;

public FlowerColor Color;

public FlowerArrangement Arrangement;

public Flower()
{
Type = FlowerType.Mixed;
Color = FlowerColor.Mixed;
Arrangement = FlowerArrangement.Vase;
pc = 0.00M;
}

public Flower(FlowerType type, FlowerColor color,

C# 3.0 Practical Learning 728


FlowerArrangement argn, decimal price)
{
Type = type;
Color = color;
Arrangement = argn;
pc = price;
}

public decimal UnitPrice


{
get { return pc; }
set { pc = value; }
}
}
}

9. To create a new class, in the Class View, right-click FlowerShop5 -> Add -> Class...

10.Set the Name to FlowerInventory and click Add

11.Change the class as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop5
{
public abstract class AFlower
{
protected int items;

public AFlower()
{
items = 0;
}

public int Count


{
get { return items; }
}

public abstract int Add(Flower obj);


public abstract Flower Get(int index);
public abstract bool Delete();
}

public class FlowerInventory : AFlower


{
public Flower Head;
public Flower Inventory;

public FlowerInventory()
{
Head = null;
}

public override int Add(Flower NewFlower)


C# 3.0 Practical Learning 729
{
Flower Sample = NewFlower;

Sample.Next = Head;
Head = Sample;
return items++;
}

public override Flower Get(int index)


{
Flower Current = Head;

for(int i = Count - 1;
i > index && Current != null;
i--)
Current = Current.Next;
return Current;
}

public override bool Delete()


{
if (Head == null)
{
Console.WriteLine("The inventory is empty");
return false;
}

Flower Current;

Current = Head.Next;
Head.Next = Current.Next;
items--;
return true;
}
}
}

12.Save all  

Introduction to the IEnumerator Interface

The IEnumerator interface provides the means of identifying the class that holds a
sample of the items that will be enumerated. This interface is equipped with one
property and two methods. To use the functionalities provided by the IEnumerator
interface, you must create a class that implements it. You can start the class as follows:
public class Enumerator : IEnumerator
{
}

If your collection is an array-based list, you can start by declaring the base array in the
class: Here is an example:
public class Enumerator : IEnumerator
{
private double[] numbers;
}

C# 3.0 Practical Learning 730


If the collection is not array-based, you can declare a variable for the class that would
be enumerated.

The role of the enumerator is to act on a collection. For this reason, the class should be
prepared to receive an external collection. This can be done by passing it to a
constructor of the enumerator. Here is an example:
public class Enumerator : IEnumerator
{
private double[] numbers;

public Enumerator(double[] list)


{
}
}

The internal collection would be used in the enumerator class. The external collection
would be the source of the values of the list that would be enumerated. For these
reasons, you can/should initialize the internal collection with the values of the external
list. This can be done as follows:
public class Enumerator : IEnumerator
{
private double[] numbers;

public Enumerator(double[] list)


{
this.numbers = list;
}
}

Practical Learning: Introducing Enumerations

1. To create a new class, in the Class View, right-click FlowerShop5 -> Add -> Class...

2. Set the Name of the class to FlowerIdentifier and click Add

3. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace FlowerShop5
{
public class FlowerIdentifier : IEnumerator
{
public FlowerInventory counts;

public void Identify(FlowerInventory list)


{
this.counts = list;
}
}
}
C# 3.0 Practical Learning 731
4. Save the file

The Current Item of an Enumeration

In the previous lesson, when introducing some techniques of creating a list, we saw that
you should have a type of tag, as a field, that allows you to monitor the item that is
being currently accessed or used in the list. This is particularly valuable when visiting the
members of the collection. The IEnumerator interface provides a property that is used
to identify the current member of the list. This property is called Current. Because the
current item is meant to be viewed only, the Current property is a read-only member.
Based on the rules of abstract classes, remember that you must implement all members
of an interface in the class that is based on it.

To implement the Current property, you can define its get accessor to return the item
at the current position. This can be done as follows:
public class Enumerator : IEnumerator
{
private double[] numbers;
private int cur;

public Enumerator(double[] list)


{
this.numbers = list;
}

public object Current


{
get { return numbers[cur]; }
}
}

Practical Learning: Getting to the Current Item

1. In the FlowerIdentifier.cs file, implement the IEnumerator.Current property as


follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace FlowerShop5
{
public class FlowerIdentifier : IEnumerator
{
private int curPosition = -1;
public FlowerInventory counts;

public void Identify(FlowerInventory list)


{
this.counts = list;
}

C# 3.0 Practical Learning 732


public object Current
{
get
{
return this.counts.Get(this.curPosition);
}
}
}
}

2. Save the file

Resetting the Tag of the Current Item

Although you should be able to identify the current item at any time, when the
application starts, before the collection can be enumerated, the tag that is used to
monitor the current item should be set to a value before the beginning of the count.
This can be done by setting the tag to -1. Here is an example:
public class Enumerator : IEnumerator
{
private double[] numbers;
private int cur;

public Enumerator(double[] list)


{
this.numbers = list;
cur = -1;
}

public Object Current


{
get { return numbers[cur]; }
}
}

While the collection is being used, at one moment you may want to reset the tag of the
current item to its original position. To support this operation, the IEnumerator
interface is equipped with a method named Reset. Its syntax is:
void Reset();

When implementing this method, simply assign a non-existing value, which is usually -1,
to the monitoring tag of the current item. This can be done as follows:
public class Enumerator : IEnumerator
{
private double[] numbers;
private int cur;

public Enumerator(double[] list)


{
this.numbers = list;
cur = -1;
}

public object Current


{

C# 3.0 Practical Learning 733


get { return numbers[cur]; }
}

public void Reset()


{
cur = -1;
}
}

When using the implementer of the IEnumerator interface, if you try accessing an item
beyond the maximum number of items, the compiler would throw an
IndexOutOfRangeException exception. For this reason, when anticipating a bad
behavior, you should catch this exception when implementing the Current property.

Practical Learning: Resetting the Tag of the Current Item

1. In the FlowerIdentifier.cs file, implement the IEnumerator.Reset() method as


follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace FlowerShop5
{
public class FlowerIdentifier : IEnumerator
{
private int curPosition = -1;
public FlowerInventory counts;

public void Identify(FlowerInventory list)


{
this.counts = list;
}

public Object Current


{
get
{
try
{
return this.counts.Get(this.curPosition);
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("The current item must be accessed
" +
"within the range of available
items");
}
}
}

public void Reset()


{
C# 3.0 Practical Learning 734
this.curPosition = -1;
}
}
}

2. Save the file

Moving to the Next Item in the Enumerator

In the previous lesson, we saw that, when using the items of a collection, one way you
could locate one item from another was to be able to jump from one item to the next.
This operation is also very important when enumerating a collection. To support this
operation, the IEnumerator interface is quipped with the MoveNext() method. Its
syntax is:
bool MoveNext();

When implementing this method, first increment the tag that monitors the current item
of the collection. After incrementing the tag, check whether it is lower than the total
number of items. If it is, return true. Otherwise, return false. This can be done as
follows:
public class Enumerator : IEnumerator
{
private double[] numbers;
private int cur;

public Enumerator(double[] list)


{
this.numbers = list;
cur = -1;
}

public Object Current


{
get { return numbers[cur]; }
}

public void Reset()


{
cur = -1;
}

public bool MoveNext()


{
cur++;
if (cur < numbers.Length)
return true;
else
return false;
}
}

Practical Learning: Moving to the Next Item in the Enumerator

C# 3.0 Practical Learning 735


1. Implement the IEnumerator.MoveNext() method as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace FlowerShop5
{
public class FlowerIdentifier : IEnumerator
{
private int curPosition = -1;
public FlowerInventory counts;

public void Identify(FlowerInventory list)


{
this.counts = list;
}

public Object Current


{
get
{
try
{
return this.counts.Get(this.curPosition);
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("The current item must be accessed
" +
"within the range of available
items");
}

return null;
}
}

public void Reset()


{
this.curPosition = -1;
}

public bool MoveNext()


{
this.curPosition++;

if (this.curPosition < counts.Count)


return true;
else
return false;
}
}
}

2. Save the file

C# 3.0 Practical Learning 736


An Enumerable Collection
 

Introduction

The IEnumerator interface is used to set up a collection for enumeration. The


IEnumerator does not provide the functionality necessary to use foreach. The next
step is to implement another interface called IEnumerable.

While the IEnumerator interface is used to identify the class that holds each value that
will be visited, the IEnumerable interface is used to communicate with the collection
whose items will be enumerated. For this reason, when implementing this class, you
should provide the means of accessing the external collection. This can be done by
passing a collection of the class that holds the values, to a constructor of the
IEnumerable implementer.

Getting the Enumerator

To implement the IEnumerable interface, start by deriving a class from it. While the
class implemented by the IEnumerator interface represents an object, the class that
implements the IEnumerable interface is a collection. Here is an example:
public class Enumerable : IEnumerable
{
}

The new class does not know what collection it will be asked to enumerate. For this
reason, in the new class, you should declare a member variable of the class that holds
the values that will be enumerated. If the collection is array-based, you can create the
field as follows:
public class Enumerable : IEnumerable
{
private double[] numbers;
}

Eventually, when instantiating the IEnumerable implementer, you will need to pass it a
collection of values. To make this possible, you can create a method in the new class
and pass that collection of objects. Here is an example:
public class Enumerable : IEnumerable
{
private double[] numbers;

public void Identify(double[] values)


{
}
}

In this method, you can assign the member variable to the argument. You should also
assign each member of the argument to its equivalent of the member of the argument.
This can be done with a for loop as follows:
public class Enumerable : IEnumerable

C# 3.0 Practical Learning 737


{
private double[] numbers;

public void Identify(double[] values)


{
numbers = values;
for (int i = 0; i < values.Length; i++)
numbers[i] = values[i];
}
}

To support the use of the foreach loop, the IEnumerable interface is equipped with
(only) a method named GetEnumerator that you must implement. The
IEnumerable.GetEnumerator() method returns an IEnumerator object. When
implementing this method, you can return an object of the class that implements the
IEnumerator interface, passing it the collection that was declared in the IEnumerable
implementer. This can be done as follows: 
public class Enumerable : IEnumerable
{
private double[] numbers;

public void Identify(double[] values)


{
numbers = values;
for (int i = 0; i < values.Length; i++)
numbers[i] = values[i];
}

public IEnumerator GetEnumerator()


{
return new Enumerator(numbers);
}
}

Practical Learning: Getting the Enumerator

1. To create a new class, in the Class View, right-click FlowerShop5 -> Add -> Class...

2. Set the Name of the class to Flowers and click Add

3. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace FlowerShop5
{
public class Flowers : IEnumerable
{
private FlowerInventory items;

public void Locate(FlowerInventory list)


{
C# 3.0 Practical Learning 738
items = new FlowerInventory();

for (int i = 0; i < list.Count; i++)


this.items.Add(list.Get(i));
}

public IEnumerator GetEnumerator()


{
FlowerIdentifier fid = new FlowerIdentifier();

fid.Identify(items);
return fid;
}
}
}

4. Save the file

Using foreach

After implementing the IEnumerator and the IEnumerable interfaces, you can then
use the foreach loop. To start, you must prepare the collection and its items for
processing. Here is an example:
public class Exercise
{
static int Main(string[] args)
{
double[] numbers = new double[5];
numbers[0] = 224.52;
numbers[1] = 60.48;
numbers[2] = 1250.64;
numbers[3] = 8.86;
numbers[4] = 1005.36;

return 0;
}
}

To enumerate the collection, declare a variable based on the implementer of the


IEnumerable and pass the collection to its constructor. Once this is done, you can then
use the foreach. Here is an example:
using System;
using System.Collections;

public class Enumerator : IEnumerator


{
private double[] numbers;
private int cur;

public Enumerator(double[] list)


{
this.numbers = list;
cur = -1;
}

public Object Current

C# 3.0 Practical Learning 739


{
get { return numbers[cur]; }
}

public void Reset()


{
cur = -1;
}

public bool MoveNext()


{
cur++;
if (cur < numbers.Length)
return true;
else
return false;
}
}

public class Enumerable : IEnumerable


{
private double[] numbers;

public void Identify(double[] values)


{
numbers = values;
for (int i = 0; i < values.Length; i++)
numbers[i] = values[i];
}

public IEnumerator GetEnumerator()


{
return new Enumerator(numbers);
}
}

public class Exercise


{
static int Main(string[] args)
{
double[] numbers = new double[5];
numbers[0] = 224.52;
numbers[1] = 60.48;
numbers[2] = 1250.64;
numbers[3] = 8.86;
numbers[4] = 1005.36;

Enumerable coll = new Enumerable();

coll.Identify(numbers);
foreach (double d in coll)
Console.WriteLine("Item {0}", d); ;

return 0;
}
}

Practical Learning: Using foreach on an Enumerator

C# 3.0 Practical Learning 740


1. Access the Program.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlowerShop5
{
public class Program
{
static void Main(string[] args)
{
FlowerInventory fls = new FlowerInventory();
Flower nice;

nice = new Flower();


nice.Type = FlowerType.Lilies;
nice.Color = FlowerColor.White;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 39.95M;
fls.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Mixed;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 40.50M;
fls.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Carnations;
nice.Color = FlowerColor.Lavender;
nice.Arrangement = FlowerArrangement.Any;
nice.UnitPrice = 34.85M;
fls.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Roses;
nice.Color = FlowerColor.Pink;
nice.Arrangement = FlowerArrangement.Bouquet;
nice.UnitPrice = 29.95M;
fls.Add(nice);

nice = new Flower();


nice.Type = FlowerType.Daisies;
nice.Color = FlowerColor.Yellow;
nice.Arrangement = FlowerArrangement.Vase;
nice.UnitPrice = 29.95M;
fls.Add(nice);

Flowers collection = new Flowers();


collection.Locate(fls);

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
Console.WriteLine("Total: {0} flower items in current
inventory",
fls.Count);
C# 3.0 Practical Learning 741
Console.WriteLine("--------------------------------------------");
Console.WriteLine("Inventory Summary");
foreach (Flower flr in collection)
{
Console.WriteLine("------------------------");
Console.WriteLine("Flower Information");
Console.WriteLine("Type: {0}", flr.Type);
Console.WriteLine("Color: {0}", flr.Color);
Console.WriteLine("Arrangement: {0}", flr.Arrangement);
Console.WriteLine("Unit Price: {0:F}", flr.UnitPrice);
}

Console.WriteLine("//=//=//=//=//=//=//=//=//=//=//=//=//=//=//");
}
}
}

2. Execute the application to see the result:


 
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Total: 5 flower items in current inventory
--------------------------------------------
Inventory Summary
------------------------
Flower Information
Type: Lilies
Color: White
Arrangement: Bouquet
Unit Price: 39.95
------------------------
Flower Information
Type: Daisies
Color: Mixed
Arrangement: Bouquet
Unit Price: 40.50
------------------------
Flower Information
Type: Carnations
Color: Lavender
Arrangement: Any
Unit Price: 34.85
------------------------
Flower Information
Type: Roses
Color: Pink
Arrangement: Bouquet
Unit Price: 29.95
------------------------
Flower Information
Type: Daisies
Color: Yellow
Arrangement: Vase
Unit Price: 29.95
//=//=//=//=//=//=//=//=//=//=//=//=//=//=//
Press any key to continue . . .

3. Close the DOS window

C# 3.0 Practical Learning 742


C# 3.0 Practical Learning 743
Introduction to Built-In
Collection Classes
 

Overview of .NET Collections


 

The ICollection Interface

To provide a common abstract techniques of creating and using lists, the .NET
Framework provides the ICollection interface. This interface is equipped with a
property to keep track of the number of items in a list: the Count property. It is also
equipped with a method to copy the items from a list to an array.

Introduction to the ArrayList Class

To support the creation of any kind of list, the Microsoft .NET Framework provides the
ArrayList class. The ArrayList class implements the ICollection interface. This
class can be used to add, locate, or remove an item from a list. The class provides many
other valuable operations routinely done on a list. 

Because of its flexibility, ArrayList is the most used class to create lists of items of any
kind in a .NET application. Besides the ability to handle any type of list, ArrayList is
a good class to study the theory of a collection. The routine operations found in the
ArrayList class are the same found in many other collection-based classes you would
use when creating commercial or graphical applications.

Besides the ability to create a collection, the ArrayList class has the built-in
mechanism for serialization.

The ArrayList class is defined in the System.Collections namespace. Therefore, in


order to use the ArrayList class in your application, you can first include the
System.Collections namespace in the file that would perform ArrayList operations.

Practical Learning: Introducing the ArrayList Class

1. Start Microsoft Visual C# and create a new Console Application named


RealEstate5

2. To save the project, on the Standard toolbar, click the Save All button

3. Accept the suggestions and click Save


C# 3.0 Practical Learning 744
4. To create a new class, in the Solution Explorer, right-click RealEstate5 -> Add ->
Class...

5. Set the Name to Property and click Add

6. Change the file as follows:


  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
public enum PropertyCondition
{
Unknown,
Excellent,
Good,
NeedsRepair,
BadShape
}

[Serializable]
public class Property
{
private string propNbr;
private PropertyCondition cond;
private short beds;
private float baths;
private int yr;
private decimal val;

public string PropertyNumber


{
get { return propNbr; }
set
{
if (propNbr == "")
propNbr = "N/A";
else
propNbr = value;
}
}

public string PropertyType;

public PropertyCondition Condition


{
get { return cond; }
set { cond = value; }
}

public short Bedrooms


{
get
{
if (beds <= 1)

C# 3.0 Practical Learning 745


return 1;
else
return beds;
}
set { beds = value; }
}

public float Bathrooms


{
get { return (baths <= 0) ? 0.00f : baths; }
set { baths = value; }
}

public int YearBuilt


{
get { return yr; }
set { yr = value; }
}

public decimal Value


{
get { return (val <= 0) ? 0.00M : val; }
set { val = value; }
}
}
}

7. To create a new class, in the Class View, right-click RealEstate5 -> Add -> Class...

8. Set the Name to Condominium and press Enter

9. Change the file as follows:


  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
[Serializable]
public class Condominium : Property
{
private bool handicap;

public Condominium()
{
this.PropertyType = "Condominium";
}

public bool HandicapAccessible


{
get { return handicap; }
set { handicap = value; }
}
}
}

C# 3.0 Practical Learning 746


10.To create a new class, on the main menu, click Project -> Add Class...

11.Set the Name to HouseType and click Add

12.Change the file as follows:


  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
[Serializable]
public class HouseType : Property
{
private short nbrOfStories;
private bool basement;
private bool garage;

public short Stories


{
get { return nbrOfStories; }
set { nbrOfStories = value; }
}

public bool FinishedBasement


{
get { return basement; }
set { basement = value; }
}

public bool IndoorGarage


{
get { return garage; }
set { garage = value; }
}
}
}

13.To create a new class, in the Solution Explorer, right-click RealEstate5 -> Add ->
Class...

14.Set the Name to Townhouse and press Enter

15.Change the file as follows:


  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
[Serializable]
public class Townhouse : HouseType
{
private bool comm;
C# 3.0 Practical Learning 747
public Townhouse()
{
this.PropertyType = "Townhouse";
}

public bool IsCommunityManaged


{
get { return this.comm; }
set { this.comm = value; }
}
}
}

16.To create a new class, in the Class View, right-click RealEstate5 -> Add -> Class...

17.Set the Name to SingleFamily and click Add

18.Change the file as follows:


  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
[Serializable]
public class SingleFamily : HouseType
{
public SingleFamily()
{
this.PropertyType = "Single Family";
}
}
}

19.Save all

The Capacity of a List

After declaring an ArrayList variable, it is empty. As objects are added to it, the list
grows. The list can grow tremendously as you wish. The number of items of the list is
managed through the memory it occupies and this memory grows as needed. The
number of items that the memory allocated is currently using is represented by the
ArrayList.Capacity property. This will usually be the least of your concerns.

If for some reason, you want to intervene and control the number of items that your
ArrayList list can contain, you can manipulate the Capacity property. For example,
you can assign it a constant to set the maximum value that the list can contain. Once
again, you will hardly have any reason to use the Capacity property: the compiler
knows what to do with it.

If you set a fixed size on an ArrayList list, you may not be able to add a new item
beyond the limit. In fact, if you attempt to do this, you may receive an error. A safe way

C# 3.0 Practical Learning 748


is to check whether the list is fixed before performing a related operation. To find out
whether a list is fixed, you can check the ArrayList variable's IsFixedSize property.

A Read-Only List

One of the reason for creating a list is to be able to add items to it, edit its items,
retrieve an items, or delete items from it. These are the default operations. You can still
limit these operations as you judge them unnecessary. For example, you may create a
list and then initialize it with the items that you want the list to only have. If you don't
intend to have the user adding items to it, you can create the list as read-only. To do
this, you can call the ArrayList.ReadOnly() method. It is overloaded with two
versions as follows:
public static ArrayList ReadOnly(ArrayList);
public static IList ReadOnly(IList);

This method is static. This means that you don't need to declare an instance of
ArrayList to call them. Instead, to make the list read-only, call the
ArrayList.ReadOnly() method and pass your ArrayList variable to it.

As we will see in the next sections, some operations cannot be performed on a read-only
list. To perform such operations, you can first find out whether an ArrayList list is
read-only. This is done by checking its IsReadOnly property.

Item Addition

The primary operation performed on a list is to create one. One of the biggest
advantages of using a linked list is that you don't have to specify in advance the number
of items of the list as done for an array. You can just start adding items. The ArrayList
class makes this possible with the Add() method. Its syntax is:
public virtual int Add(object value);

The argument of this method is the value to add to the list. If the method succeeds with
the addition, it returns the position where the value was added in the list. This is usually
the last position in the list. If the method fails, the compiler would throw an error. One
of the errors that could result from failure of this operation would be based on the fact
that either a new item cannot be added to the list because the list is read-only, or the
list was already full prior to adding the new item. Normally, a list can be full only if you
had specified the maximum number of items it can contain using the
ArrayList.Capacity property. As mentioned above, the list can be made read-only by
passing its variable to the ArrayList.ReadOnly() method.

Practical Learning: Adding Items to an ArrayList List

1. To create an inventory, on the main menu, click Project -> Add Class...

2. Set the Name to PropertyManagement and press Enter

3. Change the file as follows:


 

C# 3.0 Practical Learning 749


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;

namespace RealEstate5
{
public class PropertyManagement
{
private Condominium Condo;
private Townhouse TownHome;
private SingleFamily House;
private ArrayList Condominiums;
private ArrayList Townhouses;
private ArrayList SingleFamilies;

private string strPropertyNumber;


private string strPropertiesDirectory;

public PropertyManagement()
{
Condo = new Condominium();
TownHome = new Townhouse();
House = new SingleFamily();
Condominiums = new ArrayList();
Townhouses = new ArrayList();
SingleFamilies = new ArrayList();

strPropertyNumber = "000000";

strPropertiesDirectory = @"C:\Altair Realty\Properties";

try
{
// If a directory for the properties has not yet
// been created, then create them
Directory.CreateDirectory(strPropertiesDirectory);
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("The directory could " +
"not be created");
}
}

public PropertyCondition GetPropertyCondition()


{
short condition = 0;

try
{
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.Write("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
C# 3.0 Practical Learning 750
Console.Write("Enter Property Condition: ");
condition = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the condition of the property is not valid");
}

if (condition == 1)
return PropertyCondition.Excellent;
else if (condition == 2)
return PropertyCondition.Good;
else if (condition == 3)
return PropertyCondition.NeedsRepair;
else if (condition == 4)
return PropertyCondition.BadShape;
else
return PropertyCondition.Unknown;
}

public void CreateProperty()


{
char propType = '0';

Console.WriteLine("\n=======================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("-=- Property Creation -=-");
Console.WriteLine("------------------------");

// We will make sure that no two


// properties have the same number
Console.Write("\nEnter Property #: ");
this.strPropertyNumber = Console.ReadLine();

try
{
Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Condominium");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Single Family");
Console.Write("Enter Type of Property: ");
propType = char.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the type of property is invalid");
}

switch (propType)
{
case '1':
CreateCondominium();
break;
case '2':
CreateTownhouse();
break;
case '3':
CreateSingleFamily();
C# 3.0 Practical Learning 751
break;
default:
Console.WriteLine("Invalid Choice!!!");
break;
}
}

public void CreateCondominium()


{
char answer = 'n';

Condo.PropertyNumber = strPropertyNumber;
Condo.Condition = GetPropertyCondition();

try
{
Console.Write("\nHow many bedrooms? ");
Condo.Bedrooms = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}

try
{
Console.Write("How many bathrooms? ");
Condo.Bathrooms =
float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid value");
}

try
{
Console.Write("Year built: ");
Condo.YearBuilt =
int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"built in that year");
}

Console.Write("\nIs the building " +


"accessible to handicapped (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
Condo.HandicapAccessible = true;
else
Condo.HandicapAccessible = false;

try
{
Console.Write("Condominium Value: ");
Condo.Value = decimal.Parse(Console.ReadLine());
C# 3.0 Practical Learning 752
}
catch (FormatException)
{
Console.WriteLine("Invalid Property Value");
}

Condominiums.Add(Condo);
ShowTitle();
ShowCondominium();
SaveCondominium();
}

public void CreateTownhouse()


{
char answer = 'n';

this.TownHome.PropertyNumber = strPropertyNumber;
this.TownHome.Condition = GetPropertyCondition();

try
{
Console.Write("\nHow many stories (levels)? ");
this.TownHome.Stories =
short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The number of stories " +
"you entered is not valid");
}

try
{
Console.Write("How many bedrooms? ");
this.TownHome.Bedrooms =
short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}

try
{
Console.Write("How many bathrooms? ");
this.TownHome.Bathrooms =
float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid bathroom number.");
}

Console.Write("Does it have an indoor " +


"car garage (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
this.TownHome.IndoorGarage = true;
else
C# 3.0 Practical Learning 753
this.TownHome.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
this.TownHome.FinishedBasement = true;
else
this.TownHome.FinishedBasement = false;

try
{
Console.Write("Year built: ");
this.TownHome.YearBuilt =
int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"built in that year");
}

try
{
Console.Write("Is it community managed (y/n)? ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
this.TownHome.IsCommunityManaged = true;
else
this.TownHome.IsCommunityManaged = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Answer");
}

try
{
Console.Write("Property Value: ");
this.TownHome.Value = decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Property Value");
}

Townhouses.Add(this.TownHome);
ShowTitle();
ShowTownhouse();
SaveTownhouse();
}

public void CreateSingleFamily()


{
char answer = 'n';

Console.WriteLine(" =//= Altair Realty =//=");


Console.WriteLine("-=- Property Creation -=-");

this.House.PropertyNumber = strPropertyNumber;
House.Condition = GetPropertyCondition();

C# 3.0 Practical Learning 754


try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The number of stories you " +
"entered is not allowed");
}

try
{
Console.Write("How many bedrooms? ");
House.Bedrooms =
short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}

try
{
Console.Write("How many bathrooms? ");
House.Bathrooms =
float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid number of bathrooms");
}

try
{
Console.Write("Does it have an indoor " +
"car garage (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Indoor Car Garage Answer");
}
try
{
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Basement Answer");
C# 3.0 Practical Learning 755
}
try
{
Console.Write("Year built: ");
House.YearBuilt =
int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"built in that year");
}

try
{
Console.Write("House Value: ");
House.Value = decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Property Value");
}

SingleFamilies.Add(House);
ShowTitle();
ShowSingleFamily();
SaveSingleFamily();
}

public void ShowTitle()


{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
}

public void ShowCondominium()


{
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
Condo.PropertyNumber);
Console.WriteLine("Property Type: {0}",
Condo.PropertyType);
Console.WriteLine("Condition: {0}",
Condo.Condition);
Console.WriteLine("Bedrooms: {0}",
Condo.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
Condo.Bathrooms);
Console.WriteLine("Year Built: {0}",
Condo.YearBuilt);
Console.WriteLine("Handicapped Accessible Building: {0}",
Condo.HandicapAccessible);
Console.WriteLine("Market Value: {0:C}",
Condo.Value);
Console.WriteLine("----------------------------------");
}

public void ShowTownhouse()


{
C# 3.0 Practical Learning 756
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
TownHome.PropertyNumber);
Console.WriteLine("Property Type: {0}",
TownHome.PropertyType);
Console.WriteLine("Stories: {0}",
TownHome.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
TownHome.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
TownHome.FinishedBasement);
Console.WriteLine("Condition: {0}",
TownHome.Condition);
Console.WriteLine("Bedrooms: {0}",
TownHome.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
TownHome.Bathrooms);
Console.WriteLine("Year Built: {0}",
TownHome.YearBuilt);
Console.WriteLine("Community Managed? {0}",
TownHome.IsCommunityManaged);
Console.WriteLine("Market Value: {0:C}",
TownHome.Value);
Console.WriteLine("----------------------------------");
}

public void ShowSingleFamily()


{
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
House.PropertyNumber);
Console.WriteLine("Property Type: {0}",
House.PropertyType);
Console.WriteLine("Stories: {0}",
House.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
House.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
House.FinishedBasement);
Console.WriteLine("Condition: {0}",
House.Condition);
Console.WriteLine("Bedrooms: {0}",
House.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
House.Bathrooms);
Console.WriteLine("Year Built: {0}",
House.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
House.Value);
Console.WriteLine("----------------------------------");
}

public void SaveCondominium()


{
FileStream fsCondo = null;
BinaryFormatter bfCondo = new BinaryFormatter();

string strFilename = strPropertiesDirectory +


@"\Condominiums.alr";

C# 3.0 Practical Learning 757


try
{
fsCondo = new FileStream(strFilename,
FileMode.Create,
FileAccess.Write);
bfCondo.Serialize(fsCondo, Condominiums);
}
finally
{
fsCondo.Close();
}
}

public void SaveTownhouse()


{
FileStream fsTown = null;
BinaryFormatter bfTown =
new BinaryFormatter();

string strFilename = strPropertiesDirectory +


@"\Townhouses.alr";

try
{
fsTown = new FileStream(strFilename,
FileMode.Create,
FileAccess.Write);
bfTown.Serialize(fsTown, Townhouses);
}
finally
{
fsTown.Close();
}
}

public void SaveSingleFamily()


{
FileStream fsHouse = null;
BinaryFormatter bfHouse = new BinaryFormatter();

string strFilename = strPropertiesDirectory +


@"\SingleFamilies.alr";

try
{
fsHouse = new FileStream(strFilename,
FileMode.Create,
FileAccess.Write);
bfHouse.Serialize(fsHouse,
SingleFamilies);
}
finally
{
fsHouse.Close();
}
}
}
}

C# 3.0 Practical Learning 758


4. Access the Program.cs file and change it as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
public class Program
{
static void Main(string[] args)
{
var answer = 'q';
var listing = new PropertyManagement();

// Display the title


Console.WriteLine("=================================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("----------------------------------");
do
{
// Ask the user to select an option
try
{
Console.WriteLine("What do you want to do?");
Console.WriteLine("1. Create a property");
Console.WriteLine("0. Quit");
Console.Write("Your Choice? ");
answer = char.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Choice!!!");
}

switch (answer)
{
case '1':
listing.CreateProperty();
break;
default:
break;
}
} while(answer == '1');

Console.WriteLine();
}
}
}

5. Execute the application and continually create the following properties:


 
=================================
=//= Altair Realty =//=
----------------------------------
What do you want to do?
1. Create a property
C# 3.0 Practical Learning 759
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 000001

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
Enter Type of Property: 1

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 1

How many bedrooms? 1


How many bathrooms? 1
Year built: 1960

Is the building accessible to handicapped (y/n): n


Condominium Value: 10000
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 000001
Property Type: Condominium
Condition: Excellent
Bedrooms: 1
Bathrooms: 1.00
Year Built: 1960
Handicapped Accessible Building: False
Market Value: $10,000.00
----------------------------------

What do you want to do?


1. Create a property
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 000002

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
C# 3.0 Practical Learning 760
Enter Type of Property: 2

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 1

How many stories (levels)? 1


How many bedrooms? 1
How many bathrooms? 1
Does it have an indoor car garage (y/n): n
Is the basement finished(y/n): n
Year built: 1960
Is it community managed (y/n)? n
Property Value: 20000
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 000002
Property Type: Townhouse
Stories: 1
Has Indoor Car Garage: False
Finished Basement: False
Condition: Excellent
Bedrooms: 1
Bathrooms: 1.00
Year Built: 1960
Community Managed? False
Market Value: $20,000.00
----------------------------------

What do you want to do?


1. Create a property
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 000003

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
Enter Type of Property: 3
=//= Altair Realty =//=
-=- Property Creation -=-

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 1
C# 3.0 Practical Learning 761
How many stories (levels)? 1
How many bedrooms? 1
How many bathrooms? 1
Does it have an indoor car garage (y/n): n
Is the basement finished(y/n): n
Year built: 1960
House Value: 30000
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 000003
Property Type: Single Family
Stories: 1
Has Indoor Car Garage: False
Finished Basement: False
Condition: Excellent
Bedrooms: 1
Bathrooms: 1.00
Year Built: 1960
Market Value: $30,000.00
----------------------------------

What do you want to do?


1. Create a property
0. Quit
Your Choice? 0

Press any key to continue . . .

6. Close the DOS window

The Number of Items in the List

When using a list, at any time, you should be able to know the number of items that the
list contains. This information is provided by the ArrayList.Count property. The
Capacity and the Count have this in common: the value of each increases as the list
grows and the same value decreases if the list shrinks. It is important to know that,
although they look alike, there are various differences between the capacity of a list and
the number of items it contains. Capacity is a read/write property. This means that, as
we saw above, you can assign a value to the capacity to fix the number of items that
the list can contain. You can also retrieve the value of the Capacity. The Count is read-
only because it is used by the compiler to count the current number of items of the
items and this counting is performed without your intervention.

Item Retrieval

Once a list is ready, you can perform different types of operations on it. Besides adding
items, one of the most regular operations performed on a list consists of locating and
retrieving its items. You have various options. To retrieve a single item based on its
position, you can apply the square brackets of arrays to the variable. Like a normal
array, an ArrayList list is zero-based. Another issue to keep in mind is that the
ArrayList[] returns an Object value. Therefore, you may have to cast this value to
your type of value to get it right.
C# 3.0 Practical Learning 762
Besides using the index to access an item from the list, ArrayList class implements the
IEnumerable.GetEnumerator() method. For this reason, you can use the foreach
loop to access each member of the collection.

Practical Learning: Retrieving Items From an ArrayList List

1. Change the PropertyManagement.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;

namespace RealEstate5
{
public class PropertyManagement
{
private Condominium Condo;
private Townhouse TownHome;
private SingleFamily House;
ArrayList Condominiums;
ArrayList Townhouses;
ArrayList SingleFamilies;

string strPropertyNumber;
string strPropertiesDirectory;

public PropertyManagement()
{
Condo = new Condominium();
TownHome = new Townhouse();
House = new SingleFamily();
Condominiums = new ArrayList();
Townhouses = new ArrayList();
SingleFamilies = new ArrayList();

strPropertyNumber = "000000";

strPropertiesDirectory = @"C:\Altair Realty\Properties";

try
{
// If a directory for the properties has not yet
// been created, then create them
Directory.CreateDirectory(strPropertiesDirectory);
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("The directory could not be created");
}
}

public PropertyCondition GetPropertyCondition()


{
C# 3.0 Practical Learning 763
short condition = 0;

try
{
Console.WriteLine("\nProperties Conditions");
Console.WriteLine("1. Excellent");
Console.WriteLine("2. Good (may need minor repair)");
Console.WriteLine("3. Needs Repair");
Console.Write("4. In Bad Shape (property needs ");
Console.WriteLine("major repair or rebuild)");
Console.Write("Enter Property Condition: ");
condition = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the condition of the property is not
valid");
}

if (condition == 1)
return PropertyCondition.Excellent;
else if (condition == 2)
return PropertyCondition.Good;
else if (condition == 3)
return PropertyCondition.NeedsRepair;
else if (condition == 4)
return PropertyCondition.BadShape;
else
return PropertyCondition.Unknown;
}

public void CreateProperty()


{
char propType = '0';
bool found = false;
FileStream fsProperties = null;
BinaryFormatter bfProperties = new BinaryFormatter();

Console.WriteLine("\n=======================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("-=- Property Creation -=-");
Console.WriteLine("------------------------");

// We will make sure that no two


// properties have the same number
Console.Write("\nEnter Property #: ");
this.strPropertyNumber = Console.ReadLine();

try
{
fsProperties = new FileStream(strPropertiesDirectory +
@"\Condominiums.alr",
FileMode.Open,
FileAccess.Read);
Condominiums =
(ArrayList)bfProperties.Deserialize(fsProperties);

foreach (Condominium c in Condominiums)


{
C# 3.0 Practical Learning 764
if (c.PropertyNumber == this.strPropertyNumber)
{
found = true;
}
}
}
catch (FileNotFoundException)
{
Console.WriteLine("The Condominiums list was not found");
}
finally
{
fsProperties.Close();
}

try
{
fsProperties = new FileStream(strPropertiesDirectory +
@"\Townhouses.alr",
FileMode.Open,
FileAccess.Read);
Townhouses =
(ArrayList)bfProperties.Deserialize(fsProperties);

foreach (Townhouse t in Townhouses)


{
if (t.PropertyNumber == this.strPropertyNumber)
{
found = true;
}
}
}
finally
{
fsProperties.Close();
}

try
{
fsProperties = new FileStream(strPropertiesDirectory +
@"\SingleFamilies.alr",
FileMode.Open,
FileAccess.Read);
SingleFamilies =
(ArrayList)bfProperties.Deserialize(fsProperties);

foreach (SingleFamily s in SingleFamilies)


{
if (s.PropertyNumber == this.strPropertyNumber)
{
found = true;
}
}
}
finally
{
fsProperties.Close();
}

if (found == true)
C# 3.0 Practical Learning 765
{
Console.WriteLine("A property with that " +
"number exists already");
return;
}

try
{
Console.WriteLine("\nTypes of Properties");
Console.WriteLine("1. Condominium");
Console.WriteLine("2. Townhouse");
Console.WriteLine("3. Single Family");
Console.Write("Enter Type of Property: ");
propType = char.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the type of property is invalid");
}

switch (propType)
{
case '1':
CreateCondominium();
break;
case '2':
CreateTownhouse();
break;
case '3':
CreateSingleFamily();
break;
default:
Console.WriteLine("Invalid Choice!!!");
break;
}
}

public void CreateCondominium()


{
char answer = 'n';

Condo.PropertyNumber = strPropertyNumber;
Condo.Condition = GetPropertyCondition();

try
{
Console.Write("\nHow many bedrooms? ");
Condo.Bedrooms = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}

try
{
Console.Write("How many bathrooms? ");
Condo.Bathrooms =
C# 3.0 Practical Learning 766
float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid value");
}

try
{
Console.Write("Year built: ");
Condo.YearBuilt =
int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"built in that year");
}

Console.Write("\nIs the building " +


"accessible to handicapped (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
Condo.HandicapAccessible = true;
else
Condo.HandicapAccessible = false;

try
{
Console.Write("Condominium Value: ");
Condo.Value = decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Property Value");
}

Condominiums.Add(Condo);
ShowTitle();
ShowCondominium();
SaveCondominium();
}

public void CreateTownhouse()


{
char answer = 'n';

this.TownHome.PropertyNumber = strPropertyNumber;
this.TownHome.Condition = GetPropertyCondition();

try
{
Console.Write("\nHow many stories (levels)? ");
this.TownHome.Stories =
short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The number of stories " +
"you entered is not valid");
C# 3.0 Practical Learning 767
}

try
{
Console.Write("How many bedrooms? ");
this.TownHome.Bedrooms =
short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}

try
{
Console.Write("How many bathrooms? ");
this.TownHome.Bathrooms =
float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid bathroom number.");
}

Console.Write("Does it have an indoor " +


"car garage (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
this.TownHome.IndoorGarage = true;
else
this.TownHome.IndoorGarage = false;
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
this.TownHome.FinishedBasement = true;
else
this.TownHome.FinishedBasement = false;

try
{
Console.Write("Year built: ");
this.TownHome.YearBuilt =
int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"built in that year");
}

try
{
Console.Write("Is it community managed (y/n)? ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
this.TownHome.IsCommunityManaged = true;
else
this.TownHome.IsCommunityManaged = false;
}
C# 3.0 Practical Learning 768
catch (FormatException)
{
Console.WriteLine("Invalid Answer");
}

try
{
Console.Write("Property Value: ");
this.TownHome.Value =
decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Property Value");
}

Townhouses.Add(this.TownHome);
ShowTitle();
ShowTownhouse();
SaveTownhouse();
}

public void CreateSingleFamily()


{
char answer = 'n';

Console.WriteLine(" =//= Altair Realty =//=");


Console.WriteLine("-=- Property Creation -=-");

this.House.PropertyNumber = strPropertyNumber;
House.Condition = GetPropertyCondition();

try
{
Console.Write("\nHow many stories (levels)? ");
House.Stories = short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The number of stories you " +
"entered is not allowed");
}

try
{
Console.Write("How many bedrooms? ");
House.Bedrooms =
short.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered for " +
"the number of bedrooms is not good");
}

try
{
Console.Write("How many bathrooms? ");
House.Bathrooms =
float.Parse(Console.ReadLine());
C# 3.0 Practical Learning 769
}
catch (FormatException)
{
Console.WriteLine("Invalid number of bathrooms");
}

try
{
Console.Write("Does it have an indoor " +
"car garage (y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.IndoorGarage = true;
else
House.IndoorGarage = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Indoor Car Garage Answer");
}
try
{
Console.Write("Is the basement finished(y/n): ");
answer = char.Parse(Console.ReadLine());
if ((answer == 'y') || (answer == 'Y'))
House.FinishedBasement = true;
else
House.FinishedBasement = false;
}
catch (FormatException)
{
Console.WriteLine("Invalid Basement Answer");
}
try
{
Console.Write("Year built: ");
House.YearBuilt =
int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The house cannot have " +
"built in that year");
}

try
{
Console.Write("House Value: ");
House.Value = decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Property Value");
}

SingleFamilies.Add(House);
ShowTitle();
ShowSingleFamily();
SaveSingleFamily();
}
C# 3.0 Practical Learning 770
public void ShowTitle()
{
Console.WriteLine("==================================");
Console.WriteLine(" =//=//= Altair Realty =//=//=");
Console.WriteLine("-=-=-=- Properties Listing -=-=-=-");
}

public void ShowCondominium()


{
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
Condo.PropertyNumber);
Console.WriteLine("Property Type: {0}",
Condo.PropertyType);
Console.WriteLine("Condition: {0}",
Condo.Condition);
Console.WriteLine("Bedrooms: {0}",
Condo.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
Condo.Bathrooms);
Console.WriteLine("Year Built: {0}",
Condo.YearBuilt);
Console.WriteLine("Handicapped Accessible Building: {0}",
Condo.HandicapAccessible);
Console.WriteLine("Market Value: {0:C}",
Condo.Value);
Console.WriteLine("----------------------------------");
}

public void ShowTownhouse()


{
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
TownHome.PropertyNumber);
Console.WriteLine("Property Type: {0}",
TownHome.PropertyType);
Console.WriteLine("Stories: {0}",
TownHome.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
TownHome.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
TownHome.FinishedBasement);
Console.WriteLine("Condition: {0}",
TownHome.Condition);
Console.WriteLine("Bedrooms: {0}",
TownHome.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
TownHome.Bathrooms);
Console.WriteLine("Year Built: {0}",
TownHome.YearBuilt);
Console.WriteLine("Community Managed? {0}",
TownHome.IsCommunityManaged);
Console.WriteLine("Market Value: {0:C}",
TownHome.Value);
Console.WriteLine("----------------------------------");
}

public void ShowSingleFamily()


{
C# 3.0 Practical Learning 771
Console.WriteLine("----------------------------------");
Console.WriteLine("Property #: {0}",
House.PropertyNumber);
Console.WriteLine("Property Type: {0}",
House.PropertyType);
Console.WriteLine("Stories: {0}",
House.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
House.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
House.FinishedBasement);
Console.WriteLine("Condition: {0}",
House.Condition);
Console.WriteLine("Bedrooms: {0}",
House.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
House.Bathrooms);
Console.WriteLine("Year Built: {0}",
House.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
House.Value);
Console.WriteLine("----------------------------------");
}

public void SaveCondominium()


{
FileStream fsCondo = null;
BinaryFormatter bfCondo = new BinaryFormatter();

string strFilename = strPropertiesDirectory +


@"\Condominiums.alr";

try
{
fsCondo = new FileStream(strFilename,
FileMode.Create,
FileAccess.Write);
bfCondo.Serialize(fsCondo, Condominiums);
}
finally
{
fsCondo.Close();
}
}

public void SaveTownhouse()


{
FileStream fsTown = null;
BinaryFormatter bfTown = new BinaryFormatter();

string strFilename = strPropertiesDirectory +


@"\Townhouses.alr";

try
{
fsTown = new FileStream(strFilename,
FileMode.Create,
FileAccess.Write);
bfTown.Serialize(fsTown, Townhouses);
}
C# 3.0 Practical Learning 772
finally
{
fsTown.Close();
}
}

public void SaveSingleFamily()


{
FileStream fsHouse = null;
BinaryFormatter bfHouse =
new BinaryFormatter();

string strFilename = strPropertiesDirectory +


@"\SingleFamilies.alr";

try
{
fsHouse =
new FileStream(strFilename,
FileMode.Create,
FileAccess.Write);
bfHouse.Serialize(fsHouse, SingleFamilies);
}
finally
{
fsHouse.Close();
}
}

public void ShowProperties()


{
int choice = 0;

Console.WriteLine();
ShowTitle();

try
{
Console.WriteLine("What properties do you want to see?");
Console.WriteLine("1. One Particular Property");
Console.WriteLine("2. Condominiums Only");
Console.WriteLine("3. Townhouses Only");
Console.WriteLine("4. Single Families Only");
Console.WriteLine("5. All properties");
Console.WriteLine("6. None");
Console.Write("Your Choice? ");
choice = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Selection");
}

switch (choice)
{
case 1:
ShowParticularProperty();
break;
case 2:
ShowCondominiums();
C# 3.0 Practical Learning 773
break;
case 3:
ShowTownhouses();
break;
case 4:
ShowSingleFamilies();
break;
case 5:
ShowCondominiums();
ShowTownhouses();
ShowSingleFamilies();
break;
default:
break;
}
}

public void ShowParticularProperty()


{
bool found = false;
FileStream fsProperty = null;
BinaryFormatter bfProperty = new BinaryFormatter();

Console.WriteLine("\n=======================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("------------------------");

Console.Write("\nEnter Property #: ");


this.strPropertyNumber = Console.ReadLine();

try
{
fsProperty = new FileStream(strPropertiesDirectory +
@"\Condominiums.alr",
FileMode.Open,
FileAccess.Read);
Condominiums =
(ArrayList)bfProperty.Deserialize(fsProperty);

foreach (Condominium c in Condominiums)


{
if (c.PropertyNumber == this.strPropertyNumber)
{
found = true;
Condo = c;
ShowCondominium();
return;
}
}
}
finally
{
fsProperty.Close();
}

try
{
fsProperty = new FileStream(strPropertiesDirectory +
@"\Townhouses.alr",
FileMode.Open,
C# 3.0 Practical Learning 774
FileAccess.Read);
Townhouses =
(ArrayList)bfProperty.Deserialize(fsProperty);

foreach (Townhouse t in Townhouses)


{
if (t.PropertyNumber == this.strPropertyNumber)
{
found = true;
TownHome = t;
ShowTownhouse();
return;
}
}
}
finally
{
fsProperty.Close();
}

try
{
fsProperty = new FileStream(strPropertiesDirectory +
@"\SingleFamilies.alr",
FileMode.Open,
FileAccess.Read);
SingleFamilies =
(ArrayList)bfProperty.Deserialize(fsProperty);

foreach (SingleFamily s in SingleFamilies)


{
if (s.PropertyNumber == this.strPropertyNumber)
{
found = true;
House = s;
ShowSingleFamily();
return;
}
}
}
finally
{
fsProperty.Close();
}

if (found == false)
{
Console.WriteLine("No property with that " +
"number was found in the database");
return;
}
}

public void ShowCondominiums()


{
FileStream fsProperty = null;
BinaryFormatter bfProperty = new BinaryFormatter();

try
{
C# 3.0 Practical Learning 775
fsProperty = new FileStream(strPropertiesDirectory +
@"\Condominiums.alr",
FileMode.Open,
FileAccess.Read);
Condominiums =
(ArrayList)bfProperty.Deserialize(fsProperty);

Console.WriteLine("\n=================================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("----------------------------------");
Console.WriteLine("Condominiums Listing");
Console.WriteLine("----------------------------------");
foreach (Condominium c in Condominiums)
{
Console.WriteLine("Property #: {0}",
c.PropertyNumber);
Console.WriteLine("Condition: {0}",
c.Condition);
Console.WriteLine("Bedrooms: {0}",
c.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
c.Bathrooms);
Console.WriteLine("Year Built: {0}",
c.YearBuilt);
Console.WriteLine("Handicapped Accessible Building:
{0}",
Condo.HandicapAccessible);
Console.WriteLine("Market Value: {0:C}",
c.Value);

Console.WriteLine("----------------------------------");
}
}
finally
{
fsProperty.Close();
}
}

public void ShowTownhouses()


{
FileStream fsProperty = null;
BinaryFormatter bfProperty = new BinaryFormatter();

try
{
fsProperty = new FileStream(strPropertiesDirectory +
@"\Townhouses.alr",
FileMode.Open,
FileAccess.Read);
Townhouses =
(ArrayList)bfProperty.Deserialize(fsProperty);

Console.WriteLine("\n=================================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("----------------------------------");
Console.WriteLine("Townhouses Listing");
Console.WriteLine("----------------------------------");
foreach (Townhouse t in Townhouses)
{
C# 3.0 Practical Learning 776
Console.WriteLine("Property #: {0}",
t.PropertyNumber);
Console.WriteLine("Stories: {0}",
t.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
t.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
t.FinishedBasement);
Console.WriteLine("Condition: {0}",
t.Condition);
Console.WriteLine("Bedrooms: {0}",
t.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
t.Bathrooms);
Console.WriteLine("Year Built: {0}",
t.YearBuilt);
Console.WriteLine("Community Managed? {0}",
t.IsCommunityManaged);
Console.WriteLine("Market Value: {0:C}",
t.Value);

Console.WriteLine("----------------------------------");
}
}
finally
{
fsProperty.Close();
}
}

public void ShowSingleFamilies()


{
FileStream fsProperty = null;
BinaryFormatter bfProperty = new BinaryFormatter();

try
{
fsProperty = new FileStream(strPropertiesDirectory +
@"\SingleFamilies.alr",
FileMode.Open,
FileAccess.Read);
SingleFamilies =
(ArrayList)bfProperty.Deserialize(fsProperty);

Console.WriteLine("\n================================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("----------------------------------");
Console.WriteLine("Single Families Listing");
Console.WriteLine("----------------------------------");
foreach (SingleFamily s in SingleFamilies)
{
Console.WriteLine("Property #: {0}",
s.PropertyNumber);
Console.WriteLine("Stories: {0}",
s.Stories);
Console.WriteLine("Has Indoor Car Garage: {0}",
s.IndoorGarage);
Console.WriteLine("Finished Basement: {0}",
s.FinishedBasement);
Console.WriteLine("Condition: {0}",
C# 3.0 Practical Learning 777
s.Condition);
Console.WriteLine("Bedrooms: {0}",
s.Bedrooms);
Console.WriteLine("Bathrooms: {0:F}",
s.Bathrooms);
Console.WriteLine("Year Built: {0}",
s.YearBuilt);
Console.WriteLine("Market Value: {0:C}",
s.Value);

Console.WriteLine("----------------------------------");
}
}
finally
{
fsProperty.Close();
}
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RealEstate5
{
public class Program
{
static void Main(string[] args)
{
var answer = 'q';
var listing = new PropertyManagement();

// Display the title


Console.WriteLine("\n================================");
Console.WriteLine(" =//= Altair Realty =//=");
Console.WriteLine("----------------------------------");
do
{
// Ask the user to select an option
try
{
Console.WriteLine("What do you want to do?");
Console.WriteLine("1. Create a property");
Console.WriteLine("2. Show the properties");
Console.WriteLine("3. Delete a property");
Console.WriteLine("0. Quit");
Console.Write("Your Choice? ");
answer = char.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Choice!!!");
}

C# 3.0 Practical Learning 778


switch (answer)
{
case '1':
listing.CreateProperty();
Console.WriteLine("\n");
break;
case '2':
listing.ShowProperties();
break;
case '3':
break;
default:
break;
}
} while ((answer == '1') ||
(answer == '2') ||
(answer == '3'));

Console.WriteLine();
}
}
}

3. Execute the application and test it. Here is an example:


 
================================
=//= Altair Realty =//=
----------------------------------
What do you want to do?
1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 246185

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
Enter Type of Property: 1

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 2

How many bedrooms? 2


How many bathrooms? 2
Year built: 1996

C# 3.0 Practical Learning 779


Is the building accessible to handicapped (y/n): n
Condominium Value: 285660
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 246185
Property Type: Condominium
Condition: Good
Bedrooms: 2
Bathrooms: 2.00
Year Built: 1996
Handicapped Accessible Building: False
Market Value: $285,660.00
----------------------------------

What do you want to do?


1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 512664

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
Enter Type of Property: 2

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 1

How many stories (levels)? 3


How many bedrooms? 3
How many bathrooms? 2.5
Does it have an indoor car garage (y/n): n
Is the basement finished(y/n): y
Year built: 1992
Is it community managed (y/n)? y
Property Value: 435660
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 512664
Property Type: Townhouse
Stories: 3
Has Indoor Car Garage: False
Finished Basement: True
C# 3.0 Practical Learning 780
Condition: Excellent
Bedrooms: 3
Bathrooms: 2.50
Year Built: 1992
Community Managed? True
Market Value: $435,660.00
----------------------------------

What do you want to do?


1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 802664

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
Enter Type of Property: 3
=//= Altair Realty =//=
-=- Property Creation -=-

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 1

How many stories (levels)? 3


How many bedrooms? 4
How many bathrooms? 3.5
Does it have an indoor car garage (y/n): y
Is the basement finished(y/n): y
Year built: 1995
House Value: 755820
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 802664
Property Type: Single Family
Stories: 3
Has Indoor Car Garage: True
Finished Basement: True
Condition: Excellent
Bedrooms: 4
Bathrooms: 3.50
Year Built: 1995
Market Value: $755,820.00
----------------------------------

C# 3.0 Practical Learning 781


What do you want to do?
1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 1

=======================
=//= Altair Realty =//=
-=- Property Creation -=-
------------------------

Enter Property #: 693524

Types of Properties
1. Condominium
2. Townhouse
3. Single Family
Enter Type of Property: 3
=//= Altair Realty =//=
-=- Property Creation -=-

Properties Conditions
1. Excellent
2. Good (may need minor repair)
3. Needs Repair
4. In Bad Shape (property needs major repair or rebuild)
Enter Property Condition: 3

How many stories (levels)? 2


How many bedrooms? 3
How many bathrooms? 2.5
Does it have an indoor car garage (y/n): n
Is the basement finished(y/n): n
Year built: 1964
House Value: 515665
==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
----------------------------------
Property #: 693524
Property Type: Single Family
Stories: 2
Has Indoor Car Garage: False
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 3
Bathrooms: 2.50
Year Built: 1964
Market Value: $515,665.00
----------------------------------

What do you want to do?


1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 0

Press any key to continue . . .


C# 3.0 Practical Learning 782
4. Close the DOS window

5. Execute the application again and test different options. Here are examples:
 
================================
=//= Altair Realty =//=
----------------------------------
What do you want to do?
1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 2

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
What properties do you want to see?
1. One Particular Property
2. Condominiums Only
3. Townhouses Only
4. Single Families Only
5. All properties
6. None
Your Choice? 1

=======================
=//= Altair Realty =//=
------------------------

Enter Property #: 802664


----------------------------------
Property #: 802664
Property Type: Single Family
Stories: 3
Has Indoor Car Garage: True
Finished Basement: True
Condition: Excellent
Bedrooms: 4
Bathrooms: 3.50
Year Built: 1995
Market Value: $755,820.00
----------------------------------
What do you want to do?
1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 2

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
What properties do you want to see?
1. One Particular Property
2. Condominiums Only
3. Townhouses Only
4. Single Families Only
5. All properties
C# 3.0 Practical Learning 783
6. None
Your Choice? 3

=================================
=//= Altair Realty =//=
----------------------------------
Townhouses Listing
----------------------------------
Property #: 000002
Stories: 1
Has Indoor Car Garage: False
Finished Basement: False
Condition: Excellent
Bedrooms: 1
Bathrooms: 1.00
Year Built: 1960
Community Managed? False
Market Value: $20,000.00
----------------------------------
Property #: 512664
Stories: 3
Has Indoor Car Garage: False
Finished Basement: True
Condition: Excellent
Bedrooms: 3
Bathrooms: 2.50
Year Built: 1992
Community Managed? True
Market Value: $435,660.00
----------------------------------
What do you want to do?
1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 2

==================================
=//=//= Altair Realty =//=//=
-=-=-=- Properties Listing -=-=-=-
What properties do you want to see?
1. One Particular Property
2. Condominiums Only
3. Townhouses Only
4. Single Families Only
5. All properties
6. None
Your Choice? 4

================================
=//= Altair Realty =//=
----------------------------------
Single Families Listing
----------------------------------
Property #: 000003
Stories: 1
Has Indoor Car Garage: False
Finished Basement: False
Condition: Excellent
Bedrooms: 1
C# 3.0 Practical Learning 784
Bathrooms: 1.00
Year Built: 1960
Market Value: $30,000.00
----------------------------------
Property #: 802664
Stories: 3
Has Indoor Car Garage: True
Finished Basement: True
Condition: Excellent
Bedrooms: 4
Bathrooms: 3.50
Year Built: 1995
Market Value: $755,820.00
----------------------------------
Property #: 693524
Stories: 2
Has Indoor Car Garage: False
Finished Basement: False
Condition: NeedsRepair
Bedrooms: 3
Bathrooms: 2.50
Year Built: 1964
Market Value: $515,665.00
----------------------------------
What do you want to do?
1. Create a property
2. Show the properties
3. Delete a property
0. Quit
Your Choice? 0

Press any key to continue . . .

6. Close the DOS window

Item Location

Instead of the square brackets that allow you to retrieve an item based on its position,
you can look for an item based on its complete definition. You have various options. You
can first "build" an item and ask the compiler to check whether any item in the list
matches your definition. To perform this search, you can call the
ArrayList.Contains() method. Its syntax is:

public virtual bool Contains(object item);

The item to look for is passed as argument to the method. The compiler would look for
exactly the item, using its definition, in the list. If any detail of the argument fails to
match any item of the ArrayList list, the method would return false. If all
characteristics of the argument correspond to an item of the list, the method returns
true.

Another option to look for an item in a list consists of calling the


ArrayList.BinarySearch() method. It is overloaded in three versions and one of
them uses the following syntax:
public virtual int BinarySearch(object value);

C# 3.0 Practical Learning 785


The item to look for is passed argument to the method.

Item Deletion

As opposed to adding an item to a list, you may want to remove one. To perform this
operation, you have various options. You can ask the compiler to look for an item in the
list and if, or once, the compile finds it, it would delete the item. To perform this type of
deletion, you can call the ArrayList.Remove() method. Its syntax is:
public virtual void Remove(object obj);

This method accepts as argument the item that you want to delete from the list. To
perform this operation, the list must not be read-only.

The Remove() method allows you to specify the exact item you want to delete from a
list. Another option you have consists of deleting an item based on its position. This is
done using the RemoveAt() method whose syntax is:
public virtual void RemoveAt(int index);

With this method, the position of the item is passed as argument. If the position is not
valid because either it is lower or higher than the current Count, the compiler would
throw an ArgumentOutOfRangeException exception.

To remove all items from a list at once, you can call the ArrayList.Clear() method.
Its syntax is:
public virtual void Clear();

C# 3.0 Practical Learning 786


Generics
 

Generic Methods
 

Introduction

As is usually done, imagine you want to pass different types of values to various
methods of a class to primarily accomplish the same purpose. You may be tempted to
overloaded a method in various versions as follows:
using System;

public class Generator

{
// Display the value of an integer
public void Show(int value)
{
Console.WriteLine(value);
}

// Display the value of a double-precesion value


public void Show(double value)
{
Console.WriteLine(value);
}

// Display the value of a character


public void Show(char value)
{
Console.WriteLine(value);
}
}

public class Exercise

{
static int Main()
{
var exo = new Generator();

// Call the version of the method that displays an integer


exo.Show(246);

// Call the version of the method that displays a character


exo.Show('G');

// Call the version of the method that displays a decimal


C# 3.0 Practical Learning 787
exo.Show(355.65);

return 0;
}
}

This would produce:


246
G
355.65
Press any key to continue . . .

We passed a constant value directly to the method when we called it. Remember that
you can also first declare a variable, assign it a value, and then pass that variable to the
method. Here are examples:
public class Exercise
{
static int Main()
{
var exo = new Generator();

// Call the version of the method that displays an integer


var Value1 = 246;
exo.Show(Value1);

// Call the version of the method that displays a character


var Value2 = 'G';
exo.Show(Value2);

// Call the version of the method that displays a decimal


var Value3 = 355.65;
exo.Show(Value3);

return 0;
}
}

Although this is based on the concept of method overloading, another way you can solve
this type of problem is to create one method that doesn't know the type of value that
would be passed to it but the method is equipped to process the value appropriately.
Based on the above program, you can create one method that takes an argument and it
displays its value. To do this, at the time you are defining the method, you only let it
know that it would receive an argument but you don't specify the type of value that it
will process. Such a method is referred to as generic.

Practical Learning: Introducing Generics

1. Start Microsoft Visual C# and create a new Console Application named


CommercialStore1

2. To create a new class, on the main menu, click Project -> Add Class...

3. Set the Name to StoreItem and press Enter

4. Change the file as follows:


 
C# 3.0 Practical Learning 788
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommercialStore1
{
public class StoreItem
{
public class CItem
{
public double Item;
public CItem Next;
}

public CItem Head = null;


public int Size;

public int Count()


{
return Size;
}

public int Add(CItem NewItem)


{
CItem Sample = new CItem();

Sample = NewItem;
Sample.Next = Head;
Head = Sample;

return Size++;
}

public CItem Retrieve(int Position)


{
CItem Current = Head;

for (int i = Count() - 1; i > Position && Current != null;


i--)
{
Current = Current.Next;
}

return Current;
}

public void ShowItem(double item)


{
Console.WriteLine("Item: {0}", item);
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;

namespace CommercialStore1
C# 3.0 Practical Learning 789
{
public class Program
{
static void Main()
{
StoreItem exo = new StoreItem();
StoreItem.CItem Part;

Part = new StoreItem.CItem();


Part.Item = 97.43;
exo.Add(Part);

Part = new StoreItem.CItem();


Part.Item = 274.87;
exo.Add(Part);

Part = new StoreItem.CItem();


Part.Item = 8.7873;
exo.Add(Part);

Part = new StoreItem.CItem();


Part.Item = 2764.4;
exo.Add(Part);

Part = new StoreItem.CItem();


Part.Item = 92.4662;
exo.Add(Part);

Part = new StoreItem.CItem();


Part.Item = 66800.85;
exo.Add(Part);

Console.WriteLine("-=- List of Items -=-");

for (int i = 0; i < exo.Count(); i++)


{
StoreItem.CItem One = exo.Retrieve(i);

exo.ShowItem(One.Item);
}

Console.WriteLine("\nNumber of Items: {0}\n", exo.Count());


}
}
}

6. Execute the application to see the result


 
-=- List of Items -=-
Item: 97.43
Item: 274.87
Item: 8.7873
Item: 2764.4
Item: 92.4662
Item: 66800.9

Number of Items: 6

Press any key to continue . . .


C# 3.0 Practical Learning 790
7. Close the DOS window

Generic Method Creation

A generic method is a method that can process a value whose type is known only when
the variable is accessed. To create a generic method, on the right side of the name of
the method, type the <> operator. Inside of this operator, enter a letter or a name,
which is referred to as parameter type. Here is an example:
public class Generator
{
public void Show<TypeOfValue>()
{
}
}

One of the ways you can use the parameter type is to pass an argument to the method.
You do this by preceding the name of the argument with the parameter type. Here is an
example:
public class Generator
{
public void Show<TypeOfValue>(TypeOfValue value)
{
}
}

In the body of the method, you can process the argument as you see fit. At a minimum,
and based on our earlier program, you can simply display the value by passing it to the
Console.WriteLine() method. Here is an example:

public class Generator


{
public void Show<TypeOfValue>(TypeOfValue value)
{
Console.WriteLine(value);
}
}

By tradition, most programmers and most documents use the letter T for the parameter
type.

Practical Learning: Creating a Generic Method

1. To create a generic method, change the ShowItem() method as follows:


 
public void ShowItem<T>(T item)
{
Console.WriteLine("Item: {0}", item);
}

2. Save the file

Calling a Generic Method

C# 3.0 Practical Learning 791


As mentioned earlier, one of the particularities of a generic method is that, at the time it
is defined, the method doesn't know the type of the parameter. This means that, when
calling the method, you must make sure you clearly specify the type of value that will be
processed. You can do this by directly passing (a constant of) the type of value that the
method will process. Here are different examples of calling our Show() method:
using System;

public class Generator


{
public void Show<TypeOfValue>(TypeOfValue value)
{
Console.WriteLine(value);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator();

// Call the version of the function that displays an integer


var Value1 = 246;
exo.Show(Value1);

// Call the version of the function that displays a character


var Value2 = 'G';
exo.Show(Value2);

// Call the version of the function that displays a decimal


var Value3 = 355.65;
exo.Show(Value3);

return 0;
}
}

When complied and executed, this program would produce:


246
G
355.65
Press any key to continue . . .

As an alternative, you can type the name of the method, followed by angle brackets.
Inside of the brackets, enter the data type of the value that will be processed. After the
angle brackets, open the parentheses and, inside of them, type the constant value that
will be processed. Here are examples:
using System;

public class Generator


{
public void Show<TypeOfValue>(TypeOfValue value)
{
Console.WriteLine(value);
}
}
C# 3.0 Practical Learning 792
public class Program
{
static int Main()
{
var exo = new Generator();

// Call the version of the function that displays an integer


var Value1 = 246;
exo.Show<int>(Value1);

// Call the version of the function that displays a character


var Value2 = 'G';
exo.Show<char>(Value2);

// Call the version of the function that displays a decimal


var Value3 = 355.65;
exo.Show<double>(Value3);

return 0;
}
}

You can also declare the value as a constant before passing it to the method.

Practical Learning: Calling a Generic Method

1. To specify the parameter type of a generic method when calling it, change the
Main() method as follows:
 
class Program
{
static void Main()
{
. . .

Console.WriteLine("-=- List of Items -=-");

for (int i = 0; i < exo.Count(); i++)


{
Exercise.CItem One = exo.Retrieve(i);

exo.ShowItem<double>(One.Item);
}

Console.WriteLine("\nNumber of Items: {0}\n", exo.Count());


}
}

2. Execute the application and notice that it works fine

3. Close the DOS window

A Generic Method With Various Parameters


 

C# 3.0 Practical Learning 793


Introduction

Just like a method can take one argument, it can take various generic parameters. You
can pass one argument as a known type and the other as a generic type. Here is an
example:
using System;

public class Generator


{
public void Show<TypeOfValue>(string msg, TypeOfValue value)
{
Console.WriteLine("{0}: {1}", msg, value);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator();

exo.Show<int>("Integer", 246);

exo.Show<char>("Character", 'G');

exo.Show<double>("Decimal", 355.65);

return 0;
}
}

This would produce:


Integer: 246
Character: G
Decimal: 355.65
Press any key to continue . . .

Although we directly passed the values to the method when calling it, you can first
declare a variable before passing it to the method. Here are examples:
using System;

public class Generator


{
public void Show<TypeOfValue>(string msg, TypeOfValue value)
{
Console.WriteLine("{0}: {1}", msg, value);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator();

var message = "Integer";


const int iValue = 246;
C# 3.0 Practical Learning 794
exo.Show<int>(message, iValue);

message = "Character";
const char cValue = 'G';
exo.Show<char>(message, cValue);

message = "Decimal";
const double dValue = 355.65;
exo.Show<double>(message, dValue);

return 0;
}
}

Practical Learning: Using a Method With Various Parameters

1. Access the StoreItem.cs file

2. To create and use a method with various parameters, make the following changes:
 
namespace CommercialStore1
{
public class StoreItem
{
. . .

public void ShowItem<T>(string content, int index, T item)


{

Console.WriteLine("{0} {1}: {2}", content, index, item);

}
}
}

3. Access the Program.cs file and change it as follows:


 
namespace CommercialStore1
{
class Program
{
static void Main()
{
. . .

for (int i = 0; i < exo.Count(); i++)


{
Exercise.CItem One = exo.Retrieve(i);

exo.ShowItem<double>("Item", i+1, One.Item);


}

Console.WriteLine("\nNumber of Items: {0}\n", exo.Count());


}
}
}

C# 3.0 Practical Learning 795


4. Execute the application
 
-=- List of Items -=-
Item 1: 97.43
Item 2: 274.87
Item 3: 8.7873
Item 4: 2764.4
Item 5: 92.4662
Item 6: 66800.85

Number of Items: 6

Press any key to continue . . .

5. Close the DOS window

A Generic Method With Various Parameter Types

As seen above, you can pass different arguments to a method. You can also pass
different parameter types, in any appropriate order of your choice, to a method. To pass
two parameter types to a method, inside its <> operator, enter the names of two
parameter types separated by a comma. Here is an example:
public class Generator
{
public void Show<FirstType, SecondType>()
{
}
}

If you want to use the parameter types, you can pass an argument for each to the
method. Remember that each parameter type represents a data type; so you can use it
as the type of an argument. Here are examples:
public class Generator
{
public void Show<FirstType, SecondType>(FirstType first,
SecondType second)
{
}
}

In the body of the method, you can then use the arguments as you see fit. For example,
you can display their values by passing them to the Console.WriteLine() method.
Here is an example:
public class Generator
{
public void Show<FirstType, SecondType>(FirstType first,
SecondType second)
{
Console.WriteLine("First: {0}\nSecond: {1}\n", first, second);
}
}

Calling a Generic Method With Various Parameter Types

C# 3.0 Practical Learning 796


To call a method that takes various parameters, you can simply pass it the value of each
argument. Here is an example:
using System;

public class Generator


{
public void Show<FirstType, SecondType>(FirstType first,
SecondType second)
{
Console.WriteLine("First: {0}\nSecond: {1}\n", first, second);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator();

var iValue = 246;


var message = "Some Message";
exo.Show(message, iValue);

return 0;
}
}

This would produce:


First: Some Message
Second: 246

Press any key to continue . . .

An alternative is to specify the type of each argument. To do this, inside the <>
operator on the right side of the name of the method, enter the data types separated by
a comma. Here are examples:
using System;

public class Generator


{
public void Show<FirstType, SecondType>(FirstType first,
SecondType second)
{
Console.WriteLine("First: {0}\nSecond: {1}\n", first, second);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator();

var iValue = 246;


var message = "Some Message";
exo.Show(message, iValue);

C# 3.0 Practical Learning 797


iValue = 85;
var cValue = 'G';
exo.Show<int, char>(iValue, cValue);

var weeklyHours = 42.50d;


var hourlySalary = 25.05;
exo.Show<double, double>(weeklyHours, hourlySalary);

return 0;
}
}

This would produce:


First: Some Message
Second: 246

First: 85
Second: G

First: 42.5
Second: 25.05

Press any key to continue . . .

Notice that the arguments can be of the same type or different types. It is up to you to
determine the type of a particular argument when calling the method.

Generic Classes
 

Introduction

Like a method, a class can be created as a generic. When a class is created as generic, it
is asked to process a value wihtout knowing what type that value is. This means that the
class will known the type of value only when it is called.

To create a generic class, on the right side of the name of the class, type the <>
operator and enter a name for the parameter type. Here is an example:
public class Exercise<TypeOfValue>
{
}

This parameter type is just a representative of a data type. As a data type, you can use
it to declare a variable in the body of the class. Here is an example:
public class Exercise<TypeOfValue>
{
public TypeOfValue value;
}

After declaring such a variable, you can use it in your application. For example, you can
access it outside of the class using the period operator. Inside of the class, one way you
can use the variable is to display its value using one of the methods of the class. Here is
an example:

C# 3.0 Practical Learning 798


public class Exercise<TypeOfValue>
{
public TypeOfValue value;

public void Show()


{
Console.WriteLine("Value: {0}\n", value);
}
}

Practical Learning: Introducing Generic Classes

1. To start a new program, on the main menu, click the File -> New Project ...

2. Click Console Application. Set the Name to CommercialStore2 and press Enter

3. To create a new class, on the main menu, click Project -> Add Class...

4. Set the Name to ListOfItems and click OK

5. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommercialStore2
{
public class ListOfItems
{
public class CItem
{
public double Item;
public CItem Next;
}

public ListOfItems()
{
Head = null;
Size = 0;
}

public CItem Head;


public int Size;

public int Count()


{
return Size;
}

public int Add(CItem NewItem)


{
CItem Sample = new CItem();

Sample = NewItem;
Sample.Next = Head;
Head = Sample;
C# 3.0 Practical Learning 799
return Size++;
}

public CItem Retrieve(int Position)


{
CItem Current = Head;

for (int i = Count() - 1; i > Position && Current != null;


i--)
{
Current = Current.Next;
}

return Current;
}
}
}

6. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommercialStore2
{
public class Program
{
static void Main()
{
ListOfItems exo = new ListOfItems();
ListOfItems.CItem Part;

Part = new ListOfItems.CItem();


Part.Item = 97.43;
exo.Add(Part);

Part = new ListOfItems.CItem();


Part.Item = 274.87;
exo.Add(Part);

Part = new ListOfItems.CItem();


Part.Item = 8.7873;
exo.Add(Part);

Part = new ListOfItems.CItem();


Part.Item = 2764.4;
exo.Add(Part);

Part = new ListOfItems.CItem();


Part.Item = 92.4662;
exo.Add(Part);

Part = new ListOfItems.CItem();


Part.Item = 66800.85;
exo.Add(Part);

C# 3.0 Practical Learning 800


Console.WriteLine("-=- List of Items -=-");

for (int i = 0; i < exo.Count(); i++)


{
ListOfItems.CItem One = exo.Retrieve(i);

Console.WriteLine("Item: {0}", One.Item);


}

Console.WriteLine("\nNumber of Items: {0}\n", exo.Count());


}
}
}

7. Execute the application and test it:


 
-=- List of Items -=-
Item: 97.43
Item: 274.87
Item: 8.7873
Item: 2764.4
Item: 92.4662
Item: 66800.85

Number of Items: 6

Press any key to continue . . .

8. Close the DOS window

Using a Generic Class

After creating a generic class, you can use it. One way to do this, as we have learned in
previous lessons, consists of declaring a variable for it. In previous lessons, to declare a
variable of a class, we would write:
Exercise exo = new Exercise();

If the class is generic, on the right side, type the <> operator. Inside of this operator,
enter the data type that will be processed as the parameter type of the generic class.
Here is an example:
using System;

public class Generator<TypeOfValue>


{
public TypeOfValue value;

public void Show()


{
Console.WriteLine("Value: {0}\n", value);
}
}

public class Exercise


{
static int Main()

C# 3.0 Practical Learning 801


{
Generator<int> exo = new Generator<int>();

return 0;
}
}

You can also declare a variable of a generic type using the var keyword. To do this, use
var on the left side of the variable name, omit the <> operator and the data type. This
would be done as follows:
public class Exercise
{
static int Main()
{
var exo = new Generator<int>();

return 0;
}
}

After declaring the variable, you can then access the member(s) of the class using the
period operator. Here are examples:
using System;

public class Generator<TypeOfValue>


{
public TypeOfValue value;

public void Show()


{
Console.WriteLine("Value: {0}\n", value);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator<int>();

var iValue = 246;


exo.value = iValue;
exo.Show();

return 0;
}
}

Passing a Parameter Type to a Method

We saw that you could declare a variable of a parameter type in the generic class.
Another way you can use it is to pass it as an argument to a method and make the
argument a parameter type. As seen previously, you can use the argument as you see
fit. For example, you can display its value to the console. Here is an example:
using System;

C# 3.0 Practical Learning 802


public class Generator<TypeOfValue>
{
public void Show(TypeOfValue value)
{
Console.WriteLine("Value: {0}\n", value);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator<int>();

var iValue = 246;


exo.Show(iValue);

return 0;
}
}

In the same way, you can pass the parameter type to a constructor of the class. Here is
an example:
public class Generator<TypeOfValue>
{
private TypeOfValue val;

public Exercise(TypeOfValue v)
{
val = v;
}
}

Returning a Parameter Type

Besides, or as opposed to, passing a parameter type, you can create a method that
returns a parameter type. Once again, you can primarily observe the rules we reviewed
for returning a value from a method. Here is an example:
using System;

public class Generator<TypeOfValue>


{
private TypeOfValue val;

public Generator(TypeOfValue v)
{
val = v;
}

public TypeOfValue GetValue()


{
return val;
}
}

public class Exercise


C# 3.0 Practical Learning 803
{
static int Main()
{
var exo = new Generator<double>(35.65);

Console.WriteLine("Value: {0}\n", exo.GetValue());

return 0;
}
}

Practical Learning: Returning a Parameter Type

1. Open the ListOfItems.cs source file

2. To apply what we have reviewed, change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommercialStore2
{
public class ListOfItems
{
public class CItem<T>
{
public double Item;
public CItem<T> Next;
}

public ListOfItems()
{
Head = null;
Size = 0;
}

public CItem<double> Head;


public int Size;

public int Count()


{
return Size;
}

public int Add(CItem<double> NewItem)


{
CItem<double> Sample = new CItem<double>();

Sample = NewItem;
Sample.Next = Head;
Head = Sample;

return Size++;
}

public CItem<double> Retrieve(int Position)


C# 3.0 Practical Learning 804
{
CItem<double> Current = Head;

for (int i = Count() - 1; i > Position && Current != null;


i--)
{
Current = Current.Next;
}

return Current;
}
}
}

3. Access the Program file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommercialStore2
{
public class Program
{
static void Main()
{
ListOfItems exo = new ListOfItems();
ListOfItems.CItem<double> Part;

Part = new ListOfItems.CItem<double>();


Part.Item = 97.43;
exo.Add(Part);

Part = new ListOfItems.CItem<double>();


Part.Item = 274.87;
exo.Add(Part);

Part = new ListOfItems.CItem<double>();


Part.Item = 8.7873;
exo.Add(Part);

Part = new ListOfItems.CItem<double>();


Part.Item = 2764.4;
exo.Add(Part);

Part = new ListOfItems.CItem<double>();


Part.Item = 92.4662;
exo.Add(Part);

Part = new ListOfItems.CItem<double>();


Part.Item = 66800.85;
exo.Add(Part);

Console.WriteLine("-=- List of Items -=-");

for (int i = 0; i < exo.Count(); i++)


{
ListOfItems.CItem<double> One = exo.Retrieve(i);
C# 3.0 Practical Learning 805
Console.WriteLine("Item: {0}", One.Item);
}

Console.WriteLine("\nNumber of Items: {0}\n", exo.Count());


}
}
}

4. Execute the application and test it 

5. Close the DOS window

A Property of the Parameter Type

You can create a property that is of the parameter type of the generic class. There is no
significant rule to follow when creating the property, except that you should remember
that, at the time you are creating the property, the class doesn't know the type of the
parameter. Here is an example:
using System;

public class Generator<TypeOfValue>


{
private TypeOfValue val;

public TypeOfValue Value


{
get { return val; }
set { val = value; }
}

public void Show()


{
Console.WriteLine("Value: {0}\n", val);
}
}

public class Exercise


{
static int Main()
{
var exo = new Generator<int>();

exo.Value = 246;
exo.Show();

return 0;
}
}

A Generic Class With Multiple Parameters


 

Using Multiple Type Parameters

C# 3.0 Practical Learning 806


As done for generic methods, when creating a generic class, you can specify more than
one parameter type. To do this, in the <> operator, after the first generic type, enter a
comma and another generic type. Here is an example:
public class Generator<T, V>
{
}

If you know for sure that the parameters will be of the same type, you can use one
method to process both. Otherwise, you can declare the necessary members for each
type. You can also create a method that would take many arguments with each
argument of a particular type. Here are examples:
using System;

public class Generator<T, V>


{
private T t;
private V v;

public void SetTValue(T value)


{
t = value;
}

public T GetTValue()
{
return t;
}

public void SetVValue(V value)


{
v = value;
}
public V GetVValue()
{
return v;
}

public void Show(T tValue, V vValue)


{
Console.WriteLine("First: {0}\nSecond: {1}", tValue, vValue);
}
}

When declaring a variable for the class, make sure you appropriately specify the list of
parameter types. Here are two examples:
public class Exercise
{
static int Main()
{
Generator<int, int> IntTypes = new Generator<int, int>();
IntTypes.SetTValue(246);
IntTypes.SetVValue(6088);
IntTypes.Show(IntTypes.GetTValue(), IntTypes.GetVValue());

Generator<double, double> DoubleTypes = new Generator<double,


double>();

C# 3.0 Practical Learning 807


DoubleTypes.SetTValue(355.65);
DoubleTypes.SetVValue(1785.426);
DoubleTypes.Show(DoubleTypes.GetTValue(),
DoubleTypes.GetVValue());

Generator<short, decimal> Disparate = new Generator<short,


decimal>();
DoubleTypes.SetTValue(42);
DoubleTypes.SetVValue(245580.35);
DoubleTypes.Show(DoubleTypes.GetTValue(),
DoubleTypes.GetVValue());

return 0;
}
}

You can also declare the variable using the var keyword. To do this, on the left side of
the assignment operator, type only the var keyword and the name of the operator. Here
is an example:
public class Exercise
{
static int Main()
{
var IntTypes = new Generator<int, int>();
IntTypes.SetTValue(246);
IntTypes.SetVValue(6088);
IntTypes.Show(IntTypes.GetTValue(), IntTypes.GetVValue());

var DoubleTypes = new Generator<double, double>();


DoubleTypes.SetTValue(355.65);
DoubleTypes.SetVValue(1785.426);
DoubleTypes.Show(DoubleTypes.GetTValue(),
DoubleTypes.GetVValue());

var Disparate = new Generator<short, decimal>();


DoubleTypes.SetTValue(42);
DoubleTypes.SetVValue(245580.35);
DoubleTypes.Show(DoubleTypes.GetTValue(),
DoubleTypes.GetVValue());

return 0;
}
}

This would produce:


First: 246
Second: 6088
First: 355.65
Second: 1785.426
First: 42
Second: 245580.35
Press any key to continue . . .

If a generic class has more than one parameter type, they don't have to be of the same
type. At the time you are creating the class, you may not specify their types but you can
anticipate that they would be different. It is when you declare the variable that you
would need to determine their precise types.

C# 3.0 Practical Learning 808


Even if the parameters are of primitive types, you can first declare the variables and
pass them to the class.

A Class as a Parameter Type

So far, in our examples, we treated the parameter type as a primitive data type. A
parameter type can also be a formal class, either one that you created yourself or one
that exists as part of the C# language. When creating the generic class, you must follow
all the rules we have reviewed so far for generic classess. Here is such a simple class:
public class Generator
{
public void Show(TypeOfValue val)
{
Console.WriteLine("{0}\n", val.ToString());
}
}

As mentioned already, the class that would be processed by the generic one must have
been previously created so it can be used as a parameter. When declaring a variable of
the generic class, make sure you enter the name of the normal class in place of the
parameter type. Everything else is as we have done so far. Here is an example:
using System;

public class FourSideGeometricFigure


{
private string nm;
private double bs;
private double hg;

public string Name


{
get { return nm; }
set { nm = value; }
}

public double Base


{
get { return bs; }
set { bs = value; }
}

public double Height


{
get { return hg; }
set { hg = value; }
}

public double Area


{
get { return bs * hg; }
}

public override string ToString()


{
string result = "Type: " + nm + "\n" +
"Base: " + bs.ToString() + "\n" +
C# 3.0 Practical Learning 809
"Height: " + hg.ToString() + "\n" +
"Area: " + Area.ToString();
return result;
}
}

public class Generator<TypeOfValue>


{
public void Show(TypeOfValue val)
{
Console.WriteLine("{0}\n", val.ToString());
}
}

public class Exercise


{
static int Main()
{
var sqr = new FourSideGeometricFigure();
sqr.Name = "Square";
sqr.Base = 36.82;
sqr.Height = 36.82;
Generator<FourSideGeometricFigure> exoSquare =
new Generator<FourSideGeometricFigure>();
exoSquare.Show(sqr);

FourSideGeometricFigure rect = new FourSideGeometricFigure();


rect.Name = "Rectangle";
rect.Base = 52.94;
rect.Height = 27.58;

Generator<FourSideGeometricFigure> exoRect =
new Generator<FourSideGeometricFigure>();
exoRect.Show(rect);
return 0;
}
}

You can also declare the variable using the var keyword. Here are examples:
public class Exercise
{
static int Main()
{
var sqr = new FourSideGeometricFigure();
sqr.Name = "Square";
sqr.Base = 36.82;
sqr.Height = 36.82;
var exoSquare = new Generator<FourSideGeometricFigure>();
exoSquare.Show(sqr);

FourSideGeometricFigure rect = new FourSideGeometricFigure();


rect.Name = "Rectangle";
rect.Base = 52.94;
rect.Height = 27.58;

var exoRect = new Generator<FourSideGeometricFigure>();


exoRect.Show(rect);
return 0;
}
C# 3.0 Practical Learning 810
}

This would produce:


Type: Square
Base: 36.82
Height: 36.82
Area: 1355.7124

Type: Rectangle
Base: 52.94
Height: 27.58
Area: 1460.0852

Press any key to continue . . .

In the same way, you can create a generic class that takes more than one parameter

Generic Classes and Inheritance


 

Introduction
Consider the following geometric figures:

Square Rectangle Trapezoid Parallelogram

Notice that these are geometric figures with each having four sides. From what we know
so far, we can create a base class to prepare it for inheritance. If the class is very
general, we can make it a generic one. We can set a data type as an unknown type,
anticipating that the dimensions of the figure can be considered as integer or double-
precision types. Here is an example:
using System;

public class Quadrilateral<T>


{
protected T _base;
protected T _height;
protected string _name;

public virtual T Base


{
get { return _base; }
set { _base = value; }
}

C# 3.0 Practical Learning 811


public virtual T Height
{
get { return _height; }
set { _height = value; }
}

public virtual string Name


{
get { return _name; }
set { _name = value; }
}

public Quadrilateral()
{
_name = "Quadrilateral";
}

public Quadrilateral(string name)


{
_name = "Quadrilateral";
}

public Quadrilateral(T bs, T height)


{
_name = "Quadrilateral";
_base = bs;
_height = height;
}

public Quadrilateral(string name, T bs, T height)


{
_name = name;
_base = bs;
_height = height;
}

public virtual string Describe()


{
return "A quadrilateral is a geometric figure with four
sides";
}

public virtual void ShowCharacteristics()


{
Console.WriteLine("Geometric Figure: {0}", Name);
Console.WriteLine("Description: {0}", Describe());
Console.WriteLine("Base: {0}", Base);
Console.WriteLine("Height: {0}", Height);
}
}

public class Exercise


{
static int Main()
{
// Trapezoid with equal sides
var Kite = new Quadrilateral<double>("Beach Kite", 18.64, 18.64);
Kite.ShowCharacteristics();
C# 3.0 Practical Learning 812
Console.WriteLine();

// Rectangle, in meters
var BasketballStadium = new Quadrilateral<Byte>();
BasketballStadium.Name = "Basketball Stadium";
BasketballStadium.Base = 15;
BasketballStadium.Height = 28;
BasketballStadium.ShowCharacteristics();
Console.WriteLine();

return 0;
}
}

This would produce:


Geometric Figure: Beach Kite
Description: A quadrilateral is a geometric figure with four sides
Base: 18.64
Height: 18.64

Geometric Figure: Basketball Stadium


Description: A quadrilateral is a geometric figure with four sides
Base: 15
Height: 28

Press any key to continue . . .

If you have a generic class that can serve as a foundation for another class, you can
derive one class from the generic one. To do this, use the formula we apply when
deriving a class but follow the name of each class with <>. Inside of the <> operator,
enter the same identifier to indicate that the class is a generic type that is based on
another generic class. Here is an example:
public class Square<T> : Quadrilateral<T>
{
}

In the body of the new class, you can use the parameter type as you see fit. For
example, you can declare some member variables of that type. You can create methods
that return the parameter type or you can pass arguments of the parameter type. When
implementing the methods of the new class, use the member variables of the parameter
and the argument(s) based on the parameter type as you see fit. You can then declare a
variable of the class and use it as we done so far for other generic classes. Here is an
example:
using System;

public class Quadrilateral<T>


{
protected T _base;
protected T _height;
protected string _name;

public virtual T Base


{
get { return _base; }
set { _base = value; }
}
C# 3.0 Practical Learning 813
public virtual T Height
{
get { return _height; }
set { _height = value; }
}

public virtual string Name


{
get { return _name; }
set { _name = value; }
}

public Quadrilateral()
{
_name = "Quadrilateral";
}

public Quadrilateral(string name)


{
_name = "Quadrilateral";
}

public Quadrilateral(T bs, T height)


{
_name = "Quadrilateral";
_base = bs;
_height = height;
}

public Quadrilateral(string name, T bs, T height)


{
_name = name;
_base = bs;
_height = height;
}

public virtual string Describe()


{
return "A quadrilateral is a geometric figure with four
sides";
}

public virtual void ShowCharacteristics()


{
Console.WriteLine("Geometric Figure: {0}", Name);
Console.WriteLine("Description: {0}", Describe());
Console.WriteLine("Base: {0}", Base);
Console.WriteLine("Height: {0}", Height);
}
}

public class Square<T> : Quadrilateral<T>


{
public Square()
{
_name = "Square";
}
public Square(string name)
C# 3.0 Practical Learning 814
{
_name = "Square";
}
public Square(T side)
{
_name = "Square";
_base = side;
_height = side;
}
public Square(string name, T side)
{
_name = name;
_base = side;
_height = side;
}
public override string Describe()
{
return "A square is a quadrilateral with four equal sides";
}
public override void ShowCharacteristics()
{
Console.WriteLine("Geometric Figure: {0}", Name);
Console.WriteLine("Description: {0}", Describe());
Console.WriteLine(" {0}", Describe());
Console.WriteLine("Side: {0}", Base);
}
}

public class Exercise


{
static int Main()
{
// Rectangle, in meters
var plate = new Square<Byte>();

plate.Name = "Plate";
plate.Base = 15;
plate.Height = 28;
plate.ShowCharacteristics();

Console.WriteLine();
return 0;
}
}

This would produce:


Geometric Figure: Plate
Description: A quadrilateral is a geometric figure with four sides
A square is a quadrilateral with four equal sides
Side: 15

Press any key to continue . . .

Generic Classes and Interfaces

As done for a generic class, you can create a generic interface that would serve as the
base for generic classes. To proceed, when creating the interface, follow its name with a

C# 3.0 Practical Learning 815


<> declaration and, inside of the <> operator, enter an identifier for the parameter type.
Here is an example:
public interface IGeometry<T>
{
string Name { get; set; }
void Display();
}

Since this is a generic interface, like an interface class, when deriving a class from it,
follow the formula we reviewed for inheriting from a generic class. Here is an example:
using System;

public interface IGeometry<T>


{
string Name { get; set; }
void Display();
}

public class Round<T> : IGeometry<T>


{
}

When implementing the derived class, you must observe all rules that apply to interface
derivation. Here is an example:
using System;

public interface IGeometry<T>


{
string Name { get; set; }
void Display();
}

public class Round<T> : IGeometry<T>


{
private string _name;

public Round()
{
_name = "Unknown";
}
public Round(string name)
{
_name = name;
}

public virtual string Name


{
get { return _name; }
set { _name = value; }
}

public virtual void Display()


{
Console.WriteLine("Name: {0}", Name);
}
}

C# 3.0 Practical Learning 816


public class Exercise
{
static int Main()
{
var rnd = new Round<decimal>();

rnd.Name = "General Round Shape";


rnd.Display();

Console.WriteLine();
return 0;
}
}

This would produce:


Name: General Round Shape

Press any key to continue . . .

In the same way, you can derive a generic class from another generic class that derived
from a generic interface.

Constraining a Generic Class

Imagine you create a regular interface such as the following:


public interface IGeometry
{
string Name { get; set; }
void Display();
}

Then imagine you derive a regular class from it. Here is an example:
using System;

public interface IGeometry


{
string Name { get; set; }
void Display();
}

public class Round : IGeometry


{
private string _name;
private double _rad;

public Round()
{
_name = "Unknown";
}
public Round(string name)
{
_name = name;
_rad = 0.00;
}
public Round(string name, double radius)
{
C# 3.0 Practical Learning 817
_name = name;
_rad = radius;
}

public virtual string Name


{
get { return _name; }
set { _name = value; }
}

public double Radius


{
get { return _rad; }
set
{
_rad = (value <= 0) ? 0.00 : value;
}
}

public virtual void Display()


{
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("Radius: {0}", Radius);
}
}

public class Exercise


{
static int Main()
{
var rnd = new Round();

rnd.Name = "General Round Shape";


rnd.Radius = 38.24;
rnd.Display();

Console.WriteLine();
return 0;
}
}

You may be tempted to derive just any type of class from it. One of the features of
generics is that you can create a class that must implement the functionality of a certain
abstract class of your choice. For example, when creating a generic class, you can oblige
it to implement the functionality of a certain interface or you can make sure that the
class is derived from a specific base class. This would make sure that the generic class
surely contains some useful functionality.

To create a constraint on a generic class, after the <TypeName> operator, type where
TypeName : followed by the rule that the class must follow. For example, you may want
the generic class to implement the functionality of a pre-defined class. You can create
the generic class as follows:
public interface IGeometry
{
}

public class Round : IGeometry


{
C# 3.0 Practical Learning 818
}

public class Sphere<T>


where T : Round
{
}

After creating the class, you must implement the virtual members of the where
class/interface, using the rules of generic classes, the way we have done it so far. When
declaring a variable for the generic class, in its <> operator, you must enter an object of
the base class. Here is an example:
using System;

public interface IGeometry


{
string Name { get; set; }
void Display();
}

public class Round : IGeometry


{
private string _name;
private double _rad;

public Round()
{
_name = "Unknown";
}
public Round(string name)
{
_name = name;
_rad = 0.00;
}
public Round(string name, double radius)
{
_name = name;
_rad = radius;
}

public virtual string Name


{
get { return _name; }
set { _name = value; }
}

public double Radius


{
get { return _rad; }
set
{
_rad = (value <= 0) ? 0.00 : value;
}
}

public virtual void Display()


{
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("Radius: {0}", Radius);

C# 3.0 Practical Learning 819


}
}

public class Sphere<T>


where T : Round
{
private T _t;

public Sphere() { }
public Sphere(T fig)
{
_t = fig;
}
public T Figure
{
get { return _t; }
set { _t = value; }
}
}

public class Exercise


{
static int Main()
{
var rnd = new Round();

rnd.Name = "Circle";
rnd.Radius = 60.12;

Sphere<Round> sph = new Sphere<Round>();


sph.Figure = rnd;
Console.WriteLine("Circle Characteristics");
Console.WriteLine("Name: {0}", sph.Figure.Name);
Console.WriteLine("Radius: {0}", sph.Figure.Radius);

Console.WriteLine();
return 0;
}
}

This would produce:


Circle Characteristics
Name: Circle
Radius: 60.12

Press any key to continue . . .

You can also create a constraint so that a generic class implements an interface.

C# 3.0 Practical Learning 820


Introduction to File
Processing
 

Overview of File Processing and Definitions


 

Introduction

In Lesson 2, we saw that a piece of information used in an application was primarily


represented as a group of bits. So far, if we requested information from the user, when
the application exited, we lost all information that the user had entered. This is because
such information was only temporarily stored in the random access memory (RAM). In
some cases, you will want to "keep" information that the user has entered so you can
make the information available the next time the user opens the application. In some
other cases, whether you request information from the user or inherently provide it to
the user, you may want different people working from different computers to use or
share the same data. In these and other scenarios, you must store the information
somewhere and retrieve it when necessary. This is the basis of file processing.

  

Files

A file is a series of bytes of data that are arranged in a particular manner to produce a
usable document. For easy storage, location, and management, the bytes are stored
on a medium such as a hard disc, a floppy disc, a compact disc, or any valid and
supported type of storage. When these bytes belong to a single but common entity and
hold values that are stored on a medium, the group is referred to as a file.

For greater management, files can be stored in a parent object called a directory or a
folder. Since a file is a unit of storage and it stores information, it has a size, which is
the number of bits it uses to store its values. To manage it, a file has a location also
called a path that specifies where and/or how the file can be retrieved. Also, for better
management, a file has attributes (characteristics) that indicate what can be done on
the file or that provide specific information that the programmer or the operating
system can use when dealing with the file.

Streams

File processing consists of creating, storing, and/or retrieving the contents of a file from
a recognizable medium. For example, it is used to save word-processed files to a hard

C# 3.0 Practical Learning 821


drive, to store a presentation on floppy disk, or to open a file from a CD-ROM. A
stream is the technique or means of performing file processing. In order to manage files
stored in a computer, each file must be able to provide basic pieces of information about
itself. This basic information is specified when the file is created but can change during
the lifetime of a file.

To create a file, a user must first decide where it would be located: this is a
requirement. A file can be located on the root drive. Alternatively, a file can be
positioned inside of an existing folder. Based on security settings, a user may not be
able to create a file just anywhere in the (file system of the) computer. Once the user
has decided where the file would reside, there are various means of creating files that
the users are trained to use. When creating a file, the user must give it a name following
the rules of the operating system combined with those of the file system. The most
fundamental piece of information a file must have is a name.

Once the user has created a file, whether the file is empty or not, the operating system
assigns basic pieces of information to it. Once a file is created, it can be opened,
updated, modified, renamed, etc.

Streaming Prerequisites
 

Introduction

To support file processing, the .NET Framework provides the System.IO namespace
that contains many different classes to handle almost any type of file operation you may
need to perform. Therefore, to perform file processing, you can include the System.IO
namespace in your project.

The parent class of file processing is Stream. With Stream, you can store data to a
stream or you can retrieve data from a stream. Stream is an abstract class, which
means that you cannot use it to declare a variable in your application. As an abstract
class, Stream is used as the parent of the classes that actually implement the necessary
operations. You will usually use a combination of classes to perform a typical operation.
For example, some classes are used to create a stream object while some others are
used to write data to the created stream.

Practical Learning: Introducing Streaming

1. Start Microsoft Visual C# and create a new Console Application named IceCream3

2. To save the project, on the Standard toolbar, click the Save All button

3. Change the Solution Name to VendingMachine3

4. Accept the Name of the project as IceCream3 and click Save

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to IceCream and click Add

C# 3.0 Practical Learning 822


7. Change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IceCream3
{
delegate void Request();

// This class is used to create and manage an Ice Cream


// and to process an order
public sealed class IceCream
{
// This is the base price of an Ice Cream
// Optional values may be added to it
public const double BasePrice = 1.55D;

// These arrays are used to build the components


// of various Ice Creams
// In C#, we can allocate an array's memory in
// the body of the class
private string[] Flavor;
private string[] Container;
private string[] Ingredient;

// Additional factor used to process an Ice Cream order


private int Scoops;
private double TotalPrice;

// Variables that will hold the user's choice


// These are declared "globally" so they can be
// shared among methods
int ChoiceFlavor;
int ChoiceContainer;
int ChoiceIngredient;

// This default constructor is the best place for


// us to initialize the array
public IceCream()
{
Flavor = new string[10];
Flavor[0] = "Vanilla";
Flavor[1] = "Cream of Cocoa";
Flavor[2] = "Chocolate Chip";
Flavor[3] = "Organic Strawberry";
Flavor[4] = "Butter Pecan";
Flavor[5] = "Cherry Coke";
Flavor[6] = "Chocolate Brownies";
Flavor[7] = "Caramel Au Lait";
Flavor[8] = "Chunky Butter";
Flavor[9] = "Chocolate Cookie";

Ingredient = new string[4];


Ingredient[0] = "No Ingredient";
Ingredient[1] = "Peanuts";
Ingredient[2] = "M & M";
Ingredient[3] = "Cookies";
C# 3.0 Practical Learning 823
Container = new string[3];
Container[0] = "Cone";
Container[1] = "Cup";
Container[2] = "Bowl";
}

// This method requests a flavor from the user and


// returns the choice
internal void ChooseFlavor()
{
// Make sure the user selects a valid number
//that represents a flavor...
do
{
// In case the user types a symbol that
// is not a number
try
{
Console.WriteLine("What type of flavor do you
want?");
for (int i = 0; i < Flavor.Length; i++)
Console.WriteLine("{0} - {1}", i + 1, Flavor[i]);
Console.Write("Your Choice? ");
ChoiceFlavor = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length)
Console.WriteLine("Invalid Choice - Try Again!\n");
} while (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length);
}

// This method allows the user to select a container


internal void ChooseContainer()
{
// Make sure the user selects a valid number that
// represents a container
do
{
// If the user types a symbol that is not a number
try
{
Console.WriteLine("What type of container do you
want?");
for (int i = 0; i < Container.Length; i++)
Console.WriteLine("{0} - {1}", i + 1,
Container[i]);
Console.Write("Your Choice? ");
ChoiceContainer = int.Parse(Console.ReadLine());
}

C# 3.0 Practical Learning 824


catch (FormatException) // display an appropriate
message
{
Console.WriteLine("You must enter a valid " +
"number and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length));
}

internal void ChooseIngredient()


{
do
{
try
{
Console.WriteLine("Do you want an ingredient or
not");
for (int i = 0; i < Ingredient.Length; i++)
Console.WriteLine("{0} - {1}",
i + 1,
Ingredient[i]);
Console.Write("Your Choice? ");
ChoiceIngredient = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid " +
"number and no other character!");
}

if ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length));
}

internal void SpecifyNumberOfScoops()


{
do
{
try
{
Console.Write("How many scoops(1, 2, or 3)? ");
Scoops = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

C# 3.0 Practical Learning 825


if (Scoops < 1 || Scoops > 3)
Console.WriteLine("Invalid Choice - Try Again!");
} while (Scoops < 1 || Scoops > 3);
}

// This method is used to process a customer order


// It uses the values of the above methods
internal void ProcessAnOrder()
{
var PriceIngredient = 0.00D;
var PriceScoop = 0.00D;

// Let the user know that this is a vending machine


Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Vending Machine");
Console.WriteLine("-----------------------------------");

// Let the user select the components of the Ice Cream


Request Get = new Request(ChooseFlavor);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseContainer);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseIngredient);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(SpecifyNumberOfScoops);
Get();
Console.WriteLine("-----------------------------------");

// If the user selects an ingredient instead of "No


Ingredient",
// add $0.50 to the order
if ((ChoiceIngredient == 2) ||
(ChoiceIngredient == 3) ||
(ChoiceIngredient == 4))
PriceIngredient = 0.50D;
else
PriceIngredient = 0.00D;

// Instead of multiplying a number scoops to a value,


// We will use an incremental value depending on
// the number of scoops
if (Scoops == 1)
PriceScoop = 0.65D;
else if (Scoops == 2)
PriceScoop = 1.05D;
else
PriceScoop = 1.55D;

// Calculate the total price of the Ice Cream


TotalPrice = BasePrice + PriceScoop + PriceIngredient;

// Create the Ice Cream...

// And display a receipt to the user


DisplayReceipt();
}

C# 3.0 Practical Learning 826


// This method is used to display a receipt to the user
internal void DisplayReceipt()
{
Console.WriteLine("\n=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Order");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Flavor: {0}",
Flavor[ChoiceFlavor - 1]);
Console.WriteLine("Container: {0}",
Container[ChoiceContainer - 1]);
Console.WriteLine("Ingredient: {0}",
Ingredient[ChoiceIngredient - 1]);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}", TotalPrice);
Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
}
}
}

8. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IceCream3
{
public class Program
{
static void Main(string[] args)
{
var ic = new IceCream();
var process = new Request(ic.ProcessAnOrder);

process();
}
}
}

9. Execute the project and test it. Here is an example:


 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Vending Machine
-----------------------------------
What type of flavor do you want?
1 - Vanilla
2 - Cream of Cocoa
3 - Chocolate Chip
4 - Organic Strawberry
5 - Butter Pecan
6 - Cherry Coke
7 - Chocolate Brownies
8 - Caramel Au Lait
9 - Chunky Butter
10 - Chocolate Cookie
Your Choice? 3
-----------------------------------
C# 3.0 Practical Learning 827
What type of container do you want?
1 - Cone
2 - Cup
3 - Bowl
Your Choice? 5
Invalid Choice - Try Again!
What type of container do you want?
1 - Cone
2 - Cup
3 - Bowl
Your Choice? 3
-----------------------------------
Do you want an ingredient or not
1 - No Ingredient
2 - Peanuts
3 - M & M
4 - Cookies
Your Choice? 8
Invalid Choice - Try Again!
Do you want an ingredient or not
1 - No Ingredient
2 - Peanuts
3 - M & M
4 - Cookies
Your Choice? 4
-----------------------------------
How many scoops(1, 2, or 3)? 3
-----------------------------------

=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Order
-----------------------------------
Flavor: Chocolate Chip
Container: Bowl
Ingredient: Cookies
Scoops: 3
Total Price: $3.60
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Press any key to continue . . .

10.Close the DOS window

The Name of a File

Before performing file processing, one of your early decisions will consist of specifying
the type of operation you want the user to perform. For example, the user may want to
create a brand new file, open an existing file, or perform a routine operation on a file. In
all or most cases, whether you are creating a new file or manipulating an existing one,
you must specify the name of the file. You can do this by declaring a string variable
but, as we will learn later on, most classes used to create a stream can take a string that
represents the file.
If you are creating a new file, there are certainly some rules you must observe. The name of
a file follows the directives of the operating system. On MS DOS and Windows 3.X (that is,
prior to Microsoft Windows 9X), the file had to use the 8.3 format. The actual name had to
have a maximum of 8 characters with restrictions on the characters that could be used. The
user also had to specify three characters after a period. The three characters, known as the
C# 3.0 Practical Learning 828
file extension, were used by the operating system to classify the file. That was all necessary
for those 8-bit and 16-bit operating systems. Various rules have changed. For example, the
names of folders and files on Microsoft Windows >= 95 can have up to 255 characters. The
extension of the file is mostly left to the judgment of the programmer but the files are still
using extensions. Applications can also be configured to save different types of files; that is,
files with different extensions.

At the time of this writing, the rules for file names for Microsoft Windows were
on the MSDN web site at Windows Development\Windows Base
Services\Files and I/O\SDK Documentation\Storage\Storage Overview\File
Management\Creating, Deleting, and Maintaining Files\Naming a File (because
it is a web site and not a book, its pages can change anytime).

Based on this, if you declare a string variable to hold the name of the file, you can
simply initialize the variable with the necessary name and its extension. Here is an
example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Employees.spr";

return 0;
}
}

Practical Learning: Specifying the Name of a File

1. Access the IceCream.cs file and add a new internal method named SaveOrder of
type void as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IceCream3
{
// This class is used to create and manage an Ice Cream
// and to process an order
public sealed class IceCream
{

. . . No Change

// This method is used to display a receipt to the user


internal void DisplayReceipt()
{
. . . No Change
}

internal void SaveOrder()


C# 3.0 Practical Learning 829
{
Console.Write("Please enter your initials or the " +
"name we will use to remember your order: ");
var Filename = Console.ReadLine();
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IceCream3
{
public class Program
{
static void Main(string[] args)
{
var ic = new IceCream();
var process = new Request(ic.ProcessAnOrder);

process();

Console.Write("Do you want us to remember this " +


"order the next time you come to " +
"get your Ice Cream (y/n)? ");
var answer = char.Parse(Console.ReadLine());

if (answer == 'y' || answer == 'Y')


ic.SaveOrder();
}
}
}

3. Execute the project and test it

4. Close the DOS window

The Path to a File

If you declare a string as above, the file will be created in the folder as the application.
Otherwise, you can create your new file anywhere in the hard drive or on another
medium. To do that, you must provide a complete path where the file will reside. A path
is a string that specifies the drive (such as A:, C:, or D:, etc). The sections of a complete
path are separated by a backslash. For example, a path can be made of a folder
followed by the name of the file. An example would be
C:\Palermo.tde

A path can also consist of a drive followed by the name of the folder in which the file will
be created. Here is an example:
C:\Program Files\Palermo.tde

C# 3.0 Practical Learning 830


A path can also indicate that the file will be created in a folder that itself is inside of
another folder. In this case, remember that the names of folders must be separated by
backslashes.

In Lesson 2, we saw that the backslash character is used to create or manage escape
sequences and it can be included in a string value to make up an escape sequence.
Because of this, every time you include a backslash in a string, the compiler thinks that
you are trying to provide an escape sequence. In this case, if the combination of the
backslash and the character that follows the backslash is not recognized as an escape
sequence, you would get an error. To solve this problem, you have two alternatives. To
indicate that the backslash must be considered as a character in its own right, you can
double it. Here are examples:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "C:\\Documents and " +
"Settings\\Business Records\\Employees.spr";

return 0;
}
}

Alternative, you can keep one backslash in each placeholder but precede the value of
the string with the @ symbol. Here is an example:
using System;

public class Exercise


{
static int Main(string[] args)
{
var Filename = @"C:\Documents and " +
"Settings\Business Records\Employees.spr";

return 0;
}
}

In the same way, you can declare a string variable to represent the name of an
existing file that you plan to use in your program. You can also represent its path.

When providing a path to the file, if the drive you specify doesn't exist or cannot be
read, the compiler would consider that the file doesn't exist. If you provide folders that
don't exist in the drive, the compiler would consider that the file doesn't exist. This also
means that the compiler will not create the folder(s) (the .NET Framework provides all
means to create a folder but you must ask the compiler to create it; simply specifying a
folder that doesn't exist will not automatically create it, even if you are creating a new
file). Therefore, it is your responsibility to make sure that either the file or the path to
the file is valid. As we will see in the next section, the compiler can check the existence
of a file or path.

The .NET Support for Files


C# 3.0 Practical Learning 831
 

Introduction

The primary support of a file as an object is provided by a .NET Framework class called
File. This static class is equipped with various types of (static) methods to create, save,
open, copy, move, delete, or check the existence of a file.

File Existence

One of the valuable operations that the File class can perform is to check the existence
of the file you want to use. For example, if you are creating a new file, you may want to
make sure it doesn't exist already because if you try to create a file that exists already,
the compiler may first delete the old file before creating the new one. This could lead to
unpredictable result, especially because such a file is not sent to the Recycle Bin. On the
other hand, if you are trying to open a file, you should first make sure the file exists,
otherwise the compiler will not be able to open a file it cannot find.

To check the existence of a file, the File class provides the Exists method. Its syntax is:
public static bool Exists(string path);

If you provide only the name of the file, the compiler would check it in the folder of the
application. If you provide the path to the file, the compiler would check its drive, its
folder(s) and the file itself. In both cases, if the file exists, the method returns true. If
the compiler cannot find the file, the method returns false. It's important to know that if
you provided a complete path to the file, any slight mistake would produce a false
result.

Practical Learning: Checking the Existence of a File

1. Access the IceCream.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IceCream3
{
delegate void Request();

. . . No Change

// This method is used to display a receipt to the user


internal void DisplayReceipt()
{
. . . No Change
}

internal void SaveOrder()


{

C# 3.0 Practical Learning 832


Console.Write("Please enter your initials or the " +
"name we will use to remember your order: ");
var Filename = Console.ReadLine();

if( File.Exists(Filename) )
{
Console.WriteLine("The file you entered exists already.");
Console.Write("Do you want to replace it(y/n)?" );
var Answer = char.Parse(Console.ReadLine());

if( Answer == 'y' || Answer == 'Y' )


Console.WriteLine("The former order with the " +
"same name will be replaced");
else if( Answer == 'n' || Answer == 'N' )
{
Console.WriteLine("Please enter a name we will " +
"use to remember this order: ");
Filename = Console.ReadLine();
}
else
Console.WriteLine("Invalid Answer - We will close");

return;
}
else
Console.WriteLine("Great");
}

internal void OpenOrder()


{
Console.Write("Please enter the name you previously " +
"gave to remember your order: ");
var Filename = Console.ReadLine();

if (File.Exists(Filename))
Console.WriteLine("The file would have been opened");
else
Console.WriteLine("The name you entered is not registered
" +
"in our previous orders");
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;

namespace IceCream3
{
public class Program
{
static void Main(string[] args)
{
var ic = new IceCream();
var process = new Request(ic.ProcessAnOrder);

process();

C# 3.0 Practical Learning 833


Console.Write("Do you want us to remember this " +
"order the next time you come to " +
"get your Ice Cream (y/n)? ");
var answer = char.Parse(Console.ReadLine());

if (answer == 'y' || answer == 'Y')


ic.SaveOrder();
else
Console.WriteLine("\nIt was nice serving you." +
"\nCome Again!!!\n");
}
}
}

3. Save the file

4. Compile and execute it

File Creation

Besides checking the existence of the file, the File class can be used to create a new
file. To support this operation, the File class is equipped with the Create() method
that is overloaded with two versions as follows:
public static FileStream Create(string path);
public static FileStream Create(string path, int buffersize);

In both cases, the File.Create() method returns a Stream value, in this case a
FileStream value. As the File.Create() method indicates, it takes the name or path
of the file as argument. If you know or want to specify the size, in bytes, of the file, you
can use the second version.

To provide the same operation of creating a file, you can use the Open() method of the
File class. It is overloaded in three versions as follows:

public static FileStream Open(


string path,
FileMode mode
);
public static FileStream Open(
string path,
FileMode mode,
FileAccess access
);
public static FileStream Open(
string path,
FileMode mode,
FileAccess access,
FileShare share
);

Access to a File

In order to perform an operation on a file, you must specify to the operating system
how to proceed. One of the options you have is to indicate the type of access that will

C# 3.0 Practical Learning 834


be granted on the file. This access is specified using the FileAccess enumerator. The
members of the FileAccess enumerator are:

 FileAccess.Write: New data can be written to the file

 FileAccess.Read: Existing data can be read from the file

 FileAccess.ReadWrite: Existing data can be read from the file and new data be
written to the file

File Sharing

In standalone workstations, one person is usually able to access and open a file then
perform the necessary operations on it. In networked computers, you may create a file
that different people can access at the same time or you may make one file access
another file to retrieve information. For example, suppose you create an application for a
fast food restaurant that has two or more connected workstations and all workstations
save their customers orders to a common file. In this case, you must make sure that any
of the computers can access the file to save an order. An employee from one of these
workstations must also be able to open the file to retrieve a customer order for any
necessary reason. You can also create a situation where one file holds an inventory of
the items of a store and another file holds the customers orders. Obviously one file
would depend on another. Based on this, when an operation must be performed on a
file, you may have to specify how a file can be shared. This is done through the
FileShare enumerator.

The values of the FileShare enumerator are:

 FileShare.Inheritable: Allows other file handles to inherit from this file

 FileShare.None: The file cannot be shared

 FileShare.Read: The file can be opened and read from

 FileShare.Write: The file can be opened and written to

 FileShare.ReadWrite: The file can be opened to write to it or read from it

The Mode of a File

Besides the access to the file, another option you will most likely specify to the operating
system is referred to as the mode of a file. It is specified through the FileMode
enumerator. The members of the FileMode Enumerator are:

 FileMode.Append: If the file already exists, the new data will be added to its end.
If the file doesn't exist, it will be created and the new data will be added to it

 FileMode.Create: If the file already exists, it will be deleted and a new file with
the same name will be created. If the file doesn't exist, then it will be created

 FileMode.CreateNew: If the new already exists, the compiler will throw an error.
If the file doesn't exist, it will be created

C# 3.0 Practical Learning 835


 FileMode.Open: If the file exists, it will be opened. If the file doesn't exist, an
error would be thrown

 FileMode.OpenOrCreate: If the file already exists, it will be opened. If the file


doesn't exist, it will be created

 FileMode.Truncate: If the file already exists, its contents will be deleted


completely but the file will be kept, allowing you to write new data to it. If the file
doesn't exist, an error would be thrown

Fundamentals of File Streaming


 

Introduction

File streaming consists of performing one of the routine operations on a file, such as
creating it or opening it. This basic operation can be performed using a class called
FileStream. You can use a FileStream object to get a stream ready for processing. As
one of the most complete classes of file processing of the .NET Framework, FileStream
is equipped with all necessary properties and methods. To use it, you must first declare
a variable of it. The class is equipped with nine constructors.

One of the constructors (the second) of the FileStream class has the following syntax:
public FileStream(string path, FileMode mode);

This constructor takes as its first argument the name or the file or its path. The second
argument specifies the type of operation to perform on the file. Here is an example:
using System;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Persons.spr";

FileStream fstPersons = new FileStream(Filename, FileMode.Create);


return 0;
}
}

Practical Learning: Creating a Stream

1. To create a new stream, change the SaveOrder() method in the IceCream.cs file
and as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

C# 3.0 Practical Learning 836


namespace IceCream3
{
. . . No Change

internal void SaveOrder()


{
Console.Write("Please enter your initials or the " +
"name we will use to remember your order: ");
var Filename = Console.ReadLine();

if( File.Exists(Filename) )
{
Console.WriteLine("The file you entered exists
already.");
Console.Write("Do you want to replace it(y/n)?" );
var Answer = char.Parse(Console.ReadLine());

FileStream stmIceCream =
new FileStream(Filename, FileMode.Create);

if( Answer == 'y' || Answer == 'Y' )


Console.WriteLine("The former order with the " +
"same name will be replaced");
else if( Answer == 'n' || Answer == 'N' )
{
Console.WriteLine("Please enter a name we will " +
"use to remember this order: ");
Filename = Console.ReadLine();
}
else
Console.WriteLine("Invalid Answer - We will close");

return;
}
else
Console.WriteLine("Great");
}

internal void OpenOrder()


{
. . . No Change
}
}
}

2. Save the file

Stream Writing

A streaming operation is typically used to create a stream. Once the stream is ready,
you can write data to it. The writing operation is perform through various classes. One
of these classes is BinaryWriter.

The BinaryWriter class can be used to write values of primitive data types ( char, int,
float, double, etc). To use a BinaryWriter value, you can first declare its variable. To
do this, you would use one of the class' three constructors. One of its constructors (the
second) has the following syntax:

C# 3.0 Practical Learning 837


public BinaryWriter(Stream output);

This constructor takes as argument a Stream value, which could be a FileStream


variable. Here is an example:
using System;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Persons.spr";

FileStream fstPersons = new FileStream(Filename, FileMode.Create);


BinaryWriter wrtPersons = new BinaryWriter(fstPersons);

return 0;
}
}

If you are initializing a variable while you are creating it, remember that you can use the
var keyword.

Most classes that are used to add values to a stream are equipped with a method called
Write. This is also the case for the BinaryWriter class. This method takes as
argument the value that must be written to the stream. The method is overloaded so
that there is a version for each primitive data type. Here is an example that adds strings
to a newly created file:
using System;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Persons.spr";
var fstPersons = new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");

return 0;
}
}

Stream Closing

When you use a stream, it requests resources from the operating system and uses them
while the stream is available. When you are not using the stream anymore, you should
free the resources and make them available again to the operating system so that other
services can use them. This is done by closing the stream.

C# 3.0 Practical Learning 838


To close a stream, you can can call the Close() method of the class(es) you were using.
Here are examples:
using System;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Persons.spr";
var fstPersons = new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");

wrtPersons.Close();
fstPersons.Close();

return 0;
}
}

Practical Learning: Writing to a Stream

1. To be able to complete a file, change the SaveOrder() method in the IceCream.cs


file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IceCream3
{
. . . No Change

internal void SaveOrder()


{
Console.Write("Please enter your initials or the name " +
"we will use to remember your order: ");
var Filename = Console.ReadLine();
Filename = Filename + ".icr";

// Find out if the user entered a name of a file


// that is already in the machine
if (File.Exists(Filename))
{
var stmIceCream =
new FileStream(Filename, FileMode.Create);
var bnwIceCream =
new BinaryWriter(stmIceCream);

C# 3.0 Practical Learning 839


// If so, find out if the user wants to
// replace the old file
Console.WriteLine("The file you entered exists
already.");
Console.Write("Do you want to replace it(y/n)?");
char answer = char.Parse(Console.ReadLine());

// If the customer wants to replace it...


if (answer == 'y' || answer == 'Y')
{
// ... do so
Console.WriteLine("The former order with the same " +
"name will be replaced");

Console.WriteLine("\n=-= Ice Cream Vending Machine =-


=");
Console.WriteLine(" Saving Order: {0}", Filename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
// If the customer wants to save the new order with
// a different name
else if (answer == 'n' || answer == 'N')
{
// Ask the user to enter a name to remember the order
Console.Write("Please enter a name we will use " +
"to remember this order: ");
Filename = Console.ReadLine();
Filename = Filename + ".icr";

stmIceCream = new FileStream(Filename,


FileMode.Create);
bnwIceCream = new BinaryWriter(stmIceCream);

Console.WriteLine("\n=-= Ice Cream Vending Machine =-


=");
Console.WriteLine(" Saving Order: {0}", Filename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
else
Console.WriteLine("Invalid Answer - We will close");
bnwIceCream.Close();
stmIceCream.Close();
}
else
{
var stmIceCream =
new FileStream(Filename, FileMode.Create);
var bnwIceCream =
new BinaryWriter(stmIceCream);

Console.WriteLine("\n=-= Ice Cream Vending Machine =-=");


Console.WriteLine(" Saving Order: {0}", Filename);
C# 3.0 Practical Learning 840
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);

bnwIceCream.Close();
stmIceCream.Close();
}
}

public void OpenOrder()


{
. . . No Change
}
}
}

2. Execute the application and test it. Here is an example:


 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Vending Machine
-----------------------------------
What type of flavor do you want?
1 - Vanilla
2 - Cream of Cocoa
3 - Chocolate Chip
4 - Organic Strawberry
5 - Butter Pecan
6 - Cherry Coke
7 - Chocolate Brownies
8 - Caramel Au Lait
9 - Chunky Butter
10 - Chocolate Cookie
Your Choice? 8
-----------------------------------
What type of container do you want?
1 - Cone
2 - Cup
3 - Bowl
Your Choice? 2
-----------------------------------
Do you want an ingredient or not
1 - No Ingredient
2 - Peanuts
3 - M & M
4 - Cookies
Your Choice? 3
-----------------------------------
How many scoops(1, 2, or 3)? 2
-----------------------------------

=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Order
-----------------------------------
Flavor: Caramel Au Lait
Container: Cup
Ingredient: M & M
Scoops: 2
C# 3.0 Practical Learning 841
Total Price: $3.10
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Do you want us to remember this order the next time you


come to get your ice scream (y/n)? Y
Please enter your initials or the name we will use
to remember your order: LS

=-= Ice Cream Vending Machine =-=


Saving Order: LS.icr
Press any key to continue . . .

3. Close the DOS window

Stream Reading

As opposed to writing to a stream, you may want to read existing data from it. Before
doing this, you can first specify your intent to the streaming class using the FileMode
enumerator. This can be done using the FileStream class as follows:
using System;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Persons.spr";
/*
var fstPersons = new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");

wrtPersons.Close();
fstPersons.Close();
*/
var fstPersons = new FileStream(Filename, FileMode.Open);

return 0;
}
}

Once the stream is ready, you can get prepared to read data from it. To support this,
you can use the BinaryReader class. This class provides two constructors. One of the
constructors (the first) has the following syntax:
public BinaryReader(Stream input);

This constructor takes as argument a Stream value, which could be a FileStream


object. After declaring a FileStream variable using this constructor, you can read data
from it. To do this, you can call an appropriate method. This class provides an
appropriate method for each primitive data type.

C# 3.0 Practical Learning 842


After using the stream, you should close it to reclaim the resources it was using. This is
done by calling the Close() method.

Here is an example of using the mentioned methods:


using System;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var Filename = "Persons.spr";
/*
var fstPersons = new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");

wrtPersons.Close();
fstPersons.Close();
*/
var fstPersons = new FileStream(Filename, FileMode.Open);
var rdrPersons = new BinaryReader(fstPersons);
var strLine = "";

strLine = rdrPersons.ReadString();
Console.WriteLine(strLine);
strLine = rdrPersons.ReadString();
Console.WriteLine(strLine);
strLine = rdrPersons.ReadString();
Console.WriteLine(strLine);
strLine = rdrPersons.ReadString();
Console.WriteLine(strLine);

rdrPersons.Close();
fstPersons.Close();

return 0;
}
}

Practical Learning: Reading From a Stream

1. To be able to retrieve data from an existing file, change the IceCream.cs file as
follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IceCream3

C# 3.0 Practical Learning 843


{
delegate void Request();

// This class is used to create and manage an Ice Cream


// and to process an order
public sealed class IceCream
{
// This is the base price of an Ice Cream
// Optional values may be added to it
public const double BasePrice = 1.55D;

// These arrays are used to build the components


// of various Ice Creams
// In C#, we can allocate an array's memory in
// the body of the class
private string[] Flavor;
private string[] Container;
private string[] Ingredient;

// Additional factor used to process an Ice Cream order


private int Scoops;
private double TotalPrice;

// Variables that will hold the user's choice


// These are declared "globally" so they can be
// shared among methods
int ChoiceFlavor;
int ChoiceContainer;
int ChoiceIngredient;

// This default constructor is the best place for


// us to initialize the array
public IceCream()
{
Flavor = new string[10];
Flavor[0] = "Vanilla";
Flavor[1] = "Cream of Cocoa";
Flavor[2] = "Chocolate Chip";
Flavor[3] = "Organic Strawberry";
Flavor[4] = "Butter Pecan";
Flavor[5] = "Cherry Coke";
Flavor[6] = "Chocolate Brownies";
Flavor[7] = "Caramel Au Lait";
Flavor[8] = "Chunky Butter";
Flavor[9] = "Chocolate Cookie";

Ingredient = new string[4];


Ingredient[0] = "No Ingredient";
Ingredient[1] = "Peanuts";
Ingredient[2] = "M & M";
Ingredient[3] = "Cookies";

Container = new string[3];


Container[0] = "Cone";
Container[1] = "Cup";
Container[2] = "Bowl";
}

// This method requests a flavor from the user and


// returns the choice
C# 3.0 Practical Learning 844
internal void ChooseFlavor()
{
// Make sure the user selects a valid number
//that represents a flavor...
do
{
// In case the user types a symbol that
// is not a number
try
{
Console.WriteLine("What type of flavor do you
want?");
for (int i = 0; i < Flavor.Length; i++)
Console.WriteLine("{0} - {1}", i + 1, Flavor[i]);
Console.Write("Your Choice? ");
ChoiceFlavor = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine(@"You must enter a valid number
and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length)
Console.WriteLine("Invalid Choice - Try Again!\n");
} while (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length);
}

// This method allows the user to select a container


internal void ChooseContainer()
{
// Make sure the user selects a valid number that
// represents a container
do
{
// If the user types a symbol that is not a number
try
{
Console.WriteLine("What type of container do you
want?");
for (int i = 0; i < Container.Length; i++)
Console.WriteLine("{0} - {1}", i + 1,
Container[i]);
Console.Write("Your Choice? ");
ChoiceContainer = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine(@"You must enter a valid
number and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
C# 3.0 Practical Learning 845
if ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length));
}

internal void ChooseIngredient()


{
do
{
try
{
Console.WriteLine("Do you want an ingredient or
not");
for (int i = 0; i < Ingredient.Length; i++)
Console.WriteLine("{0} - {1}",
i + 1,
Ingredient[i]);
Console.Write("Your Choice? ");
ChoiceIngredient = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine(@"You must enter a valid
number and no other character!");
}

if ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length));
}

internal void SpecifyNumberOfScoops()


{
do
{
try
{
Console.Write("How many scoops(1, 2, or 3)? ");
Scoops = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

if (Scoops < 1 || Scoops > 3)


Console.WriteLine("Invalid Choice - Try Again!");
} while (Scoops < 1 || Scoops > 3);
}

// This method is used to process a customer order


// It uses the values of the above methods
internal void ProcessAnOrder()
{
var PriceIngredient = 0.00D;
C# 3.0 Practical Learning 846
var PriceScoop = 0.00D;

// Let the user know that this is a vending machine


Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Vending Machine");
Console.WriteLine("-----------------------------------");

// Let the user select the components of the Ice Cream


Request Get = new Request(ChooseFlavor);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseContainer);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseIngredient);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(SpecifyNumberOfScoops);
Get();
Console.WriteLine("-----------------------------------");

// If the user selects an ingredient instead of "No


Ingredient",
// add $0.50 to the order
if ((ChoiceIngredient == 2) ||
(ChoiceIngredient == 3) ||
(ChoiceIngredient == 4))
PriceIngredient = 0.50D;
else
PriceIngredient = 0.00D;

// Instead of multiplying a number scoops to a value,


// We will use an incremental value depending on
// the number of scoops
if (Scoops == 1)
PriceScoop = 0.65D;
else if (Scoops == 2)
PriceScoop = 1.05D;
else
PriceScoop = 1.55D;

// Calculate the total price of the Ice Cream


TotalPrice = BasePrice + PriceScoop + PriceIngredient;

// Create the Ice Cream...

// And display a receipt to the user


DisplayReceipt();
}

// This method is used to display a receipt to the user


internal void DisplayReceipt()
{
Console.WriteLine("\n=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Order");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Flavor: {0}",
Flavor[ChoiceFlavor - 1]);
Console.WriteLine("Container: {0}",
Container[ChoiceContainer - 1]);
C# 3.0 Practical Learning 847
Console.WriteLine("Ingredient: {0}",
Ingredient[ChoiceIngredient - 1]);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}", TotalPrice);
Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
}

internal void SaveOrder()


{
Console.Write("Please enter your initials or the name " +
"we will use to remember your order: ");
var Filename = Console.ReadLine();
Filename = Filename + ".icr";

// Find out if the user entered a name of a file


// that is already in the machine
if (File.Exists(Filename))
{
FileStream stmIceCream =
new FileStream(Filename, FileMode.Create);
BinaryWriter bnwIceCream =
new BinaryWriter(stmIceCream);

// If so, find out if the user wants to


// replace the old file
Console.WriteLine("The file you entered exists
already.");
Console.Write("Do you want to replace it(y/n)?");
char answer = char.Parse(Console.ReadLine());

// If the customer wants to replace it...


if (answer == 'y' || answer == 'Y')
{
// ... do so
Console.WriteLine("The former order with the same " +
"name will be replaced");

Console.WriteLine("\n=-= Ice Cream Vending Machine =-


=");
Console.WriteLine(" Saving Order: {0}", Filename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
// If the customer wants to save the new order with
// a different name
else if (answer == 'n' || answer == 'N')
{
// Ask the user to enter a name to remember the order
Console.Write("Please enter a name we will use " +
"to remember this order: ");
Filename = Console.ReadLine();
Filename = Filename + ".icr";

stmIceCream = new FileStream(Filename,


FileMode.Create);
bnwIceCream = new BinaryWriter(stmIceCream);

C# 3.0 Practical Learning 848


Console.WriteLine("\n=-= Ice Cream Vending Machine =-
=");
Console.WriteLine(" Saving Order: {0}", Filename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
else
Console.WriteLine("Invalid Answer - We will close");
bnwIceCream.Close();
stmIceCream.Close();
}
else
{
var stmIceCream =
new FileStream(Filename, FileMode.Create);
var bnwIceCream =
new BinaryWriter(stmIceCream);

Console.WriteLine("\n=-= Ice Cream Vending Machine =-=");


Console.WriteLine(" Saving Order: {0}", Filename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);

bnwIceCream.Close();
stmIceCream.Close();
}
}

public void OpenOrder()


{
// Ask the user to enter a name of a previously saved order
Console.Write("Please enter the name you previously " +
"gave to remember your order: ");
var Filename = Console.ReadLine();
Filename = Filename + ".icr";

var stmIceCream =
new FileStream(Filename, FileMode.Open);
var bnrIceCream =
new BinaryReader(stmIceCream);

// Find out if this order was previously saved in the machine


if (File.Exists(Filename))
{
// If so, open it
var SelectedFlavor = bnrIceCream.ReadString();
var SelectedContainer = bnrIceCream.ReadString();
var SelectedIngredient = bnrIceCream.ReadString();
Scoops = bnrIceCream.ReadInt32();
TotalPrice = bnrIceCream.ReadDouble();

// And display it to the user


Console.WriteLine("\n=-= Ice Cream Vending Machine =-=");
Console.WriteLine(" Previous Order: {0}", Filename);
C# 3.0 Practical Learning 849
Console.WriteLine("Flavor: {0}", SelectedFlavor);
Console.WriteLine("Container: {0}", SelectedContainer);
Console.WriteLine("Ingredient: {0}",
SelectedIngredient);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}\n", TotalPrice);

bnrIceCream.Close();
stmIceCream.Close();
}
else
Console.WriteLine("The name you entered is not " +
"registered in our previous orders");
}
}
}

2. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IceCream3
{
public class Program
{
static void Main(string[] args)
{
var ic = new IceCream();
var process = new Request(ic.ProcessAnOrder);

Console.Write("Do you want to re-order a previously " +


"saved order(y/n)? ");
var answer = char.Parse(Console.ReadLine());

if (answer == 'y' || answer == 'Y')


ic.OpenOrder();
else
{
process();
Console.Write("Do you want us to remember this " +
"order the next time you come to " +
"get your Ice Cream (y/n)? ");
answer = char.Parse(Console.ReadLine());
if (answer == 'y' || answer == 'Y')
ic.SaveOrder();
else
Console.WriteLine("\nIt was nice serving you." +
"\nCome Again!!!\n");
}
}
}
}

3. Execute the application and test it. Here is an example:


 

C# 3.0 Practical Learning 850


Do you want to re-order a previously saved order(y/n)? Y
Please enter the name you previously gave to remember your order: LS

=-= Ice Cream Vending Machine =-=


Previous Order: LS.icr
Flavor: Caramel Au Lait
Container: Cup
Ingredient: M & M
Scoops: 2
Total Price: $3.10

Press any key to continue . . .

4. Close the DOS window

5. Execute the application again and test it. Here is an example:


 
Do you want to re-order a previously saved order(y/n)? w
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Vending Machine
-----------------------------------
What type of flavor do you want?
1 - Vanilla
2 - Cream of Cocoa
3 - Chocolate Chip
4 - Organic Strawberry
5 - Butter Pecan
6 - Cherry Coke
7 - Chocolate Brownies
8 - Caramel Au Lait
9 - Chunky Butter
10 - Chocolate Cookie
Your Choice? 5
-----------------------------------
What type of container do you want?
1 - Cone
2 - Cup
3 - Bowl
Your Choice? 2
-----------------------------------
Do you want an ingredient or not
1 - No Ingredient
2 - Peanuts
3 - M & M
4 - Cookies
Your Choice? 1
-----------------------------------
How many scoops(1, 2, or 3)? 1
-----------------------------------

=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Order
-----------------------------------
Flavor: Butter Pecan
Container: Cup
Ingredient: No Ingredient
Scoops: 1
Total Price: $2.20
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
C# 3.0 Practical Learning 851
Do you want us to remember this order the next time
you come to get your Ice Cream (y/n)? y
Please enter your initials or the name we will use
to remember your order: DIC

=-= Ice Cream Vending Machine =-=


Saving Order: DIC.icr
Press any key to continue . . .

6. Close the DOS window

7. Execute the application again and test it. Here is an example:


 
Do you want to re-order a previously saved order(y/n)? n
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Vending Machine
-----------------------------------
What type of flavor do you want?
1 - Vanilla
2 - Cream of Cocoa
3 - Chocolate Chip
4 - Organic Strawberry
5 - Butter Pecan
6 - Cherry Coke
7 - Chocolate Brownies
8 - Caramel Au Lait
9 - Chunky Butter
10 - Chocolate Cookie
Your Choice? 9
-----------------------------------
What type of container do you want?
1 - Cone
2 - Cup
3 - Bowl
Your Choice? 3
-----------------------------------
Do you want an ingredient or not
1 - No Ingredient
2 - Peanuts
3 - M & M
4 - Cookies
Your Choice? 4
-----------------------------------
How many scoops(1, 2, or 3)? 3
-----------------------------------

=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Order
-----------------------------------
Flavor: Chunky Butter
Container: Bowl
Ingredient: Cookies
Scoops: 3
Total Price: $3.60
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Do you want us to remember this order the next time


you come to get your Ice Cream (y/n)? Y
C# 3.0 Practical Learning 852
Please enter your initials or the name we will use
to remember your order: LS
The file you entered exists already.
Do you want to replace it(y/n)?Y
The former order with the same name will be replaced

=-= Ice Cream Vending Machine =-=


Saving Order: LS.icr
Press any key to continue . . .

8. Close the DOS window

C# 3.0 Practical Learning 853


Details on File Processing
 

Exception Handling in File Processing


 

Finally

So far, to handle exceptions, we were using the try, catch, and throw keywords.
These allowed us to perform normal assignments in a try section and then handle an
exception, if any, in a catch block.

In the previous lesson, we mentioned that, when you create a stream, the operating
system must allocate resources and dedicate them to the file processing operations.
Additional resources may be provided for the object that is in charge of writing to, or
reading from, the stream. We also saw that, when the streaming was over, we should
free the resources and give them back to the operating system. To do this, we called
the Close() method of the variable that was using resources.

More than any other assignment, file processing is in prime need of exception handling.
As we will see in the next section, during file processing, there are many things that can
go wrong. For this reason, the creation and/or management of streams should be
performed in a try block to get ready to handle exceptions that would occur. Besides
actually handling exceptions, the C# language provides a special keyword used free
resources. This keyword is finally.

The finally keyword is used to create a section of an exception. Like catch, a finally block
cannot exist by itself. It can be created following a try section. The formula used would
be:
try
{
}
finally
{
}

Based on this, the finally section has a body of its own, delimited by its curly
brackets. Like catch, the finally section is created after the try section. Unlike catch,
finally never has parentheses and never takes arguments. Unlike catch, the finally
section is always executed. Because the finally clause always gets executed, you can
include any type of code in it but it is usually appropriate to free the resources that were
allocated earlier. Here is an example:
using System;
using System.IO;
C# 3.0 Practical Learning 854
public class Program
{
static int Main(string[] args)
{
var Filename = "Members.clb";
var fstPersons = new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

try
{
wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");
}
finally
{
wrtPersons.Close();
fstPersons.Close();
}

return 0;
}
}

In the same way, you can use a finally section to free resources used when reading from
a stream:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
/* var Filename = "Members.clb";
var fstPersons = new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

try
{
wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");
}
finally
{
wrtPersons.Close();
fstPersons.Close();
}*/

var strLine = "";


var Filename = "Members.clb";
var fstMembers = new FileStream(Filename, FileMode.Open);
var rdrMembers = new BinaryReader(fstMembers);

try
{
C# 3.0 Practical Learning 855
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
}
finally
{
rdrMembers.Close();
fstMembers.Close();
}

return 0;
}
}

Of course, since the whole block of code starts with a try section, it is used for
exception handling. This means that you can add the necessary and appropriate catch
section(s) but you don't have to.

Practical Learning: Finally Releasing Resources

1. Start Microsoft Visual C# and create a Console Application named IceCream4

2. To save the project, on the Standard toolbar, click the Save All button

3. Change the Solution Name to VendingMachine4

4. Accept the Name of the project as IceCream3 and click Save

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to IceCream and click Add

7. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IceCream4
{
delegate void Request();

// This class is used to create and manage an Ice Cream


// and to process an order
public sealed class IceCream
{
// This is the base price of an Ice Cream
// Optional values may be added to it
public const decimal BasePrice = 1.55M;

C# 3.0 Practical Learning 856


// These arrays are used to build the components
// of various ice creams
private string[] Flavor;
private string[] Container;
private string[] Ingredient;

// Additional factor used to process an Ice Cream order


private int Scoops;
private decimal TotalPrice;

// Variables that will hold the user's choice


// These are declared "globally" so they can be
// shared among methods
int ChoiceFlavor;
int ChoiceContainer;
int ChoiceIngredient;

// This default constructor is the best place for


// us to initialize the array
public IceCream()
{
Flavor = new string[10];
Flavor[0] = "Vanilla";
Flavor[1] = "Cream of Cocoa";
Flavor[2] = "Chocolate Chip";
Flavor[3] = "Organic Strawberry";
Flavor[4] = "Butter Pecan";
Flavor[5] = "Cherry Coke";
Flavor[6] = "Chocolate Brownies";
Flavor[7] = "Caramel Au Lait";
Flavor[8] = "Chunky Butter";
Flavor[9] = "Chocolate Cookie";

Ingredient = new string[4];


Ingredient[0] = "No Ingredient";
Ingredient[1] = "Peanuts";
Ingredient[2] = "M & M";
Ingredient[3] = "Cookies";

Container = new string[3];


Container[0] = "Cone";
Container[1] = "Cup";
Container[2] = "Bowl";
}

// This method requests a flavor from the user and


// returns the choice
internal void ChooseFlavor()
{
// Make sure the user selects a valid number
//that represents a flavor...
do
{
// In case the user types a symbol that
// is not a number
try
{
Console.WriteLine("What type of flavor do you
want?");
for (int i = 0; i < Flavor.Length; i++)
C# 3.0 Practical Learning 857
Console.WriteLine("{0} - {1}", i + 1, Flavor[i]);
Console.Write("Your Choice? ");
ChoiceFlavor = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length)
Console.WriteLine("Invalid Choice - Try Again!\n");
} while (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length);
}

// This method allows the user to select a container


internal void ChooseContainer()
{
// Make sure the user selects a valid number that
// represents a container
do
{
// If the user types a symbol that is not a number
try
{
Console.WriteLine("What type of container do you
want?");
for (int i = 0; i < Container.Length; i++)
Console.WriteLine("{0} - {1}", i + 1,
Container[i]);
Console.Write("Your Choice? ");
ChoiceContainer = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine("You must enter a valid " +
"number and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length));
}

internal void ChooseIngredient()


{
do
{
try
{
C# 3.0 Practical Learning 858
Console.WriteLine("Do you want an ingredient or
not");
for (int i = 0; i < Ingredient.Length; i++)
Console.WriteLine("{0} - {1}",
i + 1,
Ingredient[i]);
Console.Write("Your Choice? ");
ChoiceIngredient = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid " +
"number and no other character!");
}

if ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length));
}

internal void SpecifyNumberOfScoops()


{
do
{
try
{
Console.Write("How many scoops(1, 2, or 3)? ");
Scoops = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

if (Scoops < 1 || Scoops > 3)


Console.WriteLine("Invalid Choice - Try Again!");
} while (Scoops < 1 || Scoops > 3);
}

// This method is used to process a customer order


// It uses the values of the above methods
internal void ProcessAnOrder()
{
// int ChoiceFlavor;
// int ChoiceContainer;
// int ChoiceIngredient;
decimal PriceIngredient, PriceScoop;

// Let the user know that this is a vending machine


Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Vending Machine");
Console.WriteLine("-----------------------------------");

// Let the user select the components of the Ice Cream


Request Get = new Request(ChooseFlavor);
Get();
Console.WriteLine("-----------------------------------");
C# 3.0 Practical Learning 859
Get = new Request(ChooseContainer);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseIngredient);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(SpecifyNumberOfScoops);
Get();
Console.WriteLine("-----------------------------------");

// If the user selects an ingredient instead of "No


Ingredient",
// add $0.50 to the order
if ((ChoiceIngredient == 2) ||
(ChoiceIngredient == 3) ||
(ChoiceIngredient == 4))
PriceIngredient = 0.50M;
else
PriceIngredient = 0.00M;

// Instead of multiplying a number scoops to a value,


// We will use an incremental value depending on
// the number of scoops
if (Scoops == 1)
PriceScoop = 0.65M;
else if (Scoops == 2)
PriceScoop = 1.05M;
else
PriceScoop = 1.55M;

// Calculate the total price of the Ice Cream


TotalPrice = BasePrice + PriceScoop + PriceIngredient;

// Create the Ice Cream...

// And display a receipt to the user


DisplayReceipt();
}

// This method is used to display a receipt to the user


internal void DisplayReceipt()
{
Console.WriteLine("\n=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Order");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Flavor: {0}",
Flavor[ChoiceFlavor - 1]);
Console.WriteLine("Container: {0}",
Container[ChoiceContainer - 1]);
Console.WriteLine("Ingredient: {0}",
Ingredient[ChoiceIngredient - 1]);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}", TotalPrice);
Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
}

internal void SaveOrder()


{
string strFilename;

C# 3.0 Practical Learning 860


Console.Write("Please enter your initials or the name " +
"we will use to remember your order: ");
strFilename = Console.ReadLine();
strFilename = strFilename + ".icr";

// Find out if the user entered a name of a file


// that is already in the machine
if (File.Exists(strFilename))
{
char answer;

FileStream stmIceCream =
new FileStream(strFilename, FileMode.Create);
BinaryWriter bnwIceCream =
new BinaryWriter(stmIceCream);

try
{

// If so, find out if the user wants to


// replace the old file
Console.WriteLine("The file you entered exists
already.");
Console.Write("Do you want to replace it(y/n)?");
answer = char.Parse(Console.ReadLine());

// If the customer wants to replace it...


if (answer == 'y' || answer == 'Y')
{
// ... do so
Console.WriteLine("The former order with the same
" +
"name will be replaced");

Console.WriteLine("\n=-= Ice Cream Vending


Machine =-=");
Console.WriteLine(" Saving Order: {0}",
strFilename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer -
1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient -
1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
// If the customer wants to save the new order with
// a different name
else if (answer == 'n' || answer == 'N')
{
// Ask the user to enter a name to remember the
order
Console.Write("Please enter a name we will use "
+
"to remember this order: ");
strFilename = Console.ReadLine();
strFilename = strFilename + ".icr";

stmIceCream =
new FileStream(strFilename, FileMode.Create);
C# 3.0 Practical Learning 861
bnwIceCream = new BinaryWriter(stmIceCream);

Console.WriteLine("\n=-= Ice Cream Vending


Machine =-=");
Console.WriteLine(" Saving Order: {0}",
strFilename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer -
1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient -
1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
else
Console.WriteLine("Invalid Answer - We will
close");
}
finally
{
bnwIceCream.Close();
stmIceCream.Close();
}
}
else
{
FileStream stmIceCream =
new FileStream(strFilename, FileMode.Create);
BinaryWriter bnwIceCream =
new BinaryWriter(stmIceCream);

try
{
Console.WriteLine("\n=-= Ice Cream Vending Machine =-
=");
Console.WriteLine(" Saving Order: {0}", strFilename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer - 1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient - 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
finally
{
bnwIceCream.Close();
stmIceCream.Close();
}
}
}

internal void OpenOrder()


{
string strFilename;

string SelectedFlavor;
string SelectedContainer;
string SelectedIngredient;

// Ask the user to enter a name of a previously saved order


Console.Write("Please enter the name you previously " +
C# 3.0 Practical Learning 862
"gave to remember your order: ");
strFilename = Console.ReadLine();
strFilename = strFilename + ".icr";

FileStream stmIceCream =
new FileStream(strFilename, FileMode.Open);
BinaryReader bnrIceCream =
new BinaryReader(stmIceCream);

try
{
// Find out if this order was previously saved in the
machine
if (File.Exists(strFilename))
{
// If so, open it
SelectedFlavor = bnrIceCream.ReadString();
SelectedContainer = bnrIceCream.ReadString();
SelectedIngredient = bnrIceCream.ReadString();
Scoops = bnrIceCream.ReadInt32();
TotalPrice = bnrIceCream.ReadDecimal();

// And display it to the user


Console.WriteLine("\n=-= Ice Cream Vending Machine =-
=");
Console.WriteLine(" Previous Order: {0}",
strFilename);
Console.WriteLine("Flavor: {0}",
SelectedFlavor);
Console.WriteLine("Container: {0}",
SelectedContainer);
Console.WriteLine("Ingredient: {0}",
SelectedIngredient);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}\n",
TotalPrice);
}
else
Console.WriteLine("The name you entered is not " +
"registered in our previous
orders");
}
finally
{
bnrIceCream.Close();
stmIceCream.Close();
}
}
}
}

8.  Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IceCream4
C# 3.0 Practical Learning 863
{
public class Program
{
static void Main(string[] args)
{
var answer = 'n';
var ic = new IceCream();
var process = new Request(ic.ProcessAnOrder);

Console.Write("Do you want to re-order a previously " +


"saved order(y/n)? ");
answer = char.Parse(Console.ReadLine());

if (answer == 'y' || answer == 'Y')


ic.OpenOrder();
else
{
process();
Console.Write("Do you want us to remember this " +
"order the next time you come to " +
"get your Ice Cream (y/n)? ");
answer = char.Parse(Console.ReadLine());
if (answer == 'y' || answer == 'Y')
ic.SaveOrder();
else
Console.WriteLine("\nIt was nice serving you." +
"\nCome Again!!!\n");
}
}
}
}

9. Execute the application and test it. Here is an example:


 
Do you want to re-order a previously saved order(y/n)? n
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Vending Machine
-----------------------------------
What type of flavor do you want?
1 - Vanilla
2 - Cream of Cocoa
3 - Chocolate Chip
4 - Organic Strawberry
5 - Butter Pecan
6 - Cherry Coke
7 - Chocolate Brownies
8 - Caramel Au Lait
9 - Chunky Butter
10 - Chocolate Cookie
Your Choice? 6
-----------------------------------
What type of container do you want?
1 - Cone
2 - Cup
3 - Bowl
Your Choice? 2
-----------------------------------
Do you want an ingredient or not
1 - No Ingredient
C# 3.0 Practical Learning 864
2 - Peanuts
3 - M & M
4 - Cookies
Your Choice? 1
-----------------------------------
How many scoops(1, 2, or 3)? 2
-----------------------------------

=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
Ice Cream Order
-----------------------------------
Flavor: Cherry Coke
Container: Cup
Ingredient: No Ingredient
Scoops: 2
Total Price: $2.60
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

Do you want us to remember this order the next time you


come to get your Ice Cream (y/n)? n

It was nice serving you.


Come Again!!!

Press any key to continue . . .

10.Close the DOS window

11.Execute the application and test it. Indicate that you want to open an existing file

12.Enter a wrong file name such as Q4 and press Enter


 

 
Click Don't Send. Here is an example:
 
Do you want to re-order a previously saved order(y/n)? y
Please enter the name you previously gave to remember your order: Q4

C# 3.0 Practical Learning 865


Unhandled Exception: System.IO.FileNotFoundException: Could not find file
'C:\Do
cuments and Settings\Administrator\My Documents\Visual Studio
2008\Projects\Vend
ingMachine4\IceCream4\bin\Release\Q4.icr'.
File name: 'C:\Documents and Settings\Administrator\My Documents\Visual
Studio 2
008\Projects\VendingMachine4\IceCream4\bin\Release\Q4.icr'
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess
access, I
nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize,
FileOptions o
ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode)
at IceCream4.IceCream.OpenOrder() in C:\Documents and
Settings\Administrator\
My Documents\Visual Studio
2008\Projects\VendingMachine4\IceCream4\IceCream.cs:l
ine 362
at IceCream4.Program.Main(String[] args) in C:\Documents and
Settings\Adminis
trator\My Documents\Visual Studio
2008\Projects\VendingMachine4\IceCream4\Progra
m.cs:line 21
Press any key to continue . . .

13.Close the DOS window

.NET Framework Exception Handling for File Processing

In the previous lesson as our introduction to file processing, we behaved as if everything


was alright. Unfortunately, file processing can be very strict in its assignments. Based on
this, the .NET Framework provides various Exception-oriented classes to deal with
almost any type of exception you can think of.

One of the most important aspects of file processing is the name of the file that will be
dealt with. In some cases you can provide this name to the application or document. In
some other cases, you would let the user specify the name of the path. Regardless of
how the name of the file would be provided to the operating system, when this name is
acted upon, the compiler is asked to work on the file. If the file doesn't exist, the
operation cannot be carried. Furthermore, the compiler would throw an error. There are
many other exceptions that can be thrown as a result of something going bad during file
processing:

FileNotFoundException: The exception thrown when a file has not been found is of
type FileNotFoundException. Here is an example of handling it:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
/* var Filename = "Members.clb";
var fstPersons =
C# 3.0 Practical Learning 866
new FileStream(Filename, FileMode.Create);
var wrtPersons = new BinaryWriter(fstPersons);

try
{
wrtPersons.Write("James Bloch");
wrtPersons.Write("Catherina Wallace");
wrtPersons.Write("Bruce Lamont");
wrtPersons.Write("Douglas Truth");
}
finally
{
wrtPersons.Close();
fstPersons.Close();
}*/

var strLine = "";


var Filename = "Members.clc";

try
{
var fstMembers =
new FileStream(Filename, FileMode.Open);
var rdrMembers = new BinaryReader(fstMembers);

try
{
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
strLine = rdrMembers.ReadString();
Console.WriteLine(strLine);
}
finally
{
rdrMembers.Close();
fstMembers.Close();
}
}
catch (FileNotFoundException ex)
{
Console.Write("Error: " + ex.Message);
Console.WriteLine(" May be the file doesn't exist " +
"or you typed it wrong!");
}

return 0;
}
}

Here is an example of what this would produce:


Error: Could not find file 'C:\Documents and Settings\Administrator\Local
Settings\Application Data\Temporary
Projects\ConsoleApplication1\bin\Release\Members.clc'.
May be the file doesn't exist or you typed it wrong!
C# 3.0 Practical Learning 867
Press any key to continue . . .

IOException: As mentioned already, during file processing, anything could go wrong. If


you don't know what caused an error, you can throw the IOException exception.

Practical Learning: Handling File Processing Exceptions

1. To throw exceptions, change the file processing methods from the IceCream.cs file
as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IceCream4
{
delegate void Request();

// This class is used to create and manage an Ice Cream


// and to process an order
public sealed class IceCream
{
// This is the base price of an Ice Cream
// Optional values may be added to it
public const decimal BasePrice = 1.55M;

// These arrays are used to build the components


// of various Ice Creams
// In C#, we can allocate an array's memory in
// the body of the class
private string[] Flavor;
private string[] Container;
private string[] Ingredient;

// Additional factor used to process an Ice Cream order


private int Scoops;
private decimal TotalPrice;

// Variables that will hold the user's choice


// These are declared "globally" so they can be
// shared among methods
int ChoiceFlavor;
int ChoiceContainer;
int ChoiceIngredient;

// This default constructor is the best place for


// us to initialize the array
public IceCream()
{
Flavor = new string[10];
Flavor[0] = "Vanilla";
Flavor[1] = "Cream of Cocoa";
Flavor[2] = "Chocolate Chip";
Flavor[3] = "Organic Strawberry";
Flavor[4] = "Butter Pecan";

C# 3.0 Practical Learning 868


Flavor[5] = "Cherry Coke";
Flavor[6] = "Chocolate Brownies";
Flavor[7] = "Caramel Au Lait";
Flavor[8] = "Chunky Butter";
Flavor[9] = "Chocolate Cookie";

Ingredient = new string[4];


Ingredient[0] = "No Ingredient";
Ingredient[1] = "Peanuts";
Ingredient[2] = "M & M";
Ingredient[3] = "Cookies";

Container = new string[3];


Container[0] = "Cone";
Container[1] = "Cup";
Container[2] = "Bowl";
}

// This method requests a flavor from the user and


// returns the choice
internal void ChooseFlavor()
{
// Make sure the user selects a valid number
//that represents a flavor...
do
{
// In case the user types a symbol that
// is not a number
try
{
Console.WriteLine("What type of flavor do you
want?");
for (int i = 0; i < Flavor.Length; i++)
Console.WriteLine("{0} - {1}", i + 1, Flavor[i]);
Console.Write("Your Choice? ");
ChoiceFlavor = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length)
Console.WriteLine("Invalid Choice - Try Again!\n");
} while (ChoiceFlavor < 1 || ChoiceFlavor > Flavor.Length);
}

// This method allows the user to select a container


internal void ChooseContainer()
{
// Make sure the user selects a valid number that
// represents a container
do
{
// If the user types a symbol that is not a number
C# 3.0 Practical Learning 869
try
{
Console.WriteLine("What type of container do you
want?");
for (int i = 0; i < Container.Length; i++)
Console.WriteLine("{0} - {1}", i + 1,
Container[i]);
Console.Write("Your Choice? ");
ChoiceContainer = int.Parse(Console.ReadLine());
}
catch (FormatException) // display an appropriate
message
{
Console.WriteLine("You must enter a valid " +
"number and no other character!");
}

// If the user typed an invalid number out of the


// allowed range
// let him or her know and provide another chance
if ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceContainer < 1) ||
(ChoiceContainer > Container.Length));
}

internal void ChooseIngredient()


{
do
{
try
{
Console.WriteLine("Do you want an ingredient or
not");
for (int i = 0; i < Ingredient.Length; i++)
Console.WriteLine("{0} - {1}",
i + 1,
Ingredient[i]);
Console.Write("Your Choice? ");
ChoiceIngredient = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid " +
"number and no other character!");
}

if ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length))
Console.WriteLine("Invalid Choice - Try Again!");
} while ((ChoiceIngredient < 1) ||
(ChoiceIngredient > Ingredient.Length));
}

internal void SpecifyNumberOfScoops()


{
do
{
try
C# 3.0 Practical Learning 870
{
Console.Write("How many scoops(1, 2, or 3)? ");
Scoops = int.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You must enter a valid number " +
"and no other character!");
}

if (Scoops < 1 || Scoops > 3)


Console.WriteLine("Invalid Choice - Try Again!");
} while (Scoops < 1 || Scoops > 3);
}

// This method is used to process a customer order


// It uses the values of the above methods
public void ProcessAnOrder()
{
// int ChoiceFlavor;
// int ChoiceContainer;
// int ChoiceIngredient;
decimal PriceIngredient, PriceScoop;

// Let the user know that this is a vending machine


Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Vending Machine");
Console.WriteLine("-----------------------------------");

// Let the user select the components of the Ice Cream


Request Get = new Request(ChooseFlavor);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseContainer);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(ChooseIngredient);
Get();
Console.WriteLine("-----------------------------------");
Get = new Request(SpecifyNumberOfScoops);
Get();
Console.WriteLine("-----------------------------------");

// If the user selects an ingredient instead of "No


Ingredient",
// add $0.50 to the order
if ((ChoiceIngredient == 2) ||
(ChoiceIngredient == 3) ||
(ChoiceIngredient == 4))
PriceIngredient = 0.50M;
else
PriceIngredient = 0.00M;

// Instead of multiplying a number scoops to a value,


// We will use an incremental value depending on
// the number of scoops
if (Scoops == 1)
PriceScoop = 0.65M;
else if (Scoops == 2)
PriceScoop = 1.05M;
C# 3.0 Practical Learning 871
else
PriceScoop = 1.55M;

// Calculate the total price of the Ice Cream


TotalPrice = BasePrice + PriceScoop + PriceIngredient;

// Create the Ice Cream...

// And display a receipt to the user


DisplayReceipt();
}

// This method is used to display a receipt to the user


internal void DisplayReceipt()
{
Console.WriteLine("\n=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=");
Console.WriteLine("Ice Cream Order");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Flavor: {0}",
Flavor[ChoiceFlavor - 1]);
Console.WriteLine("Container: {0}",
Container[ChoiceContainer - 1]);
Console.WriteLine("Ingredient: {0}",
Ingredient[ChoiceIngredient - 1]);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}", TotalPrice);
Console.WriteLine("=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
}

internal void SaveOrder()


{
string strFilename;

Console.Write("Please enter your initials or the name " +


"we will use to remember your order: ");
strFilename = Console.ReadLine();
strFilename = strFilename + ".icr";

try
{
// Find out if the user entered a name of a file
// that is already in the machine
if (File.Exists(strFilename))
{
char answer;

FileStream stmIceCream =
new FileStream(strFilename, FileMode.Create);
BinaryWriter bnwIceCream =
new BinaryWriter(stmIceCream);

try
{

// If so, find out if the user wants to


// replace the old file
Console.WriteLine("The file you entered exists
already.");
Console.Write("Do you want to replace it(y/n)?");
answer = char.Parse(Console.ReadLine());
C# 3.0 Practical Learning 872
// If the customer wants to replace it...
if (answer == 'y' || answer == 'Y')
{
// ... do so
Console.WriteLine("The former order with the
same " +
"name will be replaced");

Console.WriteLine("\n=-= Ice Cream " +


"Vending Machine =-=");
Console.WriteLine(" Saving Order: {0}",
strFilename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer -
1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient
- 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
// If the customer wants to save the new order
with
// a different name
else if (answer == 'n' || answer == 'N')
{
// Ask the user to enter a name to remember
the order
Console.Write("Please enter a name we will
use " +
"to remember this order: ");
strFilename = Console.ReadLine();
strFilename = strFilename + ".icr";

try
{
stmIceCream = new FileStream(strFilename,
FileMode.Create);
bnwIceCream = new
BinaryWriter(stmIceCream);

Console.WriteLine("\n=-= Ice Cream " +


"Vending Machine =-=");
Console.WriteLine(" Saving Order: {0}",
strFilename);
bnwIceCream.Write(Flavor[ChoiceFlavor -
1]);
bnwIceCream.Write(Container[ChoiceContainer -
1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient
- 1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
catch (IOException)
{
Console.Write("\nThe file you wanted us
to " +
"create exists already. ");

C# 3.0 Practical Learning 873


Console.WriteLine("In case it was
registered " +
"by a different customer, " +
"we will not delete it.");
}
}
else
Console.WriteLine("Invalid Answer - We will
close");
}
catch (IOException)
{
Console.Write("\nThat file exists already. ");
Console.WriteLine("We need to preserve it just in
" +
"case another customer will require
it.");
}
finally
{
bnwIceCream.Close();
stmIceCream.Close();
}
}
else
{
FileStream stmIceCream =
new FileStream(strFilename, FileMode.Create);
BinaryWriter bnwIceCream =
new BinaryWriter(stmIceCream);

try
{
Console.WriteLine("\n=-= Ice Cream Vending
Machine =-=");
Console.WriteLine(" Saving Order: {0}",
strFilename);
bnwIceCream.Write(Flavor[ChoiceFlavor - 1]);
bnwIceCream.Write(Container[ChoiceContainer -
1]);
bnwIceCream.Write(Ingredient[ChoiceIngredient -
1]);
bnwIceCream.Write(Scoops);
bnwIceCream.Write(TotalPrice);
}
finally
{
bnwIceCream.Close();
stmIceCream.Close();
}
}
}
catch (IOException ex)
{
Console.WriteLine("\nError: " + ex.Message);
Console.WriteLine("Operation Canceled: The file you want
" +
"to create exists already.");
}
}
C# 3.0 Practical Learning 874
internal void OpenOrder()
{
string strFilename;

string SelectedFlavor;
string SelectedContainer;
string SelectedIngredient;

// Ask the user to enter a name of a previously saved order


Console.Write("Please enter the name you previously " +
"gave to remember your order: ");
strFilename = Console.ReadLine();
strFilename = strFilename + ".icr";

try
{
FileStream stmIceCream =
new FileStream(strFilename, FileMode.Open);
BinaryReader bnrIceCream =
new BinaryReader(stmIceCream);

try
{
// Find out if this order was previously saved in the
machine
if (File.Exists(strFilename))
{
// If so, open it
SelectedFlavor = bnrIceCream.ReadString();
SelectedContainer = bnrIceCream.ReadString();
SelectedIngredient = bnrIceCream.ReadString();
Scoops = bnrIceCream.ReadInt32();
TotalPrice = bnrIceCream.ReadDecimal();

// And display it to the user


Console.WriteLine("\n=-= Ice Cream Vending
Machine =-=");
Console.WriteLine(" Previous Order: {0}",
strFilename);
Console.WriteLine("Flavor: {0}",
SelectedFlavor);
Console.WriteLine("Container: {0}",
SelectedContainer);
Console.WriteLine("Ingredient: {0}",
SelectedIngredient);
Console.WriteLine("Scoops: {0}", Scoops);
Console.WriteLine("Total Price: {0:C}\n",
TotalPrice);
}
else
Console.WriteLine("The name you entered is not "
+
"registered in our previous
orders");
}
finally
{
bnrIceCream.Close();
stmIceCream.Close();
C# 3.0 Practical Learning 875
}
}
catch (FileNotFoundException ex)
{
Console.Write("\nError: " + ex.Message);
Console.WriteLine("It is unlikely that the file exists in
" +
"our machine's register.");
}
}
}
}

2. Exercise the application and test it

3. Close the DOS window

File Information
 

Introduction

In its high level of support for file processing, the .NET Framework provides the
FileInfo class. This class is equipped to handle all types of file-related operations
including creating, copying, moving, renaming, or deleting a file. FileInfo is based on
the FileSystemInfo class that provides information on characteristics of a file.

Practical Learning: Introducing File Information

1. Start a new Console Application named WattsALoan2

2. To take advantage of the Visual Basic rich library, in the Solution Explorer, under
WattsALoan2, right-click References and click Add Reference

3. In the Add Reference dialog box, click the .NET tab and click
Microsoft.VisualBasic

C# 3.0 Practical Learning 876


 

4. Click OK

5. Change the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace WattsALoan1
{
public class Program
{
static int Main(string[] args)
{
string EmployerName, ApplicantName;
string HomePhone, WorkPhone;
double LoanAmount = 0.00D, InterestRate = 0.0D;
double MonthlyPayment = 0.00D, Periods = 0D;

Console.WriteLine(" -=- Car Loan Application -=-");


Console.WriteLine("Enter the following pieces " +
"of information\n");
Console.WriteLine("Applicant Information");
Console.Write("Full Name: ");
ApplicantName = Console.ReadLine();
Console.Write("Employer Name: ");
EmployerName = Console.ReadLine();
Console.Write("Home Phone: ");
HomePhone = Console.ReadLine();
Console.Write("Work Phone: ");
WorkPhone = Console.ReadLine();
Console.WriteLine("Loan Estimation");
C# 3.0 Practical Learning 877
try
{
Console.Write("Amount of Loan: ");
LoanAmount = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Loan Amount");
}
try
{
Console.Write("Interest Rate(0 to 100): ");
InterestRate = double.Parse(Console.ReadLine()) / 100;
}
catch (FormatException)
{
Console.WriteLine("Invalid Interest Rate");
}
try
{
Console.Write("Number of Months: ");
Periods = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Number of Months");
}

try
{
MonthlyPayment =
Microsoft.VisualBasic.Financial.Pmt(InterestRate / 12,
Periods, -LoanAmount,
0, Microsoft.VisualBasic.DueDate.BegOfPeriod);
}
catch (ArgumentException)
{
Console.WriteLine("Some invalid values were provided\n");
}

Console.WriteLine();
Console.WriteLine(" -=-=-=-=-=-=-=-=-=-=-=-=-=-=");
Console.WriteLine(" -=- Car Loan Application -=-");
Console.WriteLine(" -=-=-=-=-=-=-=-=-=-=-=-=-=-=");
Console.WriteLine("Applicant Information");
Console.WriteLine("Full Name: {0}", ApplicantName);
Console.WriteLine("Employer Name: {0}", EmployerName);
Console.WriteLine("Home Phone: {0}", HomePhone);
Console.WriteLine("Work Phone: {0}", WorkPhone);
Console.WriteLine("Loan Estimation");
Console.WriteLine("Loan Amount: {0:C}", LoanAmount);
Console.WriteLine("Interest Rate: {0:P}", InterestRate);
Console.WriteLine("Number of Months: {0:F}", Periods);
Console.WriteLine("Monthly Payment: {0:C}\n",
MonthlyPayment);
}
}
}

C# 3.0 Practical Learning 878


6. Execute the application and test it. Here is an example:
 
-=- Car Loan Application -=-
Enter the following pieces of information

Applicant Information
Full Name: James Watts
Employer Name: Wattson Enterprises
Home Phone: (202) 374-4738
Work Phone: (301) 894-4789
Loan Estimation
Amount of Loan: 12500
Interest Rate(0 to 100): 10.25
Number of Months: 48

-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-=- Car Loan Application -=-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Applicant Information
Full Name: James Watts
Employer Name: Wattson Enterprises
Home Phone: (202) 374-4738
Work Phone: (301) 894-4789
Loan Estimation
Loan Amount: $12,500.00
Interest Rate: 10.25 %
Number of Months: 48.00
Monthly Payment: $315.84
Press any key to continue...

7. Close the DOS window

File Initialization

The FileInfo class is equipped with one constructor whose syntax is:
public FileInfo(string fileName);

This constructor takes as argument the name of a file or its complete path. If you
provide only the name of the file, the compiler would consider the same directory of its
project. Here is an example:
FileInfo fleMembers = new FileInfo("First.txt");

Alternatively, if you want, you can provide any valid directory you have access to. In this
case, you should provide the complete path.

File Creation

The FileInfo constructor is mostly meant only to indicate that you want to use a file,
whether it exists already or it would be created. Based on this, if you execute an
application that has only a FileInfo object created using the constructor as done
above, nothing would happen.

C# 3.0 Practical Learning 879


To create a file, you have various alternatives. If you want to create one without writing
anything in it, which implies creating an empty file, you can call the
FileInfo.Create() method. Its syntax is:

public FileStream Create();

This method simply creates an empty file. Here is an example of calling it:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var fleMembers = new FileInfo("First.txt");
fleMembers.Create();

return 0;
}
}

The FileInfo.Create() method returns a FileStream object. You can use this
returned value to write any type of value into the file, including text. If you want to
create a file that contains text, an alternative is to call the FileInfo.CreateText()
method. Its syntax is:
public StreamWriter CreateText();

This method directly returns a StreamWriter object. You can use this returned object
to write text to the file.

File Existence

When you call the FileInfo.Create() or the FileInfo.CreateText() method, if the


file passed as argument, or as the file in the path of the argument, exists already, it
would be deleted and a new one would be created with the same name. This can cause
the right file to be deleted. Therefore, before creating a file, you may need to check
whether it exists already. To do this, you can check the value of the Boolean
FileInfo.Exists property. This property holds a true value if the file exists already
and it holds a false value if the file doesn't exist or it doesn't exist in the path.

Here is an example of checking the existence of a file:


using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var fleMembers = new FileInfo("First.txt");

if (fleMembers.Exists == true)
return 0;
else
fleMembers.Create();
C# 3.0 Practical Learning 880
return 0;
}
}

Writing to a File

As mentioned earlier, the FileInfo.Create() method returns a FileStream object.


You can use this to specify the type of operation that would be allowed on the file.

To write normal text to a file, you can first call the FileInfo.CreateText() method.
This method returns a StreamWriter object. The StreamWriter class is based on the
TextWriter class that is equipped with the Write() and the WriteLine() methods
used to write values to a file. The Write() method writes text on a line and keeps the
caret on the same line. The WriteLine() method writes a line of text and moves the
caret to the next line.

After writing to a file, you should close the StreamWriter object to free the resources it
was using during its operation(s).

Practical Learning: Writing to a File

1. To allow the user to create a new employee, change the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace WattsALoan2
{
class Program
{
private static void CreateNewEmployee()
{
string employeeNumber, employeeName;
FileInfo fleEmployees = new FileInfo("Employees.txt");
StreamWriter swrEmployees = fleEmployees.CreateText();

try
{
Console.WriteLine("Hiring New Employee");
Console.Write("Enter Employee Number as 00-000: ");
employeeNumber = Console.ReadLine();
Console.Write("Enter Employee Name: ");
employeeName = Console.ReadLine();

swrEmployees.WriteLine(employeeNumber);
swrEmployees.WriteLine(employeeName);

}
finally
C# 3.0 Practical Learning 881
{
swrEmployees.Flush();
swrEmployees.Close();
}
}

static int Main(string[] args)


{
try
{
Console.Write("Do you want to hire a new " +
"employee(0=No/1=Yes)? ");
int answer = int.Parse(Console.ReadLine());

if (answer == 1)
CreateNewEmployee();
}
catch (FormatException)
{
Console.WriteLine("That was an invalid answer!\n");
}

string EmployerName, ApplicantName;


string HomePhone, WorkPhone;
double LoanAmount = 0.00D, InterestRate = 0.0D;
double MonthlyPayment = 0.00D, Periods = 0D;

. . . No Change

return 0;
}
}
}

2. Execute the application. Here is an example:


 
Do you want to hire a new employee(0=No/1=Yes)? 1
Hiring New Employee
Enter Employee Number as 00-000: 44-228
Enter Employee Name: Johnny Olney

3. Close the DOS window

Appending to a File

You may have created a text-based file and written to it. If you open such a file and find
out that a piece of information is missing, you can add that information to the end of the
file. To do this, you can call the FileInfo.AppenText() method. Its syntax is:
public StreamWriter AppendText();

When calling this method, you can retrieve the StreamWriter object that it returns,
then use that object to add new information to the file.

Practical Learning: Appending to a File

C# 3.0 Practical Learning 882


1. To allow the user to add more employees to the file that holds their names, change
the file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace WattsALoan2
{
public class Program
{
private static void CreateNewEmployee()
{
string employeeNumber, employeeName;
FileInfo fleEmployees = new FileInfo("Employees.txt");
StreamWriter swrEmployees = null;

// If the file exists already, then add the new employee to


it
if (fleEmployees.Exists == true)
swrEmployees = fleEmployees.AppendText();
else // Otherwise, create a new file
swrEmployees = fleEmployees.CreateText();

try
{
Console.WriteLine("Hiring New Employee");
Console.Write("Enter Employee Number as 00-000: ");
employeeNumber = Console.ReadLine();
Console.Write("Enter Employee Name: ");
employeeName = Console.ReadLine();

swrEmployees.WriteLine(employeeNumber);
swrEmployees.WriteLine(employeeName);

}
finally
{
swrEmployees.Flush();
swrEmployees.Close();
}
}

static void Main(string[] args)


{
. . . No Change
}
}
}

2. Execute the application

3. Type y to create an employee. Here is an example:


 
Do you want to hire a new employee(0=No/1=Yes)? 1

C# 3.0 Practical Learning 883


Hiring New Employee
Enter Employee Number as 00-000: 72-604
Enter Employee Name: Ernest Barzan

4. Close the DOS window

C# 3.0 Practical Learning 884


Files Operations
 

Routine Operations on Files


 

Opening a File

As opposed to creating a file, probably the second most regular operation performed on
a file consists of opening it to read or explore its contents. To support opening a file,
the FileInfo class is equipped with the Open() method that is overloaded with three
versions.

If you have a text-based file and want to directly read from it, you can use the
StreamReader class that is equipped with the Read() and the ReadLine() methods. As
done for the StreamWriter class, after using a StreamReader object, make sure you
close it.

Deleting a File

If you have an existing file you don't need anymore, you can delete it. This operation
can be performed by calling the FileInfo.Delete() method. Its syntax is:
public override void Delete();

Here is an example:

using System;

using System.IO;

public class Program


{
static int Main(string[] args)
{
var fleMembers = new FileInfo("First.txt");

if (fleMembers.Exists == true)
fleMembers.Delete();

return 0;
}
}

Copying a File
C# 3.0 Practical Learning 885
You can make a copy of a file from one directory to another. To do this, you can call the
FileInfo.CopyTo() method that is overloaded with two versions. The first version has
the following syntax:
public FileInfo CopyTo(string destFileName);

When calling this method, specify the path or directory that will be the destination of the
copied file. Here is an example:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var fleMembers = new FileInfo("Reality.txt");
var strMyDocuments =

Environment.GetFolderPath(Environment.SpecialFolder.Personal);

if (fleMembers.Exists == true)
fleMembers.CopyTo(string.Concat(strMyDocuments,
"\\Federal.txt"));

return 0;
}
}

In this example, a file named Reality.txt in the directory of the project would be
retrieved and its content would be applied to a new file named Federal.txt created in the
My Documents folder of the current user.

When calling the first version of the FileInfo.CopyTo() method, if the file exists
already, the operation would not continue and you would simply receive a message box.
If you insist, you can overwrite the target file. To do this, you can use the second
version of this method. Its syntax is:
public FileInfo CopyTo(string destFileName, bool overwrite);

The first argument is the same as that of the first version of the method. The second
argument specifies what action to take if the file exists already in the target directory. If
you want to overwrite it, pass the argument as true; otherwise, pass it as false.

Moving a File

If you copy a file from one directory to another, you would have two copies of the same
file or the same contents in two files. Instead of copying, if you want, you can simply
move the file from one directory to another. This operation can be performed by calling
the FileInfo.MoveTo() method. Its syntax is:
public void MoveTo(string destFileName);

The argument to this method is the same as that of the CopyTo() method. After
executing this method, the FileInfo object would be moved to the destFileName path.

C# 3.0 Practical Learning 886


Here is an example:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var fleMembers = new FileInfo("pop.txt");
var strMyDocuments =

Environment.GetFolderPath(Environment.SpecialFolder.Personal);

if (fleMembers.Exists == true)
fleMembers.MoveTo(string.Concat(strMyDocuments,
"\\Federal.txt"));

return 0;
}
}

Characteristics of a File
 

The Date and Time a File Was Created 

To keep track of it, after a file has been created, the operating system makes a note of
the date and the time the file was created. This information can be valuable in other
operations such as search routines. You too are allowed to change this date and time
values to those you prefer.

As mentioned already, the OS makes sure to keep track of the date and time a file was
created. To find out what those date and time values are, you can access the
FileSystemInfo.CreationTime property. This would be done as follows:

using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var SomeFile = new FileInfo("First.txt");
DateTime dteCreationTime = SomeFile.CreationTime;

if (SomeFile.Exists == true)
Console.WriteLine("Date and Time Created: " +
dteCreationTime.ToString());

return 0;
}
}

Of course, by entering the appropriate format in the parentheses of the ToString()


method, you can get only either the date or only the time.
C# 3.0 Practical Learning 887
If you don't like the date, the time, or both, that the OS would have set when the file
was created, you can change them. To change one or both of these values, you can
assign a desired DateTime object to the FileSystemInfo.set_CreationTime()
property.

The Date and Time a File Was Last Accessed 

Many applications allow a user to open an existing file and to modify it. When people
work in a team or when a particular file is regularly opened, at one particular time, you
may want to know the date and time that the file was last accessed. To get this
information, you can access the FileSystemInfo.LastAccessTime property.

If you are interested to know the last date and time a file was modified, you can get the
value of its FileSystemInfo.LastWriteTime property.

The Name of a File

The operating system requires that each file have a name. In fact, the name must be
specified when creating a file. This allows the OS to catalogue the computer files. This
also allows you to locate or identify a particular file you need.

When reviewing or opening a file, to get its name, the FileInfo class is equipped with
the Name property. Here is an example:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var SomeFile = new FileInfo("Persons.spr");

if (SomeFile.Exists == true)
Console.WriteLine("The name of this file is: \"" +
SomeFile.Name + "\"");

return 0;
}
}

This string simply identifies a file.

The Extension of a File

With the advent of Windows 95 and later, the user doesn't have to specify the extension
of a file when creating it. Because of the type of confusion that this can lead to, most
applications assist the user with this detail. Some applications allow the user to choose
among various extensions. For example, using Notepad, a user can open a text, a PHP,
a script, or an HTML file.

C# 3.0 Practical Learning 888


When you access a file or when the user opens one, to know the extension of the file,
you can access the value of the FileSystemInfo.Extension property. Here is an
example:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var SomeFile = new FileInfo("Persons.spr");

if (SomeFile.Exists == true)
Console.WriteLine("File Extension: " + SomeFile.Extension);

return 0;
}
}

This would produce:


File Extension: .spr
Press any key to continue . . .

The Size of a File

One of the routine operations the operating system performs consists of calculating the
sizes of files it holds. This information is provided in terms of bits, kilobits, or kilobytes.
To get the size of a file, the FileInfo class is quipped with the Length property. Here
is an example of accessing it:
using System;
using System.IO;

public class Program


{
static int Main(string[] args)
{
var SomeFile = new FileInfo("Persons.spr");

if (SomeFile.Exists == true)
Console.WriteLine("File Size: " +
SomeFile.Length.ToString());

return 0;
}
}

Here is an example of what this would produce:


File Size: 57
Press any key to continue . . .

The Path to a File

C# 3.0 Practical Learning 889


Besides the name of the file, it must be located somewhere. The location of a file is
referred to as its path or directory. The FileInfo class represents this path as the
DirectoryName property. Therefore, if a file has already been created, to get its path,
you can access the value of the FileInfo.DirectoryName property.

Besides the FileInfo.Directoryname, to know the full path to a file, you can access
its FileSystemInfo.FullName property.

The Attributes of a File

Attributes are characteristics that apply to a file, defining what can be done or must be
disallowed on it. The Attributes are primarily defined by, and in, the operating system,
mostly when a file is created. When the user accesses or opens a file, to get its
attributes, you can access the value of its FileSystemInfo.Attributes property. This
property produces a FileAttributes object.

When you create or access a file, you can specify or change some of the attributes. To
do this, you can a FileAttributes object and assign it to the
FileSystemInfo.Attributes property.

FileAttributes is an enumerator with the following members: Archive, Compressed,


Device, Directory, Encrypted, Hidden, Normal, NotContentIndexed, Offline,
ReadOnly, ReparsePoint, SparseFile, System, and Temporary.

Directories
 

Introduction

A directory is a section of a medium used to delimit a group of files. Because it is a


"physical" area, it can handle operations not available on files. In fact, there are many
fundamental differences between both:

 A file is used to contain data. A directory doesn't contain data

 A directory can contain one or more files and not vice-versa

 A directory can contain other directories

 A file can be moved from one directory to another. This operation is not possible
vice-versa since a file cannot contain a directory

The similarities of both types are:

 A directory or a file can be created. One of the restrictions is that two files cannot
have the same name inside of the same directory. Two directories cannot have the
same name inside of the same parent directory.

 A directory or a file can be renamed. If a directory is renamed, the "path" of its


file(s) changes

 A directory or a file can be deleted. If a directory is deleted, its files are deleted also

C# 3.0 Practical Learning 890


 A directory or a file can be moved. If a directory moves, it "carries" all of its files to
the new location

 A directory or a file can be copied. A file can be copied from one directory to
another. If a directory is copied to a new location, all of its files are also copied to
the new location

Practical Learning: Introducing Directories

1. Start Microsoft Visual C# and create a Console Application named


GeorgetownCleaningServices6

2. To create a new class, in the Solution Explorer, right-click


GeorgetownCleaningServices6 -> Add -> Class...

3. Set the Name to Customer and click OK

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices6
{
public class Customer
{
public string Name;
public string PhoneNumber;
}
}

5. To create a new class, on the main menu, click Project -> Add Class...

6. Set the Name to CleaningOrderDetails and press Enter

7. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices6
{
public sealed class CleaningOrderDetails
{
// The date the cleaning items were deposited
public DateTime OrderDate;
public DateTime OrderTime;
// Numbers to represent cleaning items
public uint NumberOfShirts;
public uint NumberOfPants;
public uint NumberOtherItems;

C# 3.0 Practical Learning 891


// Price of items
public decimal PriceOneShirt = 0.95M;
public decimal PriceAPairOfPants = 2.95M;
public decimal PriceOtherItems = 4.55M;
public decimal TaxRate = 0.0575M; // 5.75%

// Each of these sub totals will be used for cleaning items


public decimal SubTotalShirts;
public decimal SubTotalPants;
public decimal SubTotalOtherItems;

// Values used to process an order


public decimal TotalOrder;
public decimal TaxAmount;
public decimal SalesTotal;
}
}

8. To save the project, on the Standard toolbar, click the Save All button

9. Accept all the defaults and click Save

Directory Creation

Before using a directory, you must first have it. You can use an existing directory if the
operating system or someone else had already created one. You can also create a new
directory. Directories are created and managed by various classes but the fundamental
class is Directory. Directory is a static class, which means all of its methods are
static, which means you will never need to declare an instance of the Directory class in
order to use it.

Besides the Directory class, additional operations of folders and sub-folders can be
performed using the DirectoryInfo class.

To create a directory, you can call the CreateDirectory() method of the Directory
class. This method is available in two versions. One of the versions uses the following
syntax:
public static DirectoryInfo CreateDirectry(string path);

This method takes as argument the (complete) path of the desired directory. Here is an
example:
E:\Programs\Business Orders\Customer Information

When this method is called:

1. It first checks the parent drive, in this case E.


If the drive doesn't exist, because this method cannot create a drive, the compiler
would throw a DirectoryNotFoundException exception

2. If the drive (in this case E) exists, the compiler moves to the first directory part of
the path; in this case this would be the Programs folder in the E drive.
If the folder doesn't exist, the compiler would create it. If that first director doesn't
exist, this means that the other directory(ies), if any, under the first don't exist. So,
the compiler would create it/them
C# 3.0 Practical Learning 892
3. If the first directory exists and if there is no other directory under that directory,
the compiler would stop and would not do anything further.

4. If the directory exists and there is a sub-directory specified under it, the compiler
would check the existence of that directory.
If the sub-directory exists, the compiler would not do anything further and would
stop.
If the sub-directory doesn't exist, the compiler would create it

5. The compiler would repeat step 4 until the end of the specified path

The Directory.CreateDirectory() method returns a DirectoryInfo object that you


can use as you see fit.

Checking for a Directory Existence

Before using or creating a directory, you can first check if it exists. This is because, if a
directory already exists in the location where you want to create it, you would be
prevented from creating one with the same name. In the same way, if you just decide to
directly use a directory that doesn't exist, the operation you want to perform may fail
because the directory would not be found.

Before using or creating a directory, to first check whether it exists or not, you can call
the Directory.Exists() Boolean method. Its syntax is:
public static bool Exists(string path);

This method receives the (complete) path of the directory. If the path exists, the
method returns true. If the directory doesn't exist, the method returns false.

To create a directory, you can call the CreateDirectory() method of the Directory
class.

Locating a File

One of the most routine operations performed in a directory consists of looking for a file.
Both Microsoft Windows operating systems and the user's intuition have different ways
of addressing this issue. The .NET Framework also provides its own means of
performing this operation, through various techniques. You can start by checking the
sub-directories and files inside of a main directory.

To look for files in a directory, the DirectoryInfo class can assist you with its
GetFiles() method, which is overloaded with three versions.

Practical Learning: Using Directories and Files

1. To create a new class, in the Class View, right-click GeorgetownCleaningOrder6 ->


Add -> Class...

2. Set the Name to CleaningDeposit and press Enter

3. Change the file as follows:


 
C# 3.0 Practical Learning 893
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace GeorgetownCleaningServices6
{
public abstract class CustomerOrder
{
public abstract void ProcessOrder();
public abstract void ShowReceipt();
}

public class CleaningDeposit : CustomerOrder


{
private Customer custInfo;
public CleaningOrderDetails depot;
private decimal AmountTended;
private decimal Difference;

public CleaningDeposit()
{
this.custInfo = new Customer();
this.depot = new CleaningOrderDetails();
}

private Customer IdentifyCustomer()


{
string strCustomerName;
string strTelephoneNumber, strPhoneFormatted;

Console.Write("Enter Customer Phone Number: ");


strTelephoneNumber = Console.ReadLine();

// Remove the spaces, parentheses, if any, and dashes, if any


strTelephoneNumber = strTelephoneNumber.Replace(" ", "");
strTelephoneNumber = strTelephoneNumber.Replace("(", "");
strTelephoneNumber = strTelephoneNumber.Replace(")", "");
strTelephoneNumber = strTelephoneNumber.Replace("-", "");
if (strTelephoneNumber.Length != 10)
{
Console.WriteLine("Invalid telphone number: {0} " +
"characters instead of 10 digits",
strTelephoneNumber.Length);
return null;
}
strPhoneFormatted = "(" + strTelephoneNumber.Substring(0, 3)
+
") " + strTelephoneNumber.Substring(3, 3)
+
"-" + strTelephoneNumber.Substring(6, 4);

string strFilename = strTelephoneNumber + @".gcs";


string strPath = @"C:\Georgetown Cleaning
Services\Customers\" +
@"\" + strFilename;

if (File.Exists(strPath))
{
C# 3.0 Practical Learning 894
FileStream stmCustomer =
File.Open(strPath, FileMode.Open, FileAccess.Read);
BinaryReader bnrCustomer = new BinaryReader(stmCustomer);

custInfo.Name = bnrCustomer.ReadString();
custInfo.PhoneNumber = bnrCustomer.ReadString();

Console.WriteLine("\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
=-");
Console.WriteLine("-/- Georgetown Cleaning Services
-/-");

Console.WriteLine("------------------------------------");
Console.WriteLine("Customer Name: {0}", custInfo.Name);
Console.WriteLine("Phone Number: {0}",
custInfo.PhoneNumber);

Console.WriteLine("------------------------------------\n");
}
else // If the customer information was not found in a file
{
Console.WriteLine("It looks like this is the first time
you " +
"are trusting us with your cleaning
order");
Directory.CreateDirectory(@"C:\Georgetown Cleaning Services\Customers");
FileStream stmCustomer = File.Create(strPath);
BinaryWriter bnwCustomer =
new BinaryWriter(stmCustomer);
Console.Write("Enter Customer Name: ");
strCustomerName = Console.ReadLine();
bnwCustomer.Write(strCustomerName);
bnwCustomer.Write(strPhoneFormatted);

custInfo.Name = strCustomerName;
custInfo.PhoneNumber = strTelephoneNumber;
}

return custInfo;
}

public override void ProcessOrder()


{
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Customer client = this.IdentifyCustomer();

try
{
Console.Write("Enter the order date(mm/dd/yyyy): ");
this.depot.OrderDate =
DateTime.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you entered is not a valid
date");
}
try
{
Console.Write("Enter the order time(hh:mm AM/PM): ");
C# 3.0 Practical Learning 895
this.depot.OrderTime =
DateTime.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("The value you entered is not a valid
time");
}

// Request the quantity of each category of items


try
{
Console.Write("Number of Shirts: ");
this.depot.NumberOfShirts =
uint.Parse(Console.ReadLine());
if (this.depot.NumberOfShirts < uint.MinValue)
throw new OverflowException("Negative value not " +
"allowed for shirts");
}
catch (FormatException)
{
Console.WriteLine("The value you typed for the number of
" +
"shirts is not a valid number");
}
try
{
Console.Write("Number of Pants: ");
this.depot.NumberOfPants =
uint.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you typed for the number of
" +
"pair or pants is not a valid number");
}
try
{
Console.Write("Number of Other Items: ");
this.depot.NumberOtherItems =
uint.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("The value you typed for the number of
" +
"other items is not a valid number");
}
// Perform the necessary calculations
this.depot.SubTotalShirts =
this.depot.NumberOfShirts * this.depot.PriceOneShirt;
this.depot.SubTotalPants =
this.depot.NumberOfPants * this.depot.PriceAPairOfPants;
this.depot.SubTotalOtherItems =
this.depot.NumberOtherItems * this.depot.PriceOtherItems;
// Calculate the "temporary" total of the order
this.depot.TotalOrder = this.depot.SubTotalShirts +
this.depot.SubTotalPants +
this.depot.SubTotalOtherItems;
C# 3.0 Practical Learning 896
// Calculate the tax amount using a constant rate
this.depot.TaxAmount = this.depot.TotalOrder *
this.depot.TaxRate;
// Add the tax amount to the total order
this.depot.SalesTotal = this.depot.TotalOrder +
this.depot.TaxAmount;

// Communicate the total to the user...


Console.WriteLine("\nThe Total order is: {0:C}",
this.depot.SalesTotal);
// and request money for the order
try
{
Console.Write("Amount Tended? ");
AmountTended = decimal.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You were asked to enter an " +
"amount of money but...");
}
// Calculate the difference owed to the customer
// or that the customer still owes to the store
Difference = AmountTended - this.depot.SalesTotal;

this.ShowReceipt();
this.Save();
}

public override void ShowReceipt()


{
Console.WriteLine();
// Display the receipt
Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}", this.custInfo.Name);
Console.WriteLine("Home Phone: {0}",
this.custInfo.PhoneNumber);
Console.WriteLine("Order Date: {0:D}",
this.depot.OrderDate);
Console.WriteLine("Order Time: {0:t}",
this.depot.OrderTime);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0,3} {1,4} {2,6}",
this.depot.NumberOfShirts,
this.depot.PriceOneShirt,
this.depot.SubTotalShirts);
Console.WriteLine("Pants {0,3} {1,4} {2,6}",
this.depot.NumberOfPants,
this.depot.PriceAPairOfPants,
this.depot.SubTotalPants);
Console.WriteLine("Other Items {0,3} {1,4} {2,6}",
this.depot.NumberOtherItems,
this.depot.PriceOtherItems,
this.depot.SubTotalOtherItems);
Console.WriteLine("------------------------------------");
C# 3.0 Practical Learning 897
Console.WriteLine("Total Order: {0,6}",
this.depot.TotalOrder.ToString("C"));
Console.WriteLine("Tax Rate: {0,6}",
this.depot.TaxRate.ToString("P"));
Console.WriteLine("Tax Amount: {0,6}",
this.depot.TaxAmount.ToString("C"));
Console.WriteLine("Net Price: {0,6}",
this.depot.SalesTotal.ToString("C"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0,6}",
AmountTended.ToString("C"));
Console.WriteLine("Difference: {0,6}",
Difference.ToString("C"));
Console.WriteLine("====================================");
}

public virtual void Save()


{
string strPhoneNumber = this.custInfo.PhoneNumber;

// Remove the spaces, parentheses, and dashes


strPhoneNumber = strPhoneNumber.Replace(" ", "");
strPhoneNumber = strPhoneNumber.Replace("(", "");
strPhoneNumber = strPhoneNumber.Replace(")", "");
strPhoneNumber = strPhoneNumber.Replace("-", "");

string strMonth = depot.OrderDate.Month.ToString();


if (depot.OrderDate.Month < 10)
strMonth = "0" + strMonth;

string strDay = depot.OrderDate.Day.ToString();


if (depot.OrderDate.Day < 10)
strDay = "0" + strDay;

string strYear = depot.OrderDate.Year.ToString();

string strFilename = strMonth + strDay + strYear + @".gcs";

string strPath = @"C:\Georgetown Cleaning Services\Cleaning


Orders\" +
@"\" + strPhoneNumber + @"\" + strFilename;

Directory.CreateDirectory(@"C:\Georgetown Cleaning Services\Cleaning


Orders\"
+ strPhoneNumber);

FileStream stmCleaningOrder = File.Create(strPath);


BinaryWriter bnwCleaningOrder =
new BinaryWriter(stmCleaningOrder);

bnwCleaningOrder.Write(this.custInfo.Name);
bnwCleaningOrder.Write(this.custInfo.PhoneNumber);
bnwCleaningOrder.Write(this.depot.OrderDate.ToString());
bnwCleaningOrder.Write(this.depot.OrderTime.ToString());
bnwCleaningOrder.Write(this.depot.NumberOfShirts.ToString());
bnwCleaningOrder.Write(this.depot.NumberOfPants.ToString());

bnwCleaningOrder.Write(this.depot.NumberOtherItems.ToString());
bnwCleaningOrder.Write(this.depot.PriceOneShirt.ToString());

C# 3.0 Practical Learning 898


bnwCleaningOrder.Write(this.depot.PriceAPairOfPants.ToString());

bnwCleaningOrder.Write(this.depot.PriceOtherItems.ToString());
bnwCleaningOrder.Write(this.depot.TaxRate.ToString());
bnwCleaningOrder.Write(this.depot.SubTotalShirts.ToString());
bnwCleaningOrder.Write(this.depot.SubTotalPants.ToString());

bnwCleaningOrder.Write(this.depot.SubTotalOtherItems.ToString());
bnwCleaningOrder.Write(this.depot.TotalOrder.ToString());
bnwCleaningOrder.Write(this.depot.TaxAmount.ToString());
bnwCleaningOrder.Write(this.depot.SalesTotal.ToString());
}
}
}

4. To create a new class, in the Solution Explorer, right- click


GeorgetownCleaningOrder6 -> Add -> Class...

5. Set the Name to CleaningRetrieval and press Enter

6. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace GeorgetownCleaningServices6
{
public class CleaningRetrieval
{
private Customer custInfo;
private CleaningOrderDetails depot;
private string strPhoneNumber;

public CleaningRetrieval()
{
this.custInfo = new Customer();
this.depot = new CleaningOrderDetails();
}

public virtual void Open()


{
Console.Write("Enter Receipt Number: ");
string strFilename = Console.ReadLine();

string strPath = @"C:\Georgetown Cleaning Services\Cleaning


Orders\" +
@"\" + strFilename + @"\" + strFilename +
".gcs";

DirectoryInfo di =
new DirectoryInfo(@"C:\Georgetown Cleaning Services\Cleaning
Orders");
FileInfo[] aryFiles = di.GetFiles("*",
SearchOption.AllDirectories);

C# 3.0 Practical Learning 899


string strFileFullname = "";
bool found = false;

foreach (FileInfo fle in aryFiles)


{
if (fle.Name == (strFilename + ".gcs"))
{
found = true;
strFileFullname = fle.FullName;
}
}

if (found == true)
{
FileStream stmCleaningOrder =
File.Open(strFileFullname,
FileMode.Open,
FileAccess.Read);
BinaryReader bnrCleaningOrder = new
BinaryReader(stmCleaningOrder);
this.custInfo.Name = bnrCleaningOrder.ReadString();
this.custInfo.PhoneNumber =
bnrCleaningOrder.ReadString();
this.depot.OrderDate =
DateTime.Parse(bnrCleaningOrder.ReadString());
this.depot.OrderTime =
DateTime.Parse(bnrCleaningOrder.ReadString());
this.depot.NumberOfShirts =
uint.Parse(bnrCleaningOrder.ReadString());
this.depot.NumberOfPants =
uint.Parse(bnrCleaningOrder.ReadString());
this.depot.NumberOtherItems =
uint.Parse(bnrCleaningOrder.ReadString());
this.depot.PriceOneShirt =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.PriceAPairOfPants =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.PriceOtherItems =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.TaxRate =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.SubTotalShirts =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.SubTotalPants =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.SubTotalOtherItems =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.TotalOrder =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.TaxAmount =
decimal.Parse(bnrCleaningOrder.ReadString());
this.depot.SalesTotal =
decimal.Parse(bnrCleaningOrder.ReadString());

this.strPhoneNumber = "(" +
this.custInfo.PhoneNumber.Substring(0,
3) +
") " +
this.custInfo.PhoneNumber.Substring(3,
3) +
C# 3.0 Practical Learning 900
"-" +
this.custInfo.PhoneNumber.Substring(6,
4);
this.ShowReceipt();
}
else
Console.WriteLine("No cleaning order of " +
"that receipt number was found");
}

internal void ShowReceipt()


{
Console.WriteLine();
// Display the receipt
Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}", this.custInfo.Name);
Console.WriteLine("Home Phone: {0}",
this.custInfo.PhoneNumber);
Console.WriteLine("Order Date: {0:D}",
this.depot.OrderDate);
Console.WriteLine("Order Time: {0:t}",
this.depot.OrderTime);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts {0,3} {1,4} {2,6}",
this.depot.NumberOfShirts,
this.depot.PriceOneShirt,
this.depot.SubTotalShirts);
Console.WriteLine("Pants {0,3} {1,4} {2,6}",
this.depot.NumberOfPants,
this.depot.PriceAPairOfPants,
this.depot.SubTotalPants);
Console.WriteLine("Other Items {0,3} {1,4} {2,6}",
this.depot.NumberOtherItems,
this.depot.PriceOtherItems,
this.depot.SubTotalOtherItems);
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0,6}",
this.depot.TotalOrder.ToString("C"));
Console.WriteLine("Tax Rate: {0,6}",
this.depot.TaxRate.ToString("P"));
Console.WriteLine("Tax Amount: {0,6}",
this.depot.TaxAmount.ToString("C"));
Console.WriteLine("Net Price: {0,6}",
this.depot.SalesTotal.ToString("C"));
Console.WriteLine("====================================");
}
}
}

7. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
C# 3.0 Practical Learning 901
namespace GeorgetownCleaningServices6
{
public class Program
{
static void Main(string[] args)
{
char answer = 'q';

Console.WriteLine("Is this a new order or the customer is " +


"retrieving items previously left for
cleaning?");
Console.WriteLine("0. Quit");
Console.WriteLine("1. This is a new order");
Console.WriteLine("2. The customer is retrieving an existing
order");
Console.Write("Your Choice: ");
answer = char.Parse(Console.ReadLine());

switch (answer)
{
case '1':
CleaningDeposit depotOrder = new CleaningDeposit();
depotOrder.ProcessOrder();
break;

case '2':
CleaningRetrieval previousOrder = new
CleaningRetrieval();
previousOrder.Open();
break;

default:
break;
}

Console.WriteLine();
}
}
}

8. Execute the application and test it. Here is an example:


 
Is this a new order or the customer is retrieving
items previously left for cleaning?
0. Quit
1. This is a new order
2. The customer is retrieving an existing order
Your Choice: 0

Press any key to continue . . .

9. Close the DOS window

10.Execute the application and create a new order. Here is an example:


 
Is this a new order or the customer is retrieving
items previously left for cleaning?
C# 3.0 Practical Learning 902
0. Quit
1. This is a new order
2. The customer is retrieving an existing order
Your Choice: 1
-/- Georgetown Cleaning Services -/-
Enter Customer Phone Number: 202 103 0443
It looks like this is the first time you are trusting
us with your cleaning order
Enter Customer Name: Arsene Cranston
Enter the order date(mm/dd/yyyy): 11/20/2006
Enter the order time(hh:mm AM/PM): 08:12 AM
Number of Shirts: 6
Number of Pants: 4
Number of Other Items: 2

The Total order is: $28.13


Amount Tended? 30

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Arsene Cranston
Home Phone: 2021030443
Order Date: Monday, November 20, 2006
Order Time: 8:12 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 6 0.95 5.70
Pants 4 2.95 11.80
Other Items 2 4.55 9.10
------------------------------------
Total Order: $26.60
Tax Rate: 5.75 %
Tax Amount: $1.53
Net Price: $28.13
------------------------------------
Amount Tended: $30.00
Difference: $1.87
====================================

Press any key to continue . . .

11.Remember the date you provided and close the DOS window

12.Execute the application and create a new order. Here is an example:


 
Is this a new order or the customer is retrieving items
previously left for cleaning?
0. Quit
1. This is a new order
2. The customer is retrieving an existing order
Your Choice: 1
-/- Georgetown Cleaning Services -/-
Enter Customer Phone Number: 301-022-1077
It looks like this is the first time you are trusting
us with your cleaning order
Enter Customer Name: Helene Craft
Enter the order date(mm/dd/yyyy): 11/21/2006
C# 3.0 Practical Learning 903
Enter the order time(hh:mm AM/PM): 9:25
Number of Shirts: 3
Number of Pants: 0
Number of Other Items: 5

The Total order is: $27.07


Amount Tended? 40

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Helene Craft
Home Phone: 3010221077
Order Date: Tuesday, November 21, 2006
Order Time: 9:25 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 3 0.95 2.85
Pants 0 2.95 0.00
Other Items 5 4.55 22.75
------------------------------------
Total Order: $25.60
Tax Rate: 5.75 %
Tax Amount: $1.47
Net Price: $27.07
------------------------------------
Amount Tended: $40.00
Difference: $12.93
====================================

Press any key to continue . . .

13.Remember the date you provided and close the DOS window

14.Execute the application and choose to open an existing order. Here is an example:
 
Is this a new order or the customer is retrieving
items previously left for cleaning?
0. Quit
1. This is a new order
2. The customer is retrieving an existing order
Your Choice: 2
Enter Receipt Number: 11202006

====================================
-/- Georgetown Cleaning Services -/-
====================================
Customer: Arsene Cranston
Home Phone: 2021030443
Order Date: Monday, November 20, 2006
Order Time: 8:12 AM
------------------------------------
Item Type Qty Unit/Price Sub-Total
------------------------------------
Shirts 6 0.95 5.70
Pants 4 2.95 11.80
Other Items 2 4.55 9.10
------------------------------------
C# 3.0 Practical Learning 904
Total Order: $26.60
Tax Rate: 5.75 %
Tax Amount: $1.53
Net Price: $28.13
====================================

Press any key to continue . . .

15.Close the DOS window

C# 3.0 Practical Learning 905


Serialization
 

Object Serialization and De-Serialization


 

Introduction

Consider the following program:

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

public class Exercise

{
static int Main(string[] args)
{
var Make = "Ford";
var Model = "Escort";
var Year = 1998;

var Color = 1;

var stmCar = new FileStream("Car1.car", FileMode.Create);


var bnwCar = new BinaryWriter(stmCar);

try
{
bnwCar.Write(Make);
bnwCar.Write(Model);
bnwCar.Write(Year);
bnwCar.Write(Color);
}
finally
{
bnwCar.Close();
stmCar.Close();
}

return 0;
}
}

This is an example of the techniques we have used in previous lessons to save individual
data of primitive types:
C# 3.0 Practical Learning 906
The values can be retrieved with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

public class Exercise


{
static int Main(string[] args)
{
var stmCar = new FileStream("Car1.car", FileMode.Open);
var bnrCar = new BinaryReader(stmCar);

try
{
Console.WriteLine("Make: {0}", bnrCar.ReadString());
Console.WriteLine("Model: {0}", bnrCar.ReadString());
Console.WriteLine("Year: {0}", bnrCar.ReadUInt32());
Console.Write("Color: ");
byte clr = bnrCar.ReadByte();
switch (clr)
{
case 1:
Console.WriteLine("Black");
break;
case 2:
Console.WriteLine("Gray");
break;
case 3:
Console.WriteLine("White");
break;
case 4:
Console.WriteLine("Red");
break;
case 5:
Console.WriteLine("Blue");
break;
}
}
finally
{
bnrCar.Close();
stmCar.Close();
}

return 0;
}
}

C# 3.0 Practical Learning 907


This would produce:
Make: Ford
Model: Escort
Year: 1998
Color: Black
Press any key to continue . . .

In the same way, we learned to save the individual fields of a class:

Here is an example:
using System;
using System.IO;

public class Car


{
public string Make = "Toyota";
public string Model = "Corolla";
public uint Year = 2002;
public byte Color = 2;
}

public class Exercise


{
static int Main(string[] args)
{
var vehicle = new Car();

var stmCar = File.Create("Car2.car");


var bnwCar = new BinaryWriter(stmCar);

try
{
bnwCar.Write(vehicle.Model);
bnwCar.Write(vehicle.Year);
bnwCar.Write(vehicle.Color);
}
finally
{
bnwCar.Close();
stmCar.Close();
}

return 0;

C# 3.0 Practical Learning 908


}
}

When it comes to a class, the problem with saving individual fields is that you could
forget to save one of the fields. For example, considering a Car class, if you don't save
the Make information of a Car object and retrieve or open the saved object on another
computer, the receiving user would miss some information and the car cannot be
completely identifiable. An alternative is to save the whole Car object.

Object serialization consists of saving a whole object as one instead of its individual
fields:

In other words, a variable declared from a class can be saved to a stream and then the
saved object can be retrieved later or on another computer. The .NET Framework
supports two types of object serialization: binary and SOAP.

Practical Learning: Introducing Serialization

1. Start Microsoft Visual C# and create a Console Application named


GeorgetownCleaningServices7

2. To save the project, on the Standard toolbar, click the Save All button

3. Accept all the defaults and click Save

4. To create a new class, in the Solution Explorer, right-click


GeorgetownCleaningServices7 -> Add -> Class...

5. Set the Name to BusinessManagement and press Enter

6. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace GeorgetownCleaningServices7
{
public static class BusinessManagement

C# 3.0 Practical Learning 909


{
public static void HireEmployee()
{
FileStream fsEmployee = null;
BinaryWriter bwEmployee = null;

// Ask the clerk to enter an employee number


// using the format 00-000
Console.Write("Enter Employee Number (00-000): ");
string emplNumber = Console.ReadLine();

string strPath = @"C:\Georgetown Cleaning


Services\Employees\" +
@"\" + emplNumber + ".gce";

if (File.Exists(strPath))
{
Console.Write("\nEither the employee has already been
hired, ");
Console.WriteLine("or there is already another " +
"employee with that number.");
return;
}
else // If no employee with that number was found, create it
{
try
{
// If there is not yet a directory
// named Employees, then create it
Directory.CreateDirectory(@"C:\Georgetown Cleaning "
+
"Services\\Employees");
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("The folder could not be created");
}

try
{
fsEmployee = File.Create(strPath);
bwEmployee = new BinaryWriter(fsEmployee);
Console.Write("Enter Employee First Name: ");
string emplFName = Console.ReadLine();
Console.Write("Enter Employee Last Name: ");
string emplLName = Console.ReadLine();
Console.Write("Enter Hourly Salary: ");
double emplSalary = double.Parse(Console.ReadLine());

// The minimum salary in this company is 7.50


if (emplSalary < 7.50D)
emplSalary = 7.50D;

bwEmployee.Write(emplNumber);
bwEmployee.Write(emplFName);
bwEmployee.Write(emplLName);
bwEmployee.Write(emplSalary);
}
finally
{
C# 3.0 Practical Learning 910
bwEmployee.Close();
fsEmployee.Close();
}
}

Console.WriteLine();
}
}
}

7. Access the Program.cs file and change it as follows:


 
using System;

namespace GeorgetownCleaningServices7
{
public static class Program
{
static int Main(string[] args)
{
var answer = '0';

do
{
try
{
Console.WriteLine("What do you want to do?");
Console.WriteLine("0. Quit");
Console.WriteLine("1. Hire a new employee");
Console.WriteLine("2. Process a payroll");
Console.Write("Your Choice: ");
answer = char.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Invalid Answer!");
}

switch (answer)
{
case '1':
BusinessManagement.HireEmployee();
break;

case '2':
break;

default:
break;
}

} while (answer == '1' || answer == '2');

Console.WriteLine();
return 0;
}
}
}

C# 3.0 Practical Learning 911


8. Execute the application and test it. Here is an example:
 
What do you want to do?
0. Quit
1. Hire a new employee
2. Process a payroll
Your Choice: 1
Enter Employee Number (00-000): 86-025
Enter Employee First Name: Anne
Enter Employee Last Name: Harang
Enter Hourly Salary: 6.75

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
Your Choice: 1
Enter Employee Number (00-000): 42-713
Enter Employee First Name: Peter
Enter Employee Last Name: Lansome
Enter Hourly Salary: 12.45

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
Your Choice: 1
Enter Employee Number (00-000): 29-368
Enter Employee First Name: Gertrude
Enter Employee Last Name: Monay
Enter Hourly Salary: 10.85

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
Your Choice: 0

Press any key to continue . . .

9. Close the DOS window

Serialization

Binary serialization works by processing an object rather than streaming its individual
member variables. This means that, to use it, you define an object and initialize it, or
"fill" it, with the necessary values and any information you judge necessary. This creates
a "state" of the object. It is this state that you prepare to serialize. When you save the
object, it is converted into a stream.

To perform binary serialization, there are a few steps you must follow. When creating
the class whose objects would be serialized, start it with the [Serializable] attribute.
Here is an example:
[Serializable]
public class Car
{
C# 3.0 Practical Learning 912
public string Make;
public string Model;
public uint Year;
public byte Color;
}

Before serializing an object, you should reference the


System.Runtime.Serialization.Formatters.Binary namespace. The class
responsible for binary serialization is called BinaryFormatter. This class is equipped
with two constructors. The default constructor is used to simply create an object. After
declaring the variable, to actually serialize an object, call the Serialize() method of
the BinaryFormatter class. The method is overloaded with two versions. One of the
versions of this method uses the following syntax:
public void Serialize(Stream serializationStream, object graph);

The first argument to this method must be an object of a Stream-based class. In the
previous lessons, we saw how to create Stream objects (for example using the
FileStream class).

The second argument must be the object to serialize. This means that, before calling
this method, you should have built the object.

Here is an example:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Car
{
public string Make;
public string Model;
public uint Year;
public byte Color;
}

public class Exercise


{
static int Main(string[] args)
{
var vehicle = new Car();

vehicle.Make = "Lexus";
vehicle.Model = "LS";
vehicle.Year = 2007;
vehicle.Color = 4;

var stmCar = new FileStream("Car3.car", FileMode.Create);


var bfmCar = new BinaryFormatter();

bfmCar.Serialize(stmCar, vehicle);

return 0;
}
}

C# 3.0 Practical Learning 913


Practical Learning: Serializing an Object

1. To create a new class, in the Class View, right-click GeorgetownCleaningServices7


-> Add -> Class...

2. Set the Name to PayrollInformation and click OK

3. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices7
{
[Serializable]
public class PayrollInformation
{
private string number;
private string fname;
private string lname;
private double salary;
private DateTime start;

public string EmployeeNumber


{
get { return this.number; }
set { this.number = value; }
}

public string FirstName


{
get { return this.fname; }
set { this.fname = value; }
}

public string LastName


{
get { return this.lname; }
set { this.lname = value; }
}

public double HourlySalary


{
get { return this.salary; }
set { this.salary = value; }
}

public DateTime StartPeriod


{
get { return this.start; }
set { this.start = value; }
}

public DateTime EndPeriod


{

C# 3.0 Practical Learning 914


get { return start.AddDays(13D); }
}

public double Week1Monday;


public double Week1Tuesday;
public double Week1Wednesday;
public double Week1Thursday;
public double Week1Friday;
public double Week2Monday;
public double Week2Tuesday;
public double Week2Wednesday;
public double Week2Thursday;
public double Week2Friday;

public double RegularHours;


public double OvertimeHours;
public double RegularAmount;
public double OvertimeAmount;

public double TotalEarnings;


}
}

4. Access the BusinessManagement.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace GeorgetownCleaningServices7
{
public static class BusinessManagement
{
public static void HireEmployee()
{
FileStream fsEmployee = null;
BinaryWriter bwEmployee = null;

// Ask the clerk to enter an employee number


// using the format 00-000
Console.Write("Enter Employee Number (00-000): ");
string emplNumber = Console.ReadLine();

string strPath = @"C:\Georgetown Cleaning " +


@"Services\Employees\" +
@"\" + emplNumber + ".gce";

if (File.Exists(strPath))
{
Console.Write("\nEither the employee has " +
"already been hired, ");
Console.WriteLine("or there is already another " +
"employee with that number.");
return;
}
// If no employee with that number
C# 3.0 Practical Learning 915
// was found, create it
else
{
try
{
// If there is not yet a directory named
// Employees, then create it
Directory.CreateDirectory(@"C:\Georgetown " +
@"Cleaning Services\Employees");
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("The folder could " +
"not be created");
}

try
{
fsEmployee = File.Create(strPath);
bwEmployee = new BinaryWriter(fsEmployee);

Console.Write("Enter Employee First Name: ");


string emplFName = Console.ReadLine();
Console.Write("Enter Employee Last Name: ");
string emplLName = Console.ReadLine();
Console.Write("Enter Hourly Salary: ");
double emplSalary =
double.Parse(Console.ReadLine());

// The minimum salary in this company is 7.50


if (emplSalary < 7.50D)
emplSalary = 7.50D;

bwEmployee.Write(emplNumber);
bwEmployee.Write(emplFName);
bwEmployee.Write(emplLName);
bwEmployee.Write(emplSalary);
}
finally
{
bwEmployee.Close();
fsEmployee.Close();
}
}

Console.WriteLine();
}

public static void CreatePayroll()


{
FileStream fsPayroll = null;
BinaryReader brPayroll = null;
DateTime dteStartDate;

PayrollInformation payroll =
new PayrollInformation();

double monday1 = 0.00D, tuesday1 = 0.00D,


wednesday1 = 0.00D, thursday1 = 0.00D,
friday1 = 0.00D, monday2 = 0.00D,
C# 3.0 Practical Learning 916
tuesday2 = 0.00D, wednesday2 = 0.00D,
thursday2 = 0.00D, friday2 = 0.00D;
double totalHoursWeek1 = 0.00D,
totalHoursWeek2 = 0.00D;

double regHours1 = 0.00D, regHours2 = 0.00D,


ovtHours1 = 0.00, ovtHours2 = 0.00;
double regAmount1 = 0.00D, regAmount2 = 0.00D,
ovtAmount1 = 0.00D, ovtAmount2 = 0.00D;
double regularHours = 0.00D, overtimeHours = 0.00D;
double regularAmount = 0.00D,
overtimeAmount = 0.00D,
totalEarnings = 0.00D;

Console.Write("Enter Employee Number: ");


string emplNumber = Console.ReadLine();

string strEmployeePath = @"C:\Georgetown " +


@"Cleaning Services\Employees\" +
@"\" + emplNumber + ".gce";

if (!File.Exists(strEmployeePath))
{
Console.WriteLine("There is no employee with " +
"that number in our records");
return;
}
// If an employee with that number was found,
// continue with the payroll
else {
try
{
fsPayroll = new FileStream(strEmployeePath,
FileMode.Open,
FileAccess.Read);
brPayroll = new BinaryReader(fsPayroll);

payroll.EmployeeNumber = brPayroll.ReadString();
payroll.FirstName = brPayroll.ReadString();
payroll.LastName = brPayroll.ReadString();
payroll.HourlySalary = brPayroll.ReadDouble();

Console.WriteLine("\n------------------------" +
"------------------------");
Console.WriteLine("Employee #: {0}",
payroll.EmployeeNumber);
Console.WriteLine("Full Name: {0}, {1}",
payroll.FirstName,
payroll.LastName);
Console.WriteLine("Hourly Salary: {0:C}",
payroll.HourlySalary);
Console.WriteLine("-------------------------" +
"-----------------------\n");
}
finally
{
brPayroll.Close();
fsPayroll.Close();
}

C# 3.0 Practical Learning 917


try
{
do
{
Console.Write("Enter Payroll Start " +
"Date (mm/dd/yyyy): ");
dteStartDate =
DateTime.Parse(Console.ReadLine());
if (dteStartDate.DayOfWeek !=
DayOfWeek.Sunday)
{
Console.WriteLine("Invalid Date Entry");
Console.WriteLine("Payrolls start " +
"on a Sunday");
}
} while (dteStartDate.DayOfWeek !=
DayOfWeek.Sunday);

payroll.StartPeriod = dteStartDate;
}
catch (FormatException)
{
Console.WriteLine("Invalid Date Entry");
}
}

// Retrieve the value of each day worked


Console.WriteLine("\nEnter the time worked " +
"for each day (0.00)");
Console.WriteLine("=-= Week 1 =-=");
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(1).ToString("D"));
monday1 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(2).ToString("D"));
tuesday1 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(3).ToString("D"));
wednesday1 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
C# 3.0 Practical Learning 918
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(4).ToString("D"));
thursday1 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(5).ToString("D"));
friday1 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}

Console.WriteLine("=-= Week 2 =-=");


try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(8).ToString("D"));
monday2 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(9).ToString("D"));
tuesday2 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(10).ToString("D"));
wednesday2 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(11).ToString("D"));
thursday2 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
C# 3.0 Practical Learning 919
Console.WriteLine("You typed an invalid value");
}
try
{
Console.Write("{0}: ",
payroll.StartPeriod.AddDays(12).ToString("D"));
friday2 = double.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("You typed an invalid value");
}

// Calculate the total number of hours for each week


totalHoursWeek1 = monday1 + tuesday1 + wednesday1 +
thursday1 + friday1;
totalHoursWeek2 = monday2 + tuesday2 + wednesday2 +
thursday2 + friday2;

// The overtime is paid time and half


double ovtSalary = payroll.HourlySalary * 1.5D;

// If the employee worked under 40 hours,


// there is no overtime
if (totalHoursWeek1 < 40)
{
regHours1 = totalHoursWeek1;
regAmount1 = payroll.HourlySalary * regHours1;
ovtHours1 = 0.00D;
ovtAmount1 = 0.00D;
} // If the employee worked over 40 hours,
// calculate the overtime
else if (totalHoursWeek1 >= 40)
{
regHours1 = 40;
regAmount1 = payroll.HourlySalary * 40;
ovtHours1 = totalHoursWeek1 - 40;
ovtAmount1 = ovtHours1 * ovtSalary;
}

if (totalHoursWeek2 < 40)


{
regHours2 = totalHoursWeek2;
regAmount2 = payroll.HourlySalary * regHours2;
ovtHours2 = 0.00D;
ovtAmount2 = 0.00D;
}
else if (totalHoursWeek2 >= 40)
{
regHours2 = 40;
regAmount2 = payroll.HourlySalary * 40;
ovtHours2 = totalHoursWeek2 - 40;
ovtAmount2 = ovtHours2 * ovtSalary;
}

regularHours = regHours1 + regHours2;


overtimeHours = ovtHours1 + ovtHours2;
regularAmount = regAmount1 + regAmount2;
overtimeAmount = ovtAmount1 + ovtAmount2;
totalEarnings = regularAmount + overtimeAmount;
C# 3.0 Practical Learning 920
payroll.Week1Monday = monday1;
payroll.Week1Tuesday = tuesday1;
payroll.Week1Wednesday = wednesday1;
payroll.Week1Thursday = thursday1;
payroll.Week1Friday = friday1;

payroll.Week2Monday = monday2;
payroll.Week2Tuesday = tuesday2;
payroll.Week2Wednesday = wednesday2;
payroll.Week2Thursday = thursday2;
payroll.Week2Friday = friday2;

payroll.RegularHours = regularHours;
payroll.OvertimeHours = overtimeHours;
payroll.RegularAmount = regularAmount;
payroll.OvertimeAmount = overtimeAmount;
payroll.TotalEarnings = totalEarnings;

ShowPayroll(payroll);

Console.Write("Do you want to save " +


"the payroll (y/n): ");
string strAnswer = Console.ReadLine();

if (strAnswer.ToUpper() == "Y")
SavePayroll(payroll);
}

public static void SavePayroll(PayrollInformation pay)


{
// We will need this value to create the
// name of the payroll file
string strMonth = "0", strDay = "0", strYear = "0";

// We want the month and day to include 0 if necessary


strMonth = pay.StartPeriod.Month.ToString();
if (pay.StartPeriod.Month < 10)
strMonth = "0" + pay.StartPeriod.Month.ToString();
strDay = pay.StartPeriod.Day.ToString();
if (pay.StartPeriod.Day < 10)
strDay = "0" + pay.StartPeriod.Day.ToString();
strYear = pay.StartPeriod.Year.ToString();

string strPayrollFilename = @"C:\Georgetown " +


@"Cleaning Services\Payrolls\" +
@"\" + pay.LastName[0] +
pay.FirstName[0] +
strMonth + strDay +
strYear + ".epr";
try
{
// If there is not yet a directory for the
// payrolls, then create it
Directory.CreateDirectory(@"C:\Georgetown Cleaning " +
@"Services\Payrolls");
}
catch (DirectoryNotFoundException)
{
Console.WriteLine("The employee payroll file " +
C# 3.0 Practical Learning 921
"could not be created");
}

if (File.Exists(strPayrollFilename))
{
Console.WriteLine("The employee's payroll " +
"for that period exists already");
}

FileStream fsEmployeePayroll =
new FileStream(strPayrollFilename,
FileMode.Create);
BinaryFormatter bfEmployeePayroll =
new BinaryFormatter();

bfEmployeePayroll.Serialize(fsEmployeePayroll, pay);
fsEmployeePayroll.Close();
}

public static void ViewPayroll()


{

public static void ShowPayroll(PayrollInformation payed)


{
Console.WriteLine("\n=============================" +
"===================");
Console.WriteLine("=$= Payroll summary =$=");
Console.WriteLine("-------------------------------" +
"-----------------");
Console.WriteLine("Employee #: {0}",
payed.EmployeeNumber);
Console.WriteLine("Full Name: {0}, {1}",
payed.FirstName, payed.LastName);
Console.WriteLine("Hourly Salary: {0:C}",
payed.HourlySalary);
Console.WriteLine("Start Period: {0:D}",
payed.StartPeriod);
Console.WriteLine("End Period: {0:D}",
payed.EndPeriod);
Console.WriteLine("--------------------------------" +
"----------------");
Console.WriteLine(" Monday Tuesday Wednesday " +
"Thursday Friday");
Console.WriteLine("Week 1: {0:F} {1:F} " +
"{2:F} {3:F} {4:F}",
payed.Week1Monday, payed.Week1Tuesday,
payed.Week1Wednesday, payed.Week1Thursday,
payed.Week1Friday);
Console.WriteLine("Week 2: {0:F} {1:F} " +
"{2:F} {3:F} {4:F}",
payed.Week2Monday, payed.Week2Tuesday,
payed.Week2Wednesday, payed.Week2Thursday,
payed.Week2Friday);
Console.WriteLine("-------------------------------" +
"-----------------");
Console.WriteLine("Monetary Summary");
Console.WriteLine(" Hours Amount");
Console.WriteLine("Regular: {0,6} {1,6}",
C# 3.0 Practical Learning 922
payed.RegularHours.ToString("F"),
payed.RegularAmount.ToString("F"));
Console.WriteLine("Overtime: {0,6} {1,6}",
payed.OvertimeHours.ToString("F"),
payed.OvertimeAmount.ToString("F"));
Console.WriteLine("-------------------------------" +
"-----------------");
Console.WriteLine("Net Pay: {0:F}",
payed.TotalEarnings);
Console.WriteLine("===============================" +
"=================\n");
}
}
}

5. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GeorgetownCleaningServices7
{
public static class Program
{
static int Main(string[] args)
{
var answer = '0';

Console.WriteLine("========================" +
"========================");
Console.WriteLine("Georgetown Cleaning Services");
Console.WriteLine("========================" +
"========================");

do
{
try
{
Console.WriteLine("\nWhat do you want to do?");
Console.WriteLine("0. Quit");
Console.WriteLine("1. Hire a new employee");
Console.WriteLine("2. Process a payroll");
Console.WriteLine("3. View an employee's payroll");
Console.Write("Your Choice: ");
answer = char.Parse(Console.ReadLine());
Console.WriteLine();
}
catch (FormatException)
{
Console.WriteLine("Invalid Answer!");
}

switch (answer)
{
case '1':
BusinessManagement.HireEmployee();
break;
C# 3.0 Practical Learning 923
case '2':
BusinessManagement.CreatePayroll();
break;
case '3':
BusinessManagement.ViewPayroll();
break;
default:
break;
}

} while( (answer == '1') ||


(answer == '2') ||
(answer == '3') );

return 0;
}
}
}

6. Execute the application and test it. Here is an example:


 
================================================
Georgetown Cleaning Services
================================================

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 2

Enter Employee Number: 29-368

------------------------------------------------
Employee #: 29-368
Full Name: Gertrude, Monay
Hourly Salary: $10.85
------------------------------------------------

Enter Payroll Start Date (mm/dd/yyyy): 11/12/05


Invalid Date Entry
Payrolls start on a Sunday
Enter Payroll Start Date (mm/dd/yyyy): 11/12/06

Enter the time worked for each day (0.00)


=-= Week 1 =-=
Monday, November 13, 2006: 8.00
Tuesday, November 14, 2006: 8.50
Wednesday, November 15, 2006: 9.50
Thursday, November 16, 2006: 8
Friday, November 17, 2006: 8.50
=-= Week 2 =-=
Monday, November 20, 2006: 6.50
Tuesday, November 21, 2006: 7.00
Wednesday, November 22, 2006: 8
Thursday, November 23, 2006: 6.00
Friday, November 24, 2006: 7.00

C# 3.0 Practical Learning 924


================================================
=$= Payroll summary =$=
------------------------------------------------
Employee #: 29-368
Full Name: Gertrude, Monay
Hourly Salary: $10.85
Start Period: Sunday, November 12, 2006
End Period: Saturday, November 25, 2006
------------------------------------------------
Monday Tuesday Wednesday Thursday Friday
Week 1: 8.00 8.50 9.50 8.00 8.50
Week 2: 6.50 7.00 8.00 6.00 7.00
------------------------------------------------
Monetary Summary
Hours Amount
Regular: 74.50 808.33
Overtime: 2.50 40.69
------------------------------------------------
Net Pay: 849.01
================================================

Do you want to save the payroll (y/n): Y

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 0

Press any key to continue . . .

7. Close the DOS window

8. Execute the application again and process another payroll. Here is an example:
 
================================================
Georgetown Cleaning Services
================================================

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 2

Enter Employee Number: 86-025

------------------------------------------------
Employee #: 86-025
Full Name: Anne, Harang
Hourly Salary: $7.50
------------------------------------------------

Enter Payroll Start Date (mm/dd/yyyy): 11/26/2006

Enter the time worked for each day (0.00)


=-= Week 1 =-=
C# 3.0 Practical Learning 925
Monday, November 27, 2006: 8.00
Tuesday, November 28, 2006: 6.50
Wednesday, November 29, 2006: 8.50
Thursday, November 30, 2006: 8.00
Friday, December 01, 2006: 8.00
=-= Week 2 =-=
Monday, December 04, 2006: 9.00
Tuesday, December 05, 2006: 8.50
Wednesday, December 06, 2006: 8.00
Thursday, December 07, 2006: 9.50
Friday, December 08, 2006: 8.00

================================================
=$= Payroll summary =$=
------------------------------------------------
Employee #: 86-025
Full Name: Anne, Harang
Hourly Salary: $7.50
Start Period: Sunday, November 26, 2006
End Period: Saturday, December 09, 2006
------------------------------------------------
Monday Tuesday Wednesday Thursday Friday
Week 1: 8.00 6.50 8.50 8.00 8.00
Week 2: 9.00 8.50 8.00 9.50 8.00
------------------------------------------------
Monetary Summary
Hours Amount
Regular: 79.00 592.50
Overtime: 3.00 33.75
------------------------------------------------
Net Pay: 626.25
================================================

Do you want to save the payroll (y/n): y

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 0

Press any key to continue . . .

9. Close the DOS window

De-Serialization

As serialization is the process of storing an object to a medium, the opposite,


serialization is used to retrieve an object from a stream. To support this, the
BinaryFormatter class is equipped with the Deserialize() method. Like
Serialize(), the Deserialize() method is overloaded with two versions. One of
them uses the following syntax:
public object Deserialize(Stream serializationStream);

This method takes as argument a Stream-based object, such as a FileStream variable,


that indicates where the file is located. The Deserialize() method returns an Object
C# 3.0 Practical Learning 926
object. As a goal, you want the Deserialize() method to produce the type of object
that was saved so you can retrieve the values that the returned object holds. Because
the method returns an Object value, you must cast the returned value to the type of
your class.

Once the Deserialize() method has returned the desired object, you can access its
values. Here is an example:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Car
{
public string Make;
public string Model;
public uint Year;
public byte Color;
}

class Program
{
static int Main(string[] args)
{
var stmCar = new FileStream("Car3.car", FileMode.Open);
var bfmCar = new BinaryFormatter();
var vehicle = (Car)bfmCar.Deserialize(stmCar);

Console.WriteLine("Make: {0}", vehicle.Make);


Console.WriteLine("Model: {0}", vehicle.Model);
Console.WriteLine("Year: {0}", vehicle.Year);
Console.Write("Color: ");
byte clr = vehicle.Color;

switch (clr)
{
case 1:
Console.WriteLine("Black");
break;
case 2:
Console.WriteLine("Gray");
break;
case 3:
Console.WriteLine("White");
break;
case 4:
Console.WriteLine("Red");
break;
case 5:
Console.WriteLine("Blue");
break;
}

stmCar.Close();

return 0;
}
}
C# 3.0 Practical Learning 927
Practical Learning: De-Serializing an Object

1. Access the BusinessManagement.cs file and implement the ViewPayroll() method as


follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace GeorgetownCleaningServices7
{
public static class BusinessManagement
{
public static void HireEmployee()
{
. . . No Change
}

public static void CreatePayroll()


{
. . . No Change
}

public static void SavePayroll(PayrollInformation pay)


{
. . . No Change
}

public static void ViewPayroll()


{
string strEmplNumber, strFName, strLName;
string strMonth, strDay, strYear;

// Ask the clerk to enter an employee number


// using the format 00-000
Console.Write("Enter Employee Number (00-000): ");
strEmplNumber = Console.ReadLine();

string strFilename = @"C:\Georgetown Cleaning " +


@"Services\Employees\" +
@"\" + strEmplNumber + ".gce";

if (!File.Exists(strFilename))
{
Console.Write("There is no employee " +
"with that number.");
}
else
{
FileStream fsEmployee = null;
BinaryReader brEmployee = null;

try
{

C# 3.0 Practical Learning 928


// We need to formally open the file
// because we need the employees initials
fsEmployee = new FileStream(strFilename,
FileMode.Open,
FileAccess.Read);
brEmployee = new BinaryReader(fsEmployee);

// Read the file, mainly to get the


// employee's name
strEmplNumber = brEmployee.ReadString();
strFName = brEmployee.ReadString();
strLName = brEmployee.ReadString();
}
finally
{
brEmployee.Close();
fsEmployee.Close();
}

Console.Write("Enter the start date of the " +


"payroll you want to see (mm/dd/yyyy): ");
DateTime dteStartDate =
DateTime.Parse(Console.ReadLine());

// We want the month and day to include 0 if necessary


strMonth = dteStartDate.Month.ToString();
if (dteStartDate.Month < 10)
strMonth = "0" + dteStartDate.Month.ToString();
strDay = dteStartDate.Day.ToString();
if (dteStartDate.Day < 10)
strDay = "0" + dteStartDate.Day.ToString();
strYear = dteStartDate.Year.ToString();

strFilename = @"C:\Georgetown Cleaning " +


@"Services\Payrolls\" +
@"\" + strLName[0] +
strFName[0] + strMonth +
strDay + strYear + ".epr";
if (!File.Exists(strFilename))
{
Console.Write("{0}, {1} doesn't have a " +
"payroll in that time frame",
strLName, strFName);
}
else
{
// Open the payroll and display it
FileStream fsPayroll =
new FileStream(strFilename,
FileMode.Open);
BinaryFormatter bfPayroll =
new BinaryFormatter();
PayrollInformation pay =

(PayrollInformation)bfPayroll.Deserialize(fsPayroll);

ShowPayroll(pay);
}
}
}
C# 3.0 Practical Learning 929
public static void ShowPayroll(PayrollInformation payed)
{
. . . No Change
}
}
}

2. Execute the application and test it. Here is an example:


 
================================================
Georgetown Cleaning Services
================================================

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 3

Enter Employee Number (00-000): 29-368


Enter the start date of the payroll you want to see (mm/dd/yyyy):
11/12/2006

================================================
=$= Payroll summary =$=
------------------------------------------------
Employee #: 29-368
Full Name: Gertrude, Monay
Hourly Salary: $10.85
Start Period: Sunday, November 12, 2006
End Period: Saturday, November 25, 2006
------------------------------------------------
Monday Tuesday Wednesday Thursday Friday
Week 1: 8.00 8.50 9.50 8.00 8.50
Week 2: 6.50 7.00 8.00 6.00 7.00
------------------------------------------------
Monetary Summary
Hours Amount
Regular: 74.50 808.33
Overtime: 2.50 40.69
------------------------------------------------
Net Pay: 849.01
================================================

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 3

Enter Employee Number (00-000): 86-025


Enter the start date of the payroll you want to see (mm/dd/yyyy):
11/26/06

================================================
C# 3.0 Practical Learning 930
=$= Payroll summary =$=
------------------------------------------------
Employee #: 86-025
Full Name: Anne, Harang
Hourly Salary: $7.50
Start Period: Sunday, November 26, 2006
End Period: Saturday, December 09, 2006
------------------------------------------------
Monday Tuesday Wednesday Thursday Friday
Week 1: 8.00 6.50 8.50 8.00 8.00
Week 2: 9.00 8.50 8.00 9.50 8.00
------------------------------------------------
Monetary Summary
Hours Amount
Regular: 79.00 592.50
Overtime: 3.00 33.75
------------------------------------------------
Net Pay: 626.25
================================================

What do you want to do?


0. Quit
1. Hire a new employee
2. Process a payroll
3. View an employee's payroll
Your Choice: 0

Press any key to continue . . .

3. Close the DOS window

SOAP Serialization
 

Introduction

The .NET Framework supports another technique of serialization referred to as SOAP


(which stands for Simple Object Access Protocol). This technique is related to XML but,
although we haven't studied XML, you don't need to know anything about it to use SOAP
serialization.

Practical Learning: Introducing SOAP Serialization

1. Start a new Console Application named PropertyRental1

2. To create a new class, on the main menu, click Project -> Add Class

3. Set the Name to Property and press Enter

4. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;

C# 3.0 Practical Learning 931


using System.Text;

namespace PropertyRental1
{
public enum TypeOfProperty
{
Appartment,
SingleFamily,
Townhouse,
Unknown
}

public enum Condition


{
Excellent,
Good,
NeedsRepair,
Unknown
}

[Serializable]
public class Property
{
private long propCode;
private TypeOfProperty tp;
private Condition cond;
private short beds;
private float baths;
private int levels;
private decimal val;

public long PropertyCode


{
get { return propCode; }
set { propCode = value; }
}

public TypeOfProperty PropertyType


{
get { return tp; }
set { tp = value; }
}

public Condition PropertyCondition


{
get { return cond; }
set { cond = value; }
}

public short Bedrooms


{
get { return beds; }
set { beds = value; }
}

public float Bathrooms


{
get { return (baths <= 0) ? 0.00f : baths; }
set { baths = value; }
}
C# 3.0 Practical Learning 932
public int Stories
{
get { return levels; }
set { levels = value; }
}

public decimal MonthlyRent


{
get { return (val <= 0) ? 0.00M : val; }
set { val = value; }
}

public Property()
{
Random rnd = new Random();
propCode = rnd.Next(100000, 999999);
tp = TypeOfProperty.Unknown;
cond = Condition.Unknown;
beds = 0;
baths = 0.0f;
levels = 0;
val = 0.00M;
}
}
}

5. To create a new class, on the main menu, click Project -> Add Class

6. Set the Name to PropertyListing and press Enter

7. Change the file as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PropertyRental1
{
[Serializable]
public class PropertyListing
{
private Property[] prop = new Property[100];

public Property this[int i]


{
get { return prop[i]; }
set { prop[i] = value; }
}
}
}

8. Save all

Serialization With SOAP

C# 3.0 Practical Learning 933


To serialize an object using SOAP, you follow the same steps we reviewed for the binary
serialization with one addition that you must add a certain reference.

When creating the class whose objects would be serialized, mark it with the
[Serializable] attribute. Here is an example:

[Serializable]
public class Car
{
public string Make;
public string Model;
public uint Year;
public byte Color;
}

To support SOAP serialization, the .NET Framework provides the SoapFormatter class.
This class is defined in the System.Runtime.Serialization.Formatters. Soap
namespace that is part of the System.Runtime.Serialization.Formatters.
Soap.dll assembly. In order to use The SoapFormatter class, you must reference this
assembly. Then, you can create an object and initialize it as you see fit. Before saving it,
as always, create a Stream-based object that would indicate the name (and location) of
the file and the type of action to perform. Then, declare a SoapFormatter variable
using its default constructor. To actually save the object, call the Serialize() method
of this class. This method uses the same syntax as that of the BinaryFormatter class:
it takes two arguments. The first is a Stream-based object. The second is the object that
needs to be serialized.

Here is an example:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;

[Serializable]
public class Car
{
public string Make;
public string Model;
public uint Year;
public byte Color;
}

public static class Program


{
public static int Main(string[] args)
{
var vehicle = new Car();

vehicle.Make = "Volvo";
vehicle.Model = "S40";
vehicle.Year = 2006;
vehicle.Color = 3;

var stmCar =
new FileStream("Car4.car",
FileMode.Create);
var sopCar = new SoapFormatter();

C# 3.0 Practical Learning 934


sopCar.Serialize(stmCar, vehicle);
return 0;
}
}

Practical Learning: Serializing With SOAP

1. To add SOAP support to your project, on the main menu, click Project -> Add
Reference...

2. In the Add Reference dialog box and in the .NET tab, scroll down and select
System.Runtime.Serialization.Formatters.Soap:

3. Click OK

4. Access the Program.cs file and change it as follows:


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;

namespace PropertyRental1
{
class Program
{
static PropertyListing CreateListing()
{
Random rnd = new Random();
Property prop = new Property();
PropertyListing listing = new PropertyListing();

C# 3.0 Practical Learning 935


prop = new Property();

// Create a few properties ready to be rented


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.SingleFamily;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 5;
prop.Bathrooms = 3.5f;
prop.Stories = 3;
prop.MonthlyRent = 2650;
listing[0] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.Townhouse;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 3;
prop.Bathrooms = 2.5f;
prop.Stories = 3;
prop.MonthlyRent = 1750;
listing[1] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.SingleFamily;
prop.PropertyCondition = Condition.Good;
prop.Bedrooms = 4;
prop.Bathrooms = 2.5f;
prop.Stories = 2;
prop.MonthlyRent = 2450;
listing[2] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.Appartment;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 1;
prop.Bathrooms = 1.0f;
prop.Stories = 1;
prop.MonthlyRent = 880;
listing[3] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.Townhouse;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 3;
prop.Bathrooms = 2.5f;
prop.Stories = 2;
prop.MonthlyRent = 1880;
listing[4] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.Appartment;
prop.PropertyCondition = Condition.Good;
prop.Bedrooms = 2;
prop.Bathrooms = 1.0f;
prop.Stories = 1;
C# 3.0 Practical Learning 936
prop.MonthlyRent = 1050;
listing[5] = prop;

// Since we don't yet have a complete list of properties


// Create some empty ones
for (int i = 5; i < 100; i++)
{
prop = new Property();

listing[i] = prop;
}
return listing;
}

static int Main()


{
PropertyListing props = CreateListing();
Property prop = new Property();

FileStream prpStream =
new FileStream("properties.rnt",
FileMode.Create);
SoapFormatter prpSoap = new SoapFormatter();

prpSoap.Serialize(prpStream, props);

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


{
prop = props[i];

Console.WriteLine("{0}.----------------------------------", i + 1);
Console.WriteLine("Property #: {0}",
prop.PropertyCode);
Console.WriteLine("Type: {0}",
prop.PropertyType);
Console.WriteLine("Condition: {0}",
prop.PropertyCondition);
Console.WriteLine("Bedrooms: {0}", prop.Bedrooms);
Console.WriteLine("Bathrooms: {0}", prop.Bathrooms);
Console.WriteLine("Stories: {0}", prop.Stories);
Console.WriteLine("Market Value: {0}\n",
prop.MonthlyRent);
}
Console.WriteLine("======================================");

return 0;
}
}
}

5. Press Ctrl + F5 to execute the application

De-Serialization With SOAP

De-serialization in soap is performed exactly as done for the binary de-serialization. To


support it, the SoapFormatter class is equipped with the Deserialize() method. This
method uses the same syntax as its equivalent of the BinaryFormatter class. The
approach to use it is also the same.
C# 3.0 Practical Learning 937
Here is an example:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;

[Serializable]
public class Car
{
public string Make;
public string Model;
public uint Year;
public byte Color;
}

public static class Program


{
public static int Main(string[] args)
{
var stmCar = new FileStream("Car4.car", FileMode.Open);
var sopCar = new SoapFormatter();
var vehicle = (Car)sopCar.Deserialize(stmCar);

Console.WriteLine("Car Information");
Console.WriteLine("Make: {0}", vehicle.Make );
Console.WriteLine("Model: {0}", vehicle.Model);
Console.WriteLine("Year: {0}", vehicle.Year);
Console.Write("Color: ");
switch (vehicle.Color)
{
case 1:
Console.WriteLine("Black");
break;
case 2:
Console.WriteLine("Gray");
break;
case 3:
Console.WriteLine("White");
break;
case 4:
Console.WriteLine("Red");
break;
case 5:
Console.WriteLine("Blue");
break;
}
return 0;
}
}

Practical Learning: Deserializing With SOAP

1. To deserialize, change the contents of the Program.cs file as follows:


 
using System;
using System.Collections.Generic;
C# 3.0 Practical Learning 938
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;

namespace PropertyRental1
{
class Program
{
static int Main()
{
Property prop = new Property();

// Open the list/collection of properties


FileStream prpStream =
new FileStream("properties.rnt",
FileMode.Open);
SoapFormatter prpSoap = new SoapFormatter();
PropertyListing props =
(PropertyListing)prpSoap.Deserialize(prpStream);
prpStream.Close();

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


{
prop = props[i];
Console.WriteLine("{0}.----------------------------------", i +
1);
Console.WriteLine("Property #: {0}",
prop.PropertyCode);
Console.WriteLine("Type: {0}",
prop.PropertyType);
Console.WriteLine("Condition: {0}", prop.PropertyCondition);
Console.WriteLine("Bedrooms: {0}", prop.Bedrooms);
Console.WriteLine("Bathrooms: {0}", prop.Bathrooms);
Console.WriteLine("Stories: {0}", prop.Stories);
Console.WriteLine("Market Value: {0}\n",
prop.MonthlyRent);
}
Console.WriteLine("======================================");

return 0;
}
}
}

2. Press Ctrl + F5 to execute the application

3. After viewing the result, close the DOS window

4. To apply an example of updating the file, change the contents of the Program.cs
file as follows:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;

C# 3.0 Practical Learning 939


namespace PropertyRental1
{
class Program
{
static int Main()
{
Property prop = new Property();

// Open the list/collection of properties


FileStream prpStream =
new FileStream("properties.rnt",
FileMode.Open);
SoapFormatter prpSoap = new SoapFormatter();
// Get the list of properties and store it in an array
PropertyListing props =
(PropertyListing)prpSoap.Deserialize(prpStream);
// Close the stream while we are working on something else
prpStream.Close();

// To add a few properties, we will actually replace


// some "empty" properties whose placeholders we defined
earlier
Random rnd = new Random();
prop = new Property();
prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.Appartment;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 2;
prop.Bathrooms = 2.0f;
prop.Stories = 1;
prop.MonthlyRent = 1240;
props[7] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.SingleFamily;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 3;
prop.Bathrooms = 2.5f;
prop.Stories = 3;
prop.MonthlyRent = 1750;
props[8] = prop;

prop = new Property();


prop.PropertyCode = rnd.Next(100000, 999999);
prop.PropertyType = TypeOfProperty.SingleFamily;
prop.PropertyCondition = Condition.Good;
prop.Bedrooms = 5;
prop.Bathrooms = 3.5f;
prop.Stories = 3;
prop.MonthlyRent = 3475;
props[14] = prop;

prop = new Property();


prop.PropertyType = TypeOfProperty.Appartment;
prop.PropertyCondition = Condition.Excellent;
prop.Bedrooms = 2;
prop.Bathrooms = 1.0f;
prop.Stories = 1;
prop.MonthlyRent = 1275;
C# 3.0 Practical Learning 940
props[28] = prop;

// Reopen the stream


prpStream = new FileStream("properties.rnt",
FileMode.Create);
prpSoap = new SoapFormatter();

// Open the file and save it


prpSoap.Serialize(prpStream, props);
prpStream.Close();

// That's it

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


{
prop = props[i];
Console.WriteLine("{0}.----------------------------------", i +
1);
Console.WriteLine("Property #: {0}",
prop.PropertyCode);
Console.WriteLine("Type: {0}",
prop.PropertyType);
Console.WriteLine("Condition: {0}", prop.PropertyCondition);
Console.WriteLine("Bedrooms: {0}", prop.Bedrooms);
Console.WriteLine("Bathrooms: {0}", prop.Bathrooms);
Console.WriteLine("Stories: {0}", prop.Stories);
Console.WriteLine("Market Value: {0}\n",
prop.MonthlyRent);
}
Console.WriteLine("======================================");

return 0;
}
}
}

5. Press Ctrl + F5 to execute the application

Details on Serialization
 

Partial Serialization

In the examples we have used so far, we were saving the whole object. You can make it
possible to save only some parts of the class. When creating a class, you can specify
what fields would be serialized and which ones would not be. To specify that a member
cannot be saved, you can mark it with the [NonSerialized] attribute. Here is an
example:
[Serializable]
public class Car
{
public string Make;
public string Model;

// Because the value of a car can change,

C# 3.0 Practical Learning 941


// there is no reason to save it
[NonSerialized]
public decimal Value;
public uint Year;
public byte Color;
}

After creating the class, you can declare a variable of it and serialize it, using either the
binary or the SOAP approach. Here is an example:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Car
{
public string Make;
public string Model;

// Because the value of a car can change,


// there is no reason to save it
[NonSerialized]
public decimal Value;
public uint Year;
public byte Color;
}

public class Exercise


{
static int Main(string[] args)
{
var vehicle = new Car();

vehicle.Make = "Lexus";
vehicle.Model = "LS";
vehicle.Year = 2007;
vehicle.Color = 4;
vehicle.Value = 28640M;

var stmCar = new FileStream("Car1.car", FileMode.Create);


var bfmCar = new BinaryFormatter();

bfmCar.Serialize(stmCar, vehicle);

return 0;
}
}

You can then retrieve the object and its values, using any of the techniques we learned
earlier. Here is an example:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Car
{
C# 3.0 Practical Learning 942
public string Make;
public string Model;

// Because the value of a car can change,


// there is no reason to save it
[NonSerialized]
public decimal Value;
public uint Year;
public byte Color;
}

public class Exercise


{
static int Main(string[] args)
{
var stmCar = new FileStream("Car1.car", FileMode.Open);
var bfmCar = new BinaryFormatter();
var vehicle = (Car)bfmCar.Deserialize(stmCar);

Console.WriteLine("Car Information");
Console.WriteLine("Make: {0}", vehicle.Make);
Console.WriteLine("Model: {0}", vehicle.Model);
Console.WriteLine("Year: {0}", vehicle.Year);
Console.Write("Color: ");
switch (vehicle.Color)
{
case 1:
Console.WriteLine("Black");
break;
case 2:
Console.WriteLine("Gray");
break;
case 3:
Console.WriteLine("White");
break;
case 4:
Console.WriteLine("Red");
break;
case 5:
Console.WriteLine("Blue");
break;
}
Console.WriteLine("Value: {0}\n", vehicle.Value);

return 0;
}
}

This would produce:


Car Information
Make: Lexus
Model: LS
Year: 2007
Color: Red
Value: 0

Press any key to continue . . .

C# 3.0 Practical Learning 943


Notice that the value of the Value field was not saved: it holds the default value of its
data type. This indicates that, you can assign a value a [NonSerialized] field and save
the object. The value of that field would not be saved but the compiler would not throw
an exception.

Implementing a Custom Serialized Class

To support serialization, the .NET Framework provides the ISerializable interface.


You can create a class that implements this interface to customize the serialization
process. Even if you plan to use this interface, the class you create must be marked with
the [Serializable] attribute.

.NET Built-In Serialized Classes

The .NET Framework is filled with many classes ready for serialization. To know that a
class is ready for serialization, when viewing its documentation either in the MSDN web
site or in the help documentation, check that it is marked with the
[SerializableAttribute]. Here is an example of such as class:

C# 3.0 Practical Learning 944


Some of these classes provide the properties and methods to create an object and
directly save it. For some other classes, you must first create a class, mark it with the
[Serializable] attribute, build an object of it, and then pass it to the .NET class. 

C# 3.0 Practical Learning 945

You might also like