You are on page 1of 278

Basic C# Programming

BCSM-16
Basic C# Programming
BCSM-16
Compiled by: Kyle Brunette, Angelique Kolle, Lance Whyte, Cedric Maenetja,
Daniel Sansom and Tatenda Tagutanazvo

Updated by: Suhayl H. Asmal

Edited by: Norman Baines

Version 1.0

© August 2015 CTI Education Group


Table of Contents
Table of Contents .............................................................................. 2
Introduction to the C# Module .......................................................... 6
About this module ................................................................................................ 6
Resources ............................................................................................................. 6
How to approach this module ............................................................................... 7
Structure of a unit ................................................................................................ 8
Beginning a project .............................................................................................. 9
How projects are evaluated ................................................................................ 10
Assessment for pass ........................................................................................... 14
Symbols used in the study guide ........................................................................ 15
Unit 1 – An Introduction .................................................................. 16
1.1 Introduction to C# ..................................................................................... 17
1.1.1 What is C#?....................................................................................................................... 17
1.1.2 What is the .NET Framework? .............................................................................................. 17
1.1.3 Creating your first C# application ......................................................................................... 19
1.1.4 Exercises ........................................................................................................................... 24
1.1.5 Revision questions .............................................................................................................. 24

1.2 Object-oriented programming concepts ..................................................... 25


1.2.1 An introduction to object-oriented programming .................................................................... 25
1.2.2 Object-oriented programming principles ................................................................................ 26
1.2.3 Exercises ........................................................................................................................... 29
1.2.4 Revision questions .............................................................................................................. 29

1.3 Writing C# expressions .............................................................................. 30


1.3.1 Comments ......................................................................................................................... 30
1.3.2 Variables ........................................................................................................................... 31
1.3.3 Control statements ............................................................................................................. 33
1.3.4 More operators................................................................................................................... 40
1.3.5 Exercises ........................................................................................................................... 43
1.3.6 Revision questions .............................................................................................................. 43

1.4 Advanced coding techniques ...................................................................... 45


1.4.1 Arrays ............................................................................................................................... 45
1.4.2 Strings .............................................................................................................................. 48
1.4.3 Data-type conversion .......................................................................................................... 50
1.4.4 Enumeration ...................................................................................................................... 52
1.4.5 Exercises ........................................................................................................................... 54
1.4.6 Revision questions .............................................................................................................. 54

1.5 Coding object-oriented applications ........................................................... 55


1.5.1 Creating classes in C# ........................................................................................................ 55
1.5.2 Implementing the Vehicle class ............................................................................................ 56
1.5.3 Code regions...................................................................................................................... 59
1.5.4 Properties .......................................................................................................................... 59
1.5.5 Methods ............................................................................................................................ 62
1.5.6 Inheritance ........................................................................................................................ 64
1.5.7 Implementing functionality .................................................................................................. 68
1.5.8 Exercises ........................................................................................................................... 74
1.5.9 Revision questions .............................................................................................................. 74

1.6 Preprocessor directives .............................................................................. 75


1.6.1 Preprocessor directives ....................................................................................................... 75
1.6.2 Using preprocessor directives............................................................................................... 76
1.6.3 Exercises ........................................................................................................................... 78
1.6.4 Revision questions .............................................................................................................. 78

1.7 Using the Math and Random classes........................................................... 79


1.7.1 The Math class ................................................................................................................... 79
1.7.2 The Random class .............................................................................................................. 82
1.7.3 Exercises ........................................................................................................................... 83
1.7.4 Revision questions .............................................................................................................. 83

1.8 Test Your Knowledge (Unit 1 – Self-Test) .................................................. 84


Unit 2 – The C# Language ............................................................... 87
2.1 Using classes in C# .................................................................................... 88
2.1.1 Basic anatomy of a class ..................................................................................................... 88
2.1.2 Instance and static methods ................................................................................................ 89
2.1.3 Accessibility modifiers ......................................................................................................... 90
2.1.4 Fields ................................................................................................................................ 92
2.1.5 Constructors ...................................................................................................................... 94
2.1.6 Destructors........................................................................................................................ 98
2.1.7 Indexers ........................................................................................................................... 99
2.1.8 Exercises ..........................................................................................................................101
2.1.9 Revision questions .............................................................................................................101

2.2 Object-oriented programming basics ....................................................... 102


2.2.1 Inheritance .......................................................................................................................102
2.2.2 Encapsulating object internals .............................................................................................108
2.2.3 Polymorphism ...................................................................................................................108
2.2.4 Exercises ..........................................................................................................................115
2.2.5 Revision questions .............................................................................................................115

2.3 Overloading class members and operators ............................................... 117


2.3.1 Overloading methods .........................................................................................................117
2.3.2 Overloading indexers .........................................................................................................119
2.3.3 Overloading operators ........................................................................................................122
2.3.4 Exercises ..........................................................................................................................124
2.3.5 Revision questions .............................................................................................................124

2.4 Exceptions and exception handling .......................................................... 125


2.4.1 Try … catch blocks .............................................................................................................125
2.4.2 Finally blocks ....................................................................................................................129
2.4.3 Designing your own exception .............................................................................................130
2.4.4 Exercises ..........................................................................................................................132
2.4.5 Revision questions .............................................................................................................132

2.5 Organising code with namespaces ........................................................... 133


2.5.1 Why namespaces? .............................................................................................................133
2.5.2 Namespace directives ........................................................................................................133
2.5.3 Exercises ..........................................................................................................................135
2.5.4 Revision questions .............................................................................................................135

2.6 Structs and conversions ........................................................................... 136


2.6.1 Identifying the class/struct relationship ................................................................................136
2.6.2 Type system unification ......................................................................................................137
2.6.3 Boxing and unboxing .........................................................................................................138
2.6.4 Designing a new value type ................................................................................................138
2.6.5 Implicit versus explicit conversions ......................................................................................140
2.6.6 Exercises ..........................................................................................................................142
2.6.7 Revision questions .............................................................................................................142

2.7 Using and implementing interfaces .......................................................... 143


2.7.1 What is an interface? .........................................................................................................143
2.7.2 Interfaces versus abstract classes .......................................................................................143
2.7.3 Implicit and explicit implementation .....................................................................................144
2.7.4 Exercises ..........................................................................................................................156
2.7.5 Revision questions .............................................................................................................156

2.8 Test Your Knowledge (Unit 2 – Self-Test) ................................................ 157


Unit 3 – Graphical User Interfaces..................................................160
3.1 Delegates and events ............................................................................... 161
3.1.1 Delegates .........................................................................................................................161
3.1.2 Events and delegates .........................................................................................................165
3.1.3 Exercises ..........................................................................................................................166
3.1.4 Revision questions .............................................................................................................166

3.2 Introduction to Windows forms ................................................................ 167


3.2.1 Windows forms .................................................................................................................167
3.2.2 Controls in C# ..................................................................................................................167
3.2.3 Creating a GUI program in Visual Studio ..............................................................................168
3.2.4 Events .............................................................................................................................174
3.2.5 Control properties and layout ..............................................................................................177
3.2.6 TextBoxes ........................................................................................................................180
3.2.7 GroupBoxes and Panels ......................................................................................................182
3.2.8 Checkboxes and RadioButtons ............................................................................................184
3.2.9 MessageBoxes ..................................................................................................................186
3.2.10 Mouse events....................................................................................................................188
3.2.11 Keyboard events ...............................................................................................................190
3.2.12 Exercises ..........................................................................................................................193
3.2.13 Revision questions .............................................................................................................193

3.3 More advanced controls ........................................................................... 195


3.3.1 PictureBox controls and the Image class ...............................................................................195
3.3.2 Menus ..............................................................................................................................198
3.3.3 LinkLabel controls..............................................................................................................201
3.3.4 ListBox, CheckedListBox and ComboBox ...............................................................................202
3.3.5 Dialogs.............................................................................................................................209
3.3.6 MDI (Multiple-Document Interface) ......................................................................................210
3.3.7 Exercises ..........................................................................................................................212
3.3.8 Revision questions .............................................................................................................212

3.4 String manipulation and regular expressions ........................................... 213


3.4.1 The string class .................................................................................................................213
3.4.2 The StringBuilder class .......................................................................................................223
3.4.3 String formatting ...............................................................................................................225
3.4.4 Regular expressions ...........................................................................................................228
3.4.5 Exercises ..........................................................................................................................231
3.4.6 Revision questions .............................................................................................................232

3.5 Collections ................................................................................................ 233


3.5.1 The ArrayList Collection ......................................................................................................233
3.5.2 The BitArray Collection .......................................................................................................236
3.5.3 The HashTable collection ....................................................................................................237
3.5.4 The Queue collection..........................................................................................................239
3.5.5 The SortedList collection ....................................................................................................240
3.5.6 The Stack collection ...........................................................................................................242
3.5.7 Collection interfaces...........................................................................................................243
3.5.8 Exercises ..........................................................................................................................244
3.5.9 Revision questions .............................................................................................................244

3.6 Test Your Knowledge (Unit 3 – Self-Test) ................................................ 246


3.7 Projects .................................................................................................... 249
3.7.1 Project 1 – Blackjack .........................................................................................................249
3.7.2 Project 2 – Editor ..............................................................................................................253

Language Comparison ....................................................................257


Glossary .........................................................................................269
Bibliography ...................................................................................271
C# – Exercise Checklist ..................................................................272
Introduction to the C# Module

About this module

Welcome to the C Sharp module! Previous programming experience is not a


prerequisite for completing this module. C Sharp (from now on referred to as
C#) is a powerful language, and the aim of this module is to enable each
student to take full advantage of it.

This module covers the basics of C# and, with due diligence and application to
understanding all the concepts discussed, each student should be able to
program in C# by the end of the module. There are many ideas and concepts
that will be of benefit to any programmer, no matter which programming
language is used in the future.

Resources

The following textbook will be used for this module:

• Sharp, J. 2013. Microsoft Visual C# 2013 Step by Step.


Microsoft Press (ISBN 978-0-7356-8183-5)

Please note the following about the prescribed textbook:

The study guide does not reference the textbook. The textbook
is an invaluable tool should difficulties be experienced at any
point in the module. The textbook and study guide are based on
the assumption that the concepts may be unfamiliar and
detailed explanations are always provided.

Basic C# Programming | V1.0 August 2015 Page 6 of 276


How to approach this module

This course is divided into three units. Each unit consists of:
• Theory
• Examples
• Exercises

A theory examination will be written at the end of each unit. You will need to
complete a project at the end of this module (Unit 3). You will write a theory
and a practical examination after you have completed the project. Ensure that
you know and understand the theory before continuing with an exercise,
project or examination. Everyone wants to get their hands dirty as soon as
possible with regard to actual programming, but there will be many
opportunities to practise what you have learnt. Work through the examples in
the reference book (Microsoft Visual C# 2013 Step by Step) and complete all
the exercises in this study guide before attempting the project as well as the
examinations. Application questions will be asked in the examination – you
must be able to apply your knowledge to practical situations.

You will not pass the examination if you rush through the material and do the
project without understanding what you have learnt. The examinations are
designed to test theory, insight and practical skills. Theory examinations will
consist of true/false questions, multiple choice questions, identifying errors in
an existing section of code, multiple response questions and selection
questions. The practical examination will present you with the opportunity to
code a program on a computer.

It is very important to use all the study aids available to you. Some of the
questions in the examinations will test your general knowledge on advanced
subjects that may not have been covered in the study guide, although the
content in the study guide will be sufficient to ensure that you pass each unit.

Take note that each unit builds on previous units. Examinations will cover all
the material with which you should be familiar. For example, the examination
at the end of Unit 3 will also cover material from Units 1 and 2.

You have a certain number of days to complete the course, including all three
units, the project, the theory examinations and the practical examination.

The course is divided up as follows:

Section Unit Days % Notes


10 Go through unit and start project
1
2 10 Theory exam at the end of the unit
10 Go through unit and continue with project
C# A 2
2 10 Theory exam at the end of the unit
100%
10 5 Go through unit and finish project
3 2 45 Theory exam covering all work done so far
1 30 Practical exam

Basic C# Programming | V1.0 August 2015 Page 7 of 276


Structure of a unit

All the units follow the same structure. You will be presented with the
outcomes for each unit. These outcomes can be used as an indication of what
is important and what you should focus on when going through the unit’s
material. Notes will follow this. Read these sections carefully. Key terms will
list what you should have read and understood in the unit.

You will be presented with exercises that will require you to apply your
knowledge of the material. Ensure that you understand the exercises. Ask for
help if you are unsure of what to do. Revision questions will give you an
indication of what to expect in the examination, although you should not rely
on these questions as your only reference. Some examination questions will
undoubtedly be more difficult than the revision questions.

The Bibliography will list additional resources. It is strongly recommended


that you have a look at some of these resources, as they will provide you with
additional information that may come in handy.

You will find the project specifications at the end of the study guide. Please
do not start working on the project until you have completed (and understood)
all the exercises. Once you have covered all the topics from the previous units
and you are satisfied that you have met the outcomes, you may start the
project. Use the project specifications as a guide. They will list everything that
you need to do to comply with the project’s requirements. If your project does
not comply with these requirements, it will not be marked. Please see the
mark sheets for each project. These indicate how the marks will be allocated.

Basic C# Programming | V1.0 August 2015 Page 8 of 276


Beginning a project

It is suggested that you read through your project as soon as you receive your
new study guide. This will give you an idea of what is expected of your project.
As you progress through the guide, you will start identifying how to approach
the project. You should only start working on your project once you have a
good understanding of the material. Performing the following steps will help to
ensure that you complete your project successfully:

1. Read the relevant section in the study guide to familiarise yourself with
the material.
2. Type the examples. This might seem pointless, but it is an easy way to
familiarise yourself with the language. Experiment with the code; make
deliberate mistakes to get a feel for the way in which the compiler
handles errors.
3. Complete the exercises at the end of every chapter in the reference book
(Dorman, S. 2010. Sams teach yourself Visual C# 2010 in 24 hours).
The best way to learn a language is to practise it. This will also help you
in the examination.
4. Only start with the project if you feel comfortable with the material.
5. Make use of textbooks when the need arises.

If these guidelines are followed, the projects may not prove too difficult.

Basic C# Programming | V1.0 August 2015 Page 9 of 276


How projects are evaluated

Your lecturer will mark your projects and you will find the project evaluation
forms at the back of your study guide. Your lecturer can also provide these to
you on request. The general expectations for each of the sections are provided
below:

 Project specification
The project specification provides a detailed description of what the project
requires and how the project must function. This specification must be
printed and included with your final project submission. This includes any
projects submitted electronically

 Program design
You must follow the project specifications. For example, if the project
specifications instruct you to use a specific class, you will need to use that
class. You will be allowed to be creative, but you will be required to
incorporate certain elements into the project.

Various techniques may be employed in the planning stage of the project,


according to the project specifications. A structured plan will be an
invaluable aid to developing a fully functional project.

The first step in any program development cycle should be a design


phase: what exactly it is that you want to do, and how you will achieve it.

This will include:


o Giving the program a name.
o Stating the goal of the program.
o Stating the features of the program.
o The program design must be printed and submitted with your final
project submission. (This includes any projects submitted
electronically.)

 Source code
For any serious program that you develop, it is almost guaranteed that
either you or another programmer will have to return to the code on
occasion to correct a problem or add a new feature. It is thus important
that your code is easy to read. One way to make code easy to read is by
using indentation and white space.

Your code should also contain comments that clearly explain what is
intended by structures and blocks in the code. If a programmer who has
to maintain the code has to try to understand what it was that you
intended first, it not only wastes time but also opens the possibility that
the intention may be misunderstood, which may lead to further problems.

A well-documented program will be easier to follow, modify, debug and


maintain than a program that does not contain sufficient documentation.

Basic C# Programming | V1.0 August 2015 Page 10 of 276


Comments stating what is intended should be included for each program
flow or control statement (e.g. for, if, while, etc.). Any block of code (in
braces or surrounded by blank lines) should have a short explanation of
its purpose.

The following lists what is expected from your source code:


o The program source code must be clear and well laid out.
o You must follow a set naming standard for variable and method
names.
o Method and variable names should be descriptive.
o Each file must be clearly labelled, with a prologue displaying the
following details in comments:
 Name of the file
 Name of the author
 Date created
 Operating system
 Version
 Description of the code

For example:

Example 1 – File prologue

o You will need to provide comments for all of the following:


 Each class
 Each field
 Each method
o You need to provide the following when commenting on a method as
well:
 Author
 Version
 Date
 Return statements (if required)
 Parameters (if required)
 Exceptions that are thrown (if required)
o The source code must be printed and submitted with your final
project submission. (This includes any projects submitted
electronically.)

Basic C# Programming | V1.0 August 2015 Page 11 of 276


• Program content
Marks will be deducted if:
o The program does not run or if there are warnings of any kind. Your
program must compile and work properly before you submit it. If
your program does not run correctly, you will fail the project
and you will need to redo it. If you follow the project specification
and your program runs without any extra effort, you should receive at
least 60% for the project. Possible deductions are listed below:
 Project returned and resubmitted (–10%)
 Project copied (resubmit and 20%)
 Program does not run or crashes (resubmit and –20%)
 Redundant code (–10%)
o Syntax errors occur, e.g. ‘;’ at the end of if statements.
o There is redundant code.
o There is invalid use of arguments or return code.
o There are logic or structural errors.
o There are calculation errors.
o There are invalid variable conversions, e.g. float with an integer
variable.
o There is unnecessary code in the main() method (if applicable).

• User interface
o Ensure that the screen layout is pleasing to the eye.
o Always provide the user with clear instructions (including messages
like ‘Press any key to continue...’ when you are waiting for the user to
read the screen and ‘Please wait a moment’ when the program will be
delayed for a few seconds).
o Display money values with an appropriate symbol (e.g. R, £ or $) and
percentages with the percentage symbol (%).
o Make use of input validation to ensure that the correct data has been
entered by the user. If incorrect data has been entered, present a
user-friendly message to the user that indicates this.

• User documentation
All programs should be adequately documented:
o Those who have to maintain the code must know what was intended
by every single line of code (called program design documentation and
source code documentation).
o Those who have to use the program must know how to run it, what to
expect and what output will be displayed or printed (called user
documentation).
o You should supply extensive descriptions for your classes and
members.
o Documentation must be in the form of a Word document unless stated
otherwise.
o The user documentation must adequately explain how to install and
run the application, working on the assumption that the end user has
no prior experience of doing so.

Basic C# Programming | V1.0 August 2015 Page 12 of 276


o The user documentation must explain how to use each feature of the
application. The screenshots included must clarify each operation.
o The user documentation should consist of the following:
 An index page
 Description of the program
 Instructions on which operating system to use
 The type and version of programs used
 How to install and setup the program
 How to run the program
 What values to enter when asked for user input
 How to handle any error messages
 Screen shots of all operations
 Bibliography

o The user documentation must be printed and submitted with your


final project submission. (This includes any project submitted
electronically.)

• Project documentation
Your project documentation must include all of the following when
submitting your project:
o Project specification
o Program design
o Project source code
o User documentation
o Databases (if any)
o Resources (if any)
o System requirements (if any)
o Rough work (if any)

NOTE All projects must be presented in a professional format. Treat your


project submissions as you would in the working environment.
Documentation should be neat and typed. Ensure that you run a spell
check on your project before you submit. All your projects will make
up your portfolio of evidence that you can present to your future
employer to show what you have completed as a student.

• System requirements
o Dual Core Processor
o Microsoft Windows 7
o 2 GB RAM
o 5 GB of available disk space
o Microsoft Visual Studio 2013 Professional

Basic C# Programming | V1.0 August 2015 Page 13 of 276


Assessment for pass

A pass is awarded for the unit on the achievement of all the pass assessment
criteria.

Learning outcomes Assessment criteria for pass


To achieve each outcome a student must
demonstrate the ability to:
P1.1. Understand the .NET framework
P1. Understand the P1.2. Understand the structure of object-oriented
concepts of C# concepts
P1.3. Understand operators

P2. Be able to implement P2.1. Use control statements


object-oriented P2.2. Use Math and Random classes
processes P2.3. Use object-oriented concepts
P3.1. Create classes and methods
P3. Be able to implement P3.2. Use of exceptions, structs and conversions
functions P3.3. Create a fault-tolerant C# application
P3.4. Write an interface for a C# program
P4.1. Write C# programs incorporating delegates
P4.2. Create Windows Forms and use advanced
P4. Be able to create
Windows Controls
Graphical User
P4.3. Use string manipulation and regular
Interfaces
expressions
P4.4. Write C# programs incorporating collections

Basic C# Programming | V1.0 August 2015 Page 14 of 276


Symbols used in the study guide

Denotes the start of each main subsection in the study


guide

Denotes the start of each main subsection of the units in


the study guide.

Denotes the outcomes of the unit, i.e. the knowledge and


skills that you should have acquired after each section.

Points out the keywords of each section. Ensure that you


can name and explain all the keywords before proceeding
to the next section

Recommended exercises for each section.

Test your understanding. Answers to these revision


questions are provided in the lecturer guide.

This icon is used to indicate required reading from the


textbook.

This icon is used to indicate supplementary reading from


other sources that you can use to broaden your knowledge.

Basic C# Programming | V1.0 August 2015 Page 15 of 276


Unit 1 – An Introduction

This is an introduction to the basics of C# programming.

This unit counts 10% towards part A of the C# mark, and there are 12 days in
which to complete it. The time and marks are scheduled as follows:

Reading 10 days
Exam preparation and exam 2 days 10%

Basic C# Programming | V1.0 August 2015 Page 16 of 276


1.1 Introduction to C#

At the end of this section you will be able to:


 Understand how the compiler works.
 Briefly explain what C# and the .NET platform are and
how they work.
 Write a simple C# program.

1.1.1 What is C#?

C# is a programming language that is part of the Microsoft .NET Framework


(pronounced dot-net). It bears strong similarities to other programming
languages, such as Java and C++, as well as bringing some unique
functionality of its own.

C# is a fully event-driven, object-oriented visual programming language.

1.1.2 What is the .NET Framework?

Applications written in most programming languages are compiled into


machine code which can then be executed by the operating system. Some
others do not compile code at all, but are executed line-by-line when the
application is run (these are known as interpreted languages). Some
languages, however, compile their applications into a format that needs to be
run in a special environment known as an application virtual machine. The
virtual machine then compiles the application into machine code at runtime.
This is known as just-in-time (JIT) compilation. The .NET Framework uses
such a virtual machine. It is, however, a very special kind of virtual machine
known as the Common Language Runtime (CLR).

When a C# application is compiled, the compiler converts the source code from
regular C# to another language, known as the Common Intermediate
Language (CIL). This is then stored in an executable file (with the .exe
extension) which can be run using the .NET virtual machine. When the
executable file is run, the .NET Framework uses JIT compilation to convert
the application into machine code which can in turn be run by the operating
system.

NOTE The Common Intermediate Language was previously known as the


Microsoft Intermediate Language (MSIL).

Basic C# Programming | V1.0 August 2015 Page 17 of 276


Figure 1 – The .NET architecture

Why go to the trouble of compiling an application in two steps when it is


possible to use a language that can do it all in one? While there are many
advantages to the .NET Framework, the biggest one is this: the .NET
Framework allows code to be written in many different programming
languages, all of which can be compiled to CIL and then run in the virtual
machine. In addition, functionality has been provided which allows these
programs to interact with one another, even if they have been written in
different languages. This makes the .NET Framework a very powerful tool in
organisations where programmers specialising in different languages can still
work together on the same projects and even the same applications. Figure 1
illustrates the flexibility of the .NET Framework.

1.1.2.1 Advantages of the .NET Framework


 The .NET Framework supports many different programming languages.
 The .NET Framework can be used to create:
o Windows Desktop Applications
o Web Applications
o Windows Store Applications (for Windows 8)
o Mobile Applications (for cell phones, PDAs, etc.)
o Windows Services
o Web Services
o Distributed Applications (applications that interact across a network)
 Applications and classes created using different programming languages in
the .NET Framework are compatible with each other.
 .NET Applications can run on any operating system that has the .NET
Framework installed.

Basic C# Programming | V1.0 August 2015 Page 18 of 276


1.1.2.2 Disadvantages of the .NET Framework
 The CLR is only officially supported on Microsoft platforms.
 The .NET Framework needs to be installed on a computer before it can
run .NET applications. However, some Windows versions have the
framework pre-installed.

1.1.3 Creating your first C# application

1.1.3.1 Installing Visual Studio 2013 Professional


Before any code can be written in C#, Visual Studio 2013 Professional must be
installed on the computer. This is the Integrated Development Environment
(IDE) that will be used in this module.

An IDE is an application that is used to write code and create applications. The
standard IDE allows applications to be tested and run, as well as incorporating
other features such as syntax highlighting and code completion. The Visual
Studio IDE has all these features and more.

Use the DVD provided with this guide and select vs_professional.exe from the
auto-run menu. The installer screen, as shown in Figure 2, will be displayed.

Figure 2 – Visual Studio Professional 2013 Setup

Basic C# Programming | V1.0 August 2015 Page 19 of 276


 Ensure that I agree to the Licence Terms and Privacy Policy is
selected.
 To change the directory where Visual Studio is installed, do so now.
 Click Next.
 Ensure that all features are selected.
 Visual Studio will now begin installing the necessary files on to the
computer.
 When complete, Visual Studio will be successfully installed.

1.1.3.2 Using Visual Studio Professional 2013


When Visual Studio is opened, the screen shown in Figure 3 should be
displayed.

Figure 3 – Visual Studio Professional 2013 Start Page

This is the Start Page of Visual Studio Professional, which will be displayed
every time the IDE is run. The Start Page has several features, such as
Announcements which provides updates on the Visual Studio developments.
The list of ‘Recent’ displays a list of projects that have been worked on
recently. Clicking a project in this list will open the selected project for editing.

NOTE In Visual Studio, a project is a collection of files and resources used to


create an application. In a sense, the project is the application.

Basic C# Programming | V1.0 August 2015 Page 20 of 276


To get acquainted with the concepts involved, the first application to be
created is very simple. The application will prompt the user to enter his or her
name, and then greet him/her by the given name.

The first step to creating a new application is thus:

 Open the FILE menu, select New and click Project.

Figure 4 – New Project dialog

The New Project dialog, as shown in Figure 4, is displayed.

 Select Console Application from the list.


 Enter greetingApplication in the Name field.
 Click OK.

The Code Editor, as shown in Figure 5, is displayed.

Figure 5 – New Project in the Code Editor

Basic C# Programming | V1.0 August 2015 Page 21 of 276


This is where the C# code will be written. To make the application work, the
code must be modified so that it looks exactly like the following:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace greetingApplication
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 string userName;
14
15 Console.Write("Please enter your name : ");
16 userName = Console.ReadLine();
17
18 Console.WriteLine("Greetings, " + userName);
19 Console.ReadLine();
20 }
21 }
22 }

Line 1-5: A program can have multiple using statements to include different
namespaces.

Line 7: This is a namespace declaration. A namespace is a collection of classes.


The namespace greetingApplication contains the Program class.

Line 9: This line contains the class declaration. A class defines attributes and
behaviours. Each namespace can have more than one class.

Line 11: The Main method is the entry/starting point of each C# program and
contains the code that will run first when the class is executed. Without the
Main method the program cannot run and a class cannot contain more than
one Main method.

Line 13: A variable named userName of the string data type is declared.

Line 15: Write is a method of the Console class that can be found in the
System namespace and will display the message ‘Please enter your name:’ on
the console.

Line 16: Readline is a method of the Console class that reads user input from
the console. When the user enters their name and presses enter the value will
be assigned to the username variable.

Line 18: WriteLine will display the message on a new line

Line 19: Adding Console.ReadLine() at the end of the code in the Main method
prevents the console from closing too quickly when the program runs.

Basic C# Programming | V1.0 August 2015 Page 22 of 276


The application is now ready to be run!

 Press <F5>, or open the DEBUG menu and click Start Debugging.

The result is:

Figure 6– The Greeting Application in action

Basic C# Programming | V1.0 August 2015 Page 23 of 276


1.1.4 Exercises
1. Briefly explain what C# is.

2. List the disadvantages of the .NET framework.

3. Explain how JIT compilation works briefly.

1.1.5 Revision questions


1. True/False: JIT stands for Java Input Timer.

2. True/False: C# is part of .NET.

3. True/False: C# is a procedure-oriented programming


language.

Basic C# Programming | V1.0 August 2015 Page 24 of 276


1.2 Object-oriented programming concepts

At the end of this section you will be able to:


 Explain the fundamental concepts behind object-
oriented programming.

1.2.1 An introduction to object-oriented programming

Object-oriented programming (OOP) is a method of programming in which


everything is treated as a self-contained object, each with its own attributes
and behaviours. The objects are defined in a class, which can be thought of as
the template from which the objects are created. Object-oriented programming
attempts to simulate the real world. There are many languages that are
object-oriented, such as C#, Java, C++ and VB.NET.

Some of the most pertinent terminology will now be explored.

1.2.1.1 Classes
A class is one of the most important concepts of object-oriented programming.
A class is best thought of as a template from which objects are created. The
template describes what attributes and behaviours the object will have. For
example, a Book class does not refer to a specific book, but rather the general
description of a book. The class will never have specific information about any
book.

1.2.1.2 Objects
An object is a specific instance of a class. Where the Book class describes a
book, the instance is an actual book. For example Twilight, Fallen, etc. are
instances of the Book class.

1.2.1.3 Attributes
An attribute is a piece of information about an object. For example, a book
might have a name, an author and an ISBN number. In programming terms,
attributes are often referred to as instance variables, where an instance is
the object created from the class.

1.2.1.4 Behaviours
A behaviour is something that an object does. A book can be read, printed,
bought or sold. A method to count the number of pages, words, or lines in the
book could be developed. Behaviours can also cover things that a class will
automatically do. These are known as events. Note, however, that an event
does not have any code in itself, but rather that the event calls a specific
method called the event-handler.

Basic C# Programming | V1.0 August 2015 Page 25 of 276


1.2.2 Object-oriented programming principles

Four main principles are common to all OOP languages, namely: abstraction,
encapsulation, inheritance and polymorphism.

1.2.2.1 Abstraction
An abstraction is an idea or concept that is not associated with one specific
object. In programming languages, abstract templates (classes) that store the
essential attributes and behaviours for a type of object are created. For
example, an abstract Vehicle class would define all the attributes and
behaviours common to all vehicles. Because the Vehicle class is abstract, it
would not be possible to create objects from it – it can be considered as a
template from which other classes can be created through inheritance (which
can then be used to create objects).

1.2.2.2 Encapsulation
Encapsulation, also known as data-hiding, is a principle of object-oriented
programming which states that all the attributes and behaviours of an object
should be grouped together in one data type or class. What this ultimately
means is that each class should be as self-sufficient as possible. The main
reason for this is to hide the implementation of the attributes and/or
behaviours of a class from other classes. The class thus presents a standard,
constant interface.

For example, the Drive()method is called to enable the Vehicle class to move.
However, it is not necessary to know how the Drive()method actually works,
only what it is intended to do. This allows programmers to change how their
classes work (which may be necessary at some point) without breaking
compatibility with other classes. In other words, other classes that use the
Vehicle class would not need to be modified to continue to work as before.

1.2.2.3 Inheritance
Inheritance is a core principle of object-oriented programming which allows
one class to inherit all the attributes and behaviours of another class. This
allows a class to be specialised by inheriting from it and providing additional
functionality (attributes and behaviours). For example, when a new Car class is
created from the abstract Vehicle class, it has not only its own unique
functionality, but also has all the functionality inherited from the Vehicle class.
Likewise, a Truck class and a Bike class will also inherit the functionality from
the Vehicle class, much like the Car class, but the additional functionality
provided will be different. These relationships are illustrated in Figure 7.

Basic C# Programming | V1.0 August 2015 Page 26 of 276


Vehicle
Name
NumWheels

Drive
Park

Car Truck Bike


NumPassengers CargoType EngineSize
CargoAmount

LoadPassenger LoadCargo

Figure 7 – Class diagram showing inheritance

A class that inherits from another class is known as a derived class, or


alternatively, a sub-class. Inheritance (a) saves having to write the same code
out more than once, and (b) allows for the use of polymorphism.

Inheritance can be thought of as an is a relationship. Car is a Vehicle. Note


that inheritance can have multiple levels. A class that inherits from Car, for
example, will inherit everything from the Car class, including that which the
Car class has already inherited from the Vehicle class. In this case, the new
class, called Sedan, is a Car. Because it is a Car, it is also a Vehicle. There is
no limit to multiple inheritance. Figure 8 shows a diagram that describes
multiple levels of inheritance.

Basic C# Programming | V1.0 August 2015 Page 27 of 276


Vehicle

Car Truck Motorbike

Sedan Hatchback SUV

Figure 8 – Class diagram showing multiple levels of inheritance

1.2.2.4 Polymorphism
Polymorphism literally means ‘many forms’. In object-oriented programming,
the principle of polymorphism allows behaviours inherited from a parent class
to be overridden so that the derived class (the class that inherits from the
parent) has behaviours that work differently from the parent class, although
they share the same name. For example, the Car and Bike classes might both
inherit a method called Drive(), but each would implement it differently.

In practical terms, there could be an array of Vehicle objects, any one of which
could be a Car, Bike or Truck. It might not be known what Vehicle type it is,
nor would it be necessary to know. When the Drive()method is called, the
program automatically calls the method in the derived class. If no method of
that name existed in the derived class, the program will then look for one in
the parent class, and so on.

This highlights the is a principle of inheritance. Because a Car is a Vehicle, it


can be treated as such in any application.

Basic C# Programming | V1.0 August 2015 Page 28 of 276


1.2.3 Exercises
1. Why is encapsulation also known as data-hiding?

2. Briefly describe the principles of polymorphism.

3. What makes a class self-sufficient?

1.2.4 Revision questions


1. True/False: Encapsulation allows classes to be modified
without breaking compatibility with other classes.

2. True/False: Abstraction is not associated with one specific


object.

3. True/False: Inheritance is not used in object-oriented


programming.

Basic C# Programming | V1.0 August 2015 Page 29 of 276


1.3 Writing C# expressions

At the end of this section you will be able to:


 Understand what a variable is and how it works.
 Understand what control statements are and how they
work.
 Understand how to use conditions.

1.3.1 Comments

It is often necessary to explain how a certain piece of code works, or why it


has been done in a certain way. This is done through the use of comments.
Comments are ignored by the compiler (i.e. they do not affect program logic in
any way) as their only purpose is to document code. Visual C# changes the
colour of any text that is commented-out so that the comment is clearly
distinguishable from normal code.

1.3.1.1 Single-line comments


These comments start with two forward slashes (//). Anything typed between
the start and the end of the line it is on will be commented-out. A single-line
comment is shown in Figure 9.

// This is a single-line comment.


Figure 9 – C# single-line comment

1.3.1.2 Multi-line comments


These comments start with /* and end with */. Anything typed between the
start and end of the comment will be commented-out. A multi-line comment is
also known as a block comment. Figure 10 illustrates a multi-line comment.

/*
* This is a
* multi-line
* comment
*/
Figure 10 – C# multi-line comment

All coding should always be documented with comments that briefly explain
what the program is doing. Comments can also be used to comment-out
problematic sections of code to allow the program to compile, or to include or
hide, code used for debugging purposes.

Basic C# Programming | V1.0 August 2015 Page 30 of 276


1.3.2 Variables

A variable represents a location in memory that contains a value. For example,


consider a variable called ‘number’ and a value of 5 stored in this variable. This
means that the computer will know where to look when number is accessed.
The term variable is used because the value entered into the memory location
can change. Think of a variable as a container which can be filled with different
values.

1.3.2.1 Variable types


In most programming languages, C# included, variables are strongly typed.
What this means is that a specific type of variable is required to store a specific
type of value. For example, a user name may not be stored in a variable
intended to hold numbers. Table 1 shows the C#’s variable types.

Table 1 – Basic C# variable types


Type Description Example

Used to store a sequence of characters,


string string name = ‘John’;
such as a word or sentence.

Used to store an integer. Cannot be


int int passMark = 60;
used to store floating point numbers.

double Used to store a decimal number. double pi = 3.14;

char Used to store a single character. char gender = ‘m’;

bool Used to store a true or false value. bool passed = true;

Used to store an integer, but can only


short store numbers between 32,768 and short x = 50;
32,767.
Used to store an integer, but can store
very long numbers long y =
long
-922337203685477508 to 23000120023;
922337203685477507.

Used to store a decimal number, but


decimal z =
decimal with greater precision than the double
992.11242;
data type.

Used to store a decimal value with


float float f = 1.4;
single point precision.

Basic C# Programming | V1.0 August 2015 Page 31 of 276


Used to store an integer value between
byte byte b = 128;
0 and 255.

Unsigned int, short and long data types can be uint x =1;
data unsigned, i.e. only positive if you place ushort y = 2;
types a u in front of their declaration. ufloat z = 1.4;

1.3.2.2 Declaring variables


In C#, it is important to remember to declare a variable before attempting to
give it a value. Failing to do so will result in a compilation error. Each example
in Table 1 illustrates a variable declaration with initial assignment.

Figure 11 shows the syntax used to declare a variable.

Figure 11– Basic variable declaration

Figure 12 shows how to declare a variable and assign an initial (starting) value
to it.

Figure 12 – Variable declaration with initial assignment

1.3.2.3 Where to declare variables


Variables should preferably be declared at the top of the section in which they
will be used. So, if a variable is only referenced inside a single method, and
there is no need for the variable to store a value in between calls, then that
variable should be declared within that method. Otherwise, it should be
declared at the top of the program.

It is not impossible to declare variables elsewhere. However, keeping to a set


standard when coding applications will make them far easier to debug.

1.3.2.4 Variable scope


A variable can only be referenced (used) within the block of code in which it is
declared. If a variable is declared inside a method, that variable cannot be
used outside the method. In fact, once the event-handler has completed its
execution, the variable will be destroyed.

Basic C# Programming | V1.0 August 2015 Page 32 of 276


If a variable is declared at the top of the program, it may be used anywhere in
the code.

{ // Beginning of a code block.

} // End of a code block.

So, for example, the following code would not compile:

{
int x = 10;
}

Console.WriteLine(x); // Variable x is inaccessible.

Code blocks are almost exclusively used by class definitions, method


definitions and control statements. They can, however, be used without
accompanying statements (as in the two examples above), although this is far
from common practice.

A variable declared inside a code block or method is referred to as a local


variable. Variables that are declared inside the class body (but not within a
method or other code block) are referred to as class variables.

NOTE It is possible to declare two variables with the same name if one of
them is declared at the top of the program and the other is declared
within a method. The one declared within the method will be used
within the method, and the other one will be used everywhere else.
They are not the same variable.

1.3.2.5 Data type conversions


It is possible to convert a value from one type to another. This will be covered
later in this module.

1.3.3 Control statements

A control statement is any statement that can change the flow of the program
depending on certain conditions. Usually, a variable will be checked against
some predefined value to determine what the program should do next.

1.3.3.1 Conditions
A condition is a statement that is checked by a control statement to determine
whether it is true or not. For example, the condition:

1 < 2 // 1 is smaller than 2.

will evaluate to true, whereas the condition:

Basic C# Programming | V1.0 August 2015 Page 33 of 276


1 > 2 // 1 is greater than 2.

will evaluate to false.

The general syntax for a condition is as follows:

value1 (operator) value2

1.3.3.2 Conditional operators

Table 2 – Conditional operators


Operator Description
== Evaluates to true if value1 is equal to value2, false otherwise.
Evaluates to true if value1 is smaller than but not equal to
<
value2, false otherwise.
Evaluates to true if value1 is greater than but not equal to
>
value2, false otherwise.
Evaluates to true if value1 is greater than or equal to value2,
>=
false otherwise.
Evaluates to true if value1 is smaller than or equal to value2,
<=
false otherwise.
Evaluates to true if value 1 is not equal to value 2, false
!=
otherwise.

Table 2 lists the conditional operators. These conditional operators make the
most sense when used to compare numerical variables, but it note that they
can often be used for other data types.

Note that conditional operators return a Boolean (bool) variable representing


the result of that operator. So if the conditional operator evaluates to true, it
returns a Boolean variable with the value of true. What this means is that, if
so desired, the result of a conditional operator may be stored in a variable. The
reverse is also true – Boolean variables may be checked as conditions.

1.3.3.3 Compound conditions


It is possible to combine multiple conditions into one end result which can then
be checked by a control statement or stored in a variable. This is done through
the use of Boolean algebra.

The following is an example of a compound condition:

(condition1 & (condition2 | condition3))

In this example, the compound condition would evaluate to true only if:

Basic C# Programming | V1.0 August 2015 Page 34 of 276


1. condition1 evaluates to true
AND (&)
2. condition2 OR (|) condition3 evaluates to true

In any other circumstance, it would evaluate to false. Note the use of the
brackets.
The compound condition operators are shown in Table 3.

Table 3 – Compound condition operators


Operator Description
Evaluates to true if both the condition on the left and the
&
condition on the right evaluate to true, false otherwise.
Same as above, but the way in which the check is done differs. The
condition on the left is checked, and if it evaluates to false this
operator automatically evaluates to false, without checking the
&&
condition on the right. This may be advantageous in some
situations, but should only be used when it is not vital for the
condition on the right to be checked.
Evaluates to true if either the condition on the left or the
|
condition on the right evaluates to true, false otherwise.
Same as above, but the way in which the check is done differs. The
condition on the left is checked, and if it evaluates to true, then
this operator automatically evaluates to true without checking the
||
condition on the right. This may be advantageous in some
situations, but should only be used when it is not vital for the
condition on the right to be checked.
Placed before another condition to negate it. A negated Boolean
expression will evaluate to the opposite of what it normally
!
would, i.e. if it would normally evaluate to true, it would evaluate
to false instead.

1.3.3.4 The if statement


The most basic control statement is called the if statement. The if statement
checks whether a condition is true or not, and when it is true, the code
statements contained within its code block are executed.

if (condition)
{
// Statements.
} // If code block ends here.

1.3.3.4.1 The ternary operator


The ternary operator is a special case which is a compressed if statement. It
checks a condition, and if that condition is true, assigns a certain value to a
variable. If the condition is false, a different value is assigned to the variable.
The syntax for the ternary operator is as follows:

variable = condition ? true statement : false statement;

Basic C# Programming | V1.0 August 2015 Page 35 of 276


Here is a basic example of a ternary operator:

string stringResult = 2 < 1 ? "2 is smaller than one" : "2 is greater than one";

Console.WriteLine(stringResult);
Console.ReadLine();

Because the condition used by the ternary operator is false in the above
example, the print out is: 2 is greater than one.

1.3.3.5 The if … else if … else statement


An extension of the basic if statement, the if … else if … else statement,
checks if a condition is true; if it is true, the code within the if code block is
executed. If the condition is not true, another condition is checked with the
else if statement, which will execute the code within its block if the condition
that it checks is true. If both the if condition and the else if condition are
false, the code in the else block will be executed.

Multiple else if statements may be used as part of one chain, but there may
only be one if statement and one else statement. The else if and else are
both completely optional – removing them both would revert the statement to
a basic if statement.

The following is an example of an if … else if … else if … else chain.

if (condition)
{
// Statements
} // if code block ends here
else if (condition)
{
// Statements
} // else … if code block ends here
else if (condition)
{
// Statements
} // else … if code block ends here
else
{
// Statements
} // else code block ends here

Example:

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

namespace Operators
{
class Conditions
{
static void Main(string[] args)
{
int scoreTeam1 = 3;

Basic C# Programming | V1.0 August 2015 Page 36 of 276


int scoreTeam2 = 3;

if(scoreTeam1 > scoreTeam2)


{
Console.WriteLine("Team 1 is the winner!");
}
else if (scoreTeam2 > scoreTeam1)
{
Console.WriteLine("Team 2 is the winner!");
}
else
{
Console.WriteLine("It is a tie");
}
Console.ReadLine();
}

}
}

1.3.3.6 The switch … case statement


While it is possible to use a long chain of if … else if statements to check
multiple conditions, it can be simpler to use a switch … case statement
instead. The code below shows the syntax of a switch … case statement. A
switch … case statement is very similar to a chain of if … else if statements;
however, it differs in the fact that it cannot evaluate Boolean conditions other
than ‘==’, which it does by default. Nevertheless, the switch … case statement
is very useful and is widely used throughout the programming world.

switch (variable)
{
case 0:
// Code here is executed if 'variable' == 0
break;

case 1:
// Code here is executed if 'variable' == 1
break;

default:
// Code here is executed if none of the above ‘cases’ are true
break;
} // end of switch statement

Example:

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

namespace Statements
{
class CaseStament
{
static void Main(string[] args)
{
char grade = 'A';

switch (grade)

Basic C# Programming | V1.0 August 2015 Page 37 of 276


{
case 'A':
Console.WriteLine("You are a genius!");
break;

case 'B':
case 'C':
Console.WriteLine("Well done");
break;

case 'D':
case 'E':
Console.WriteLine("You passed");
break;

case 'F':
Console.WriteLine("Oops! You failed. Better luck next
time...");
break;

default:
Console.WriteLine("Invalid code!");
break;
}
Console.ReadLine();
}
}
}

The result is:

You are a genius

1.3.3.7 Loops
A loop is a special kind of control statement, which can execute the code within
its code block multiple times depending on certain conditions.

1.3.3.7.1 The for loop


A for loop is a loop designed to execute a certain number of times. Figure 13
shows a for loop that will execute 5 times.

Figure 13 – A for loop

 Initialisation statement:
This statement is executed when the for loop starts. It is intended to be
used to declare a variable that will be used to count the number of times
the loop has executed, as well as assign an initial value to that variable. In

Basic C# Programming | V1.0 August 2015 Page 38 of 276


the case of this example, an integer variable called loopCounter has been
declared with an initial value of 0.

 Test condition:
This is a Boolean condition which will be tested every time the loop
executes. If the condition evaluates to false, the loop will terminate and
the program will continue executing the code after the for loop. In this
example, the for loop will continue to execute so long as the loopCounter
variable is smaller than, but not equal to, 5.

 Counting expression:
This is a statement that is intended to increment (increase) or
decrement (decrease) the loop variable. In this example, loopCounter is
increased by 1 every time the for loop executes. The counting expression
does not necessarily have to modify the loop variable; it could also modify
anything else. Be careful to ensure that at some point the values which
must be evaluated by the test condition change so that the test condition
evaluates to false, or the loop will repeat infinitely, i.e. it will never end
and the program will never continue. This is known as an infinite loop and
should be avoided in almost all situations.

1.3.3.7.2 The while loop


A while loop is designed to execute so long as the condition it checks remains
true. It is very much like a for loop without an initialisation statement or
counting expression.

while (condition)
{
// Code to be executed.
} // End of while loop.

Before the first execution, and for every execution thereafter, a while loop
checks the condition before executing the code within the while block. If the
condition evaluates to false, the loop will terminate and the program will
continue executing code after the while loop. If the condition is false before the
first execution, the program will continue execution after the while loop
without executing the loop code. As in the case of a for loop, take care not to
create infinite loops.

1.3.3.7.3 The do … while loop


A do … while loop is almost identical to a normal while loop, except that the
code within its code block will always execute at least once as the condition is
only tested after each execution, instead of before it. The following code shows
the syntax of a do … while loop:

do
{
// Code to be executed.
}
while(condition)

Basic C# Programming | V1.0 August 2015 Page 39 of 276


1.3.3.8 Breaking and continuing
1.3.3.8.1 The continue statement
Sometimes a condition arises inside a control statement, which means that the
rest of the current execution must be skipped and the next one begun
immediately. This can be done with the use of the continue statement. The
following code shows an example of a for loop that makes use of the continue
statement:

int messageToHide = 3;
for(int loop = 0; loop < 10; loop = loop + 1)
{
if(loop == messageToHide)
{
continue;
}

Console.WriteLine(“This loop has executed “ + (loop + 1) + “ times.”);


}

In this example, a variable messageToHide has been declared with a value of


3. Inside the for loop, this variable is checked at the beginning of every
execution. If the current value of loop is not equal to messageToHide, the loop
carries on with the rest of its execution and shows a message telling the user
how many times the loop has executed (loop + 1 because the loop starts at 0).

However, if the value of loop is equal to the value of messageToHide, then the
continue statement is executed, and the rest of the loop is skipped, the
counting expression is executed, and the loop begins again. From a user
perspective, 9 messages will be seen, one after the other, for each execution
of the loop except for the fourth execution (when loop == 3).

1.3.3.8.2 The break statement


The break statement is used to ‘break out’ of a code block or loop immediately,
and force the program to continue its execution after the loop. It may be used
in any type of loop, but its use inside the switch … case control statement is
mandatory. It can be used much in the same way as a continue statement,
except that the loop will not restart its execution.

1.3.4 More operators

In C# (and most other programming languages), operators are used to


perform and evaluate mathematical operations.

1.3.4.1 Unary operators


Unary literally means ‘one’. As such, a unary operator works with only one
variable (referred to as an operand) at a time. There are many different unary
operators (see Table 4), but you should already be familiar with two of the
most basic: the unary plus and unary minus operators. These two operators
are used to change the value of one value. For example:

int number = -5;

Basic C# Programming | V1.0 August 2015 Page 40 of 276


In the above example, the unary minus operator is placed before the value (5)
to change it from a positive number to a negative one.

Note that the unary plus operator serves no true function. In mathematics,
placing a plus sign before a number does not change the value of that number
in any way. The unary minus will change a positive number to a negative one,
or a negative number to a positive one.

int number;
// These two statements mean exactly the same thing.
number = 5;
number = +5;

There are many other unary operators, and these are listed in Table 4.

1.3.4.1.1 Incremental and decremental operators


Incremental operators are used to increase the value of a variable by a certain
amount (usually one). Similarly, decremental operators are used to decrease
the value of a variable by a certain amount (usually one). Both of these
operators can be used before (pre) or after (post) the variable name to
determine what value is to be returned.

// Declare two variables.


int num1 = 1;
int num2;

num2 = num1++; // Post-increment – num2 is set to num1’s value before num1 is


// incremented. num2 = 1 and num1 = 2.

num2 = ++num1; // Pre-increment – num1 is incremented and then num2 is set to


// that value. num2 = 3 and num1 = 3

num2 = num1--; // Post-decrement – num2 is set to num1’s value before num1 is


// decremented. num2 = 3 and num1 = 2

num2 = --num1; // Pre-decrement – num1 is decremented and then num2 is set to


// that value. num2 = 1 and num1 = 1

// The operators can also be used without assigning the return value to
another // variable.
num1++; // num1’s value is increased by one.

num2--; // num2’s value is decreased by one.

1.3.4.1.2 Negation operator


The negation operator (also referred to as the NOT operator) is used to invert
the value of a Boolean variable or expression. The negation operator was
shown earlier in Table 3.

// Declare a Boolean variable.


bool var = true;

var = !var; // var is now false, it is not true (!true).

The unary operators are shown in Table 4:

Basic C# Programming | V1.0 August 2015 Page 41 of 276


Table 4 – Unary operators
Operator Name Description
+ Unary plus Has no effect.
Changes the sign of the value, i.e. if it is
- Unary minus negative it becomes positive; if it is positive it
becomes negative.
++ Incremental Increases the value of the variable by one.
-- Decremental Decreases the value of the variable by one.
Inverts the value of a Boolean variable or
! Negation
expression.

1.3.4.2 Binary operators


Binary operators work with two variables (operands). Those familiar with
mathematics will have used many of these in the past.

Table 5 shows the binary operators:

Table 5 – Binary operators


Operator Name Description
+ Binary Adds one operand to the other and returns the result.
plus
- Binary Subtracts the right operand from the left and returns the
minus result.
* Multiply Multiplies one operand by the other and returns the
result.
/ Divide Divides the left operand by the right operand and returns
the result.
% Modulus Divides the left operand by the right operand and returns
the remainder (if any).

As with conditional operators, binary operators usually make the most sense
when working with numerical variables. However, some can be used with other
variable types. For example, strings may be concatenated (appended one to
the other) using the binary plus operator. This has already been seen in action
in the output (Console.WriteLine("")) of some of the examples.

Basic C# Programming | V1.0 August 2015 Page 42 of 276


1.3.5 Exercises
1. When would the following condition evaluate to true?
(condition1 | condition2 & condition1)

2. What is the modulus operator (%) used for?

3. Describe the difference between a while loop and a do …


while loop.

4. Describe the usage of the NOT operator.

5. When are binary operators used?

6. Why is it important always to declare a variable before


using it?

7. What is the value of num1 and num2 after the following


code has been executed?

int num1 = 9;
int num2 = 4;
num1 = num1 + num2++;

a. num1 = 13 and num2 = 5


b. num1 = 9 and num2 = 9
c. num1 = 13 and num2 = 5
d. num1 = 5 and num2 = 9

8. When is an if … else if chain used instead of a switch


statement?

1.3.6 Revision questions


1. True/False: The binary plus operator cannot be used with
strings.

2. True/False: Pre-incremental and post-incremental


operators change the value of the variable by different
amounts.

3. True/False: Unary operators work with two or more


variables.

4. True/False: The ternary operator is a compressed if


statement.

5. True/False: Conditional operators can use Boolean


algebra.

6. True/False: Incremental operators increase the value of

Basic C# Programming | V1.0 August 2015 Page 43 of 276


the variable by one.

7. True/False: The break statement slows the computer to a


halt.

Basic C# Programming | V1.0 August 2015 Page 44 of 276


1.4 Advanced coding techniques

At the end of this section you will be able to:


 Understand what arrays are, and how they are used.
 Understand the concepts behind the string class and its
methods.
 Understand how to convert values from one data type
to another.

1.4.1 Arrays

An array is a special type of variable that can hold zero or more values within
it. An array can be of any type, but all its elements (values stored within it)
must be of the same base type. The following is an example of a basic
application that uses an array (this code would be found inside the Main
method):

// Declare the array.


string[] customers = new string[5];

// Add the values.


customers[0] = "Kyle";
customers[1] = "Carla";
customers[2] = "Luke";
customers[3] = "Angelique";
customers[4] = "Cameron";

// Using a for loop to display the contents of the array.


for (int loop = 0; loop < 5; loop++)
{
Console.WriteLine("Customer number " + loop + "’s name is : "
+ customers[loop]);
}

The above example declares a string array with 5 elements, and sets the value
for each of those elements. A for loop is used to iterate through the array and
display each element.

The example will now be explained step by step.

1.4.1.1 Declaring the array


As with any other variable, an array needs to be declared before it can be used
in the application.

// Declare the array.


string[] customers = new string[5];

The square brackets ([ ]) are known in many programming languages (C#


included) as the index operator. When used to declare a variable (as shown

Basic C# Programming | V1.0 August 2015 Page 45 of 276


above), they indicate that the variable is an array. For example, to create an
array to hold 10 integers, the following code is used:

int[] customers = new int[10];

The number between the square brackets in the initialisation statement (right-
hand side) indicates how many elements the array should have. Once
declared, this size cannot be changed.

It is also possible to declare an array with initial values. The following code
shows how this can be done:

// Declare the array.


string[] customers = new string[5]
{
"Kyle",
"Carla",
"Luke",
"Angelique",
"Cameron"
};

This can be done with any type of array.

1.4.1.2 Setting the array’s values


Setting the value for each of the elements of the array is fairly straightforward.
First, establish which element must be set or changed. In the code below, the
value of the first element (element 0, as arrays count up from 0) is being set:

// Add the values.


customers[0] = "Kyle";

Setting the value of an array element is thus much the same as for a normal
variable.

1.4.1.3 Accessing/modifying values in the array


Now that there is an array with data in it, the data will be put to use. To access
an element in the array, it is necessary to know which element must be
retrieved. To display the first element of the array, the following code is used:

Console.WriteLine(customers[0]);

Notice that the number 0 is used with the index operator to retrieve the first
element.

This is all very well for situations where the exact element(s) of the array are
known, but in many situations this may very well not be known beforehand.
For these and similar situations (which is in most situations where arrays are
involved), a variable is used to specify which element of the array to retrieve.
In the following example, a for loop is used to retrieve each element of the
array and display its value. This is where the true value of loops and arrays
becomes evident; the same operations on or with every element in an array is

Basic C# Programming | V1.0 August 2015 Page 46 of 276


executed, without having to create code for each element or even having to
know exactly how many elements there are.

// Using a for loop to display the contents of the array.


for (int loop = 0; loop < 5; loop++)
{
Console.WriteLine("Customer number " + loop + "’s name is : "
+ customers[loop]);
}

To adjust the loop to iterate through an entire array without knowing its exact
size, the test condition of the for loop is simply modified. All arrays have a
property called Length which can be used to retrieve the size of the array. The
updated loop looks as follows:

// Using a for loop to display the contents of the array.


for (int loop = 0; loop < customers.Length; loop++)
{
Console.WriteLine("Customer number " + loop + "’s name is : "
+ customers[loop]);
}

NOTE Always make sure that the element you are attempting to access
exists (i.e. a value has been set at the specified index, and that the
index of the element is not greater than the size of the array. Also
always ensure that your array index is not negative.) Failing to do
so will lead to an exception being thrown.

1.4.1.4 Default values


When an array is created without any initial values, the array elements are
automatically assigned default values:

 Numerical values of type short, int, float, decimal, and so on, are assigned
the value zero.
 Values of type char are assigned the Unicode character \u0000 (Null).
 Values of type bool are initialised to the value false.
 Values of reference types are initialised to null.

1.4.1.5 Foreach loops


There is a special type of loop that is designed to work with arrays and
collections (collections will be covered in-depth later on in the guide). This loop
is known as the foreach loop. The code below shows how a foreach loop could
be used to work with the customers array:

// Using a for loop to display the contents of the array.


foreach (string name in customers)
{
Console.WriteLine(name);
}

Basic C# Programming | V1.0 August 2015 Page 47 of 276


1.4.2 Strings

A string is a C# data type used to store a sequence of characters, such as a


word or sentence. Strings are a special data type based on an array of
characters, with some additional functionality. Because of this, all the methods
used for interacting with an array can also be used to interact with a string.

For example, to get the first character in a string:

string name = "Kyle";


char firstLetter = name[0];

1.4.2.1 String class methods


When working with a string value, the word index is used (as with arrays) to
specify the location of a character. Table 6 shows some of the methods of the
string class.

Table 6 – String class methods


Return
Method Description
type
Returns true if the beginning of string
str.StartsWith(string s) bool str matches string s; otherwise it
returns false.
Returns true if the end of string str
str.EndsWith(string s) bool matches string s; otherwise it returns
false.
Searches string str for occurrences of
string s. If one is found, the index of
str.IndexOf(string s) int the first occurrence is returned as an
integer. If no occurrence is found, a
value of 1 is returned.
Searches string str for occurrences of
string s. If one is found, the index of
str.LastIndexOf(string s) int the last occurrence is returned as an
integer. If no occurrence is found, a
value of 1 is returned.
Searches string str for occurrences of
string s. If one is found, a value of
str.Contains(string s) bool
true is returned; otherwise it returns
false.
Searches string str for occurrences of
string old. Any occurrences that are
found are replaced with string new.
str.Replace(string old, string
string The method then returns the updated
new)
string (note that str itself remains
unchanged unless it has the updated
string assigned to it).
Returns string str with all of its
str.ToLower() string
characters set to lower case.

Basic C# Programming | V1.0 August 2015 Page 48 of 276


Returns string str with all of its
str.ToUpper() string
characters set to upper case.

The following code demonstrates some of these string methods.

 To test the methods, enter the code into the Main method in a new
application.

// Declare variable.
string testString = "This is a test string";

// Display the original string.


Console.WriteLine("Original String: " + testString);

// Convert the string to lower case.


testString = testString.ToLower();

// Display the updated string.


Console.WriteLine("String in lower case: " + testString);

// Display the string in upper case, but do not save it.


Console.WriteLine("String in upper case: " + testString.ToUpper());

// Does this string start with the word "this" ?.


Console.WriteLine("String starts with 'this': "
+ testString.StartsWith("this"));

// Does this string end with the word "this" ?.


Console.WriteLine("String ends with 'this': " + testString.EndsWith("this"));

// Replace all spaces in the string with dashes.


testString = testString.Replace(" ", "-");

// Display the updated string.


Console.WriteLine("String with dashes instead of spaces: " + testString);

// Pause.
Console.ReadLine();

 Press <F5> to test the application. The result is:

Original String: This is a test string


String in lower case: this is a test string
String in upper case: THIS IS A TEST STRING
String starts with 'this': True
String ends with 'this': False
String with dashes instead of spaces: this-is-a-test-string

1.4.2.2 Formatting a string


The way data is displayed in a string must sometimes be explicitly specified
and controlled. For example, a number must be displayed using scientific
notation, or to a certain number of decimal places. This can be done through
the use of string formatting. The following code shows how string formatting
can be performed:

Basic C# Programming | V1.0 August 2015 Page 49 of 276


// Pi.
double Pi = 3.1428571428571428571428571428571;
// Simple string format.
Console.WriteLine("1. Pi is equal to {0}.", Pi);
// Specify a format (0.00).
Console.WriteLine("2. Pi is equal to {0:0.00}.", Pi);
// Exponential format.
Console.WriteLine("3. Pi is equal to {0:E2}", Pi);
// Multiple items.
Console.WriteLine("4. Pi is equal to {0:0.00}, twice that is {1:0.00}.", Pi,
Pi * 2);
// Three items.
Console.WriteLine("5. {0:0.00}, {1:0.00}, {2:0.00}, {3:0.00}", Pi, Pi * 2, Pi
*
3, Pi * 4);
// Pause.
Console.ReadLine();

The result is:

1. Pi is equal to 3.14285714285714.
2. Pi is equal to 3.14.
3. Pi is equal to 3.14E+000
4. Pi is equal to 3.14 twice that is 6.29.
5. 3.14, 6.29, 9.43, 12.57

1.4.3 Data-type conversion

It is often necessary to convert data from one data type into another. For
example, input is almost always read in as a string value. Mathematical
operations cannot be performed with a string. In this case, the string value will
have to be converted into an integer value.

A simple application is created to demonstrate this. This application accepts


the age of a user as its input. It then calculates how many days that user has
been alive (at least up until his or her most recent birthday). To do this, the
user input is actually required as an integer. However, the
Console.ReadLine()method only reads input as a string value. In this case, the
string value needs to be converted into an int value.

1.4.3.1 Parsing strings


The process of converting a string to another data type is known as parsing.

The following code shows how this can be done:

// Variable declaration.
int userAge;

// Prompt for input.


Console.Write("Please enter your age: ");

// Parse the user's input.


userAge = Int32.Parse(Console.ReadLine());

// Perform the calculation.


int daysAlive = userAge * 365;

Basic C# Programming | V1.0 August 2015 Page 50 of 276


// Display the result.
Console.WriteLine("You have been alive for " + daysAlive + " days!");

// Pause.
Console.ReadLine();

The result is:

Please enter your age: 21


You have been alive for 7665 days!

Look at the line in which the parsing is done:

// Parse the user's input.


userAge = Int32.Parse(Console.ReadLine());

On this line, a string is read in from the user, via the console. That string is
then parsed into an integer and assigned to the integer variable userAge.

Strings may be parsed into other data types as well. For example, the
following code converts a string into the double data type:

// Parse the user's input.


cashAmount = Double.Parse(Console.ReadLine());

Converting a string to a character is easy – simply use the index operator to


pick out the first character in the string, as shown in the following code:

string name = "Kyle";


char firstLetter = name[0];

1.4.3.2 Converting other data types to strings


Every class in C# (including those that are user-created) has a method called
ToString()which returns a string representation of that object. To convert any
data type or object to a string value, simply call its ToString()method.

It is worth noting here that when a string value is created through


concatenation (adding one or more strings together), those objects that are
added will automatically have their ToString()methods called. Because of this,
both of the following lines of code have exactly the same effect:

// Age is an int.
Console.WriteLine("Age : " + age);

Console.WriteLine("Age : " + age.ToString());

1.4.3.3 Converting between other data types


Sometimes it will be necessary to convert between other data types. This is
done through casting. There are two types of casting: implicit and explicit.

Basic C# Programming | V1.0 August 2015 Page 51 of 276


1.4.3.3.1 Implicit casting
Implicit casting happens automatically when it is guaranteed that no data will
be lost when the type is converted. For example, converting an integer to a
double would be implicit because the double data type can hold all the
information of the integer data type and more. However, the reverse is not
true – a double cannot be implicitly converted into an integer as all the
information following the decimal point will be lost. Consider the following
example:

int radius = 5;
double circumference = 3.14 * 2 * radius;

The two integer values (2 and radius) are first implicitly converted to the
double data type before the calculation is performed.

Implicit conversion can take place anywhere a mathematical operation is


performed, even inside conditions. Implicit conversion will only take place if it
is necessary for the calculation being performed.

1.4.3.3.2 Explicit casting


Explicit casting will only happen if it is so specified. Explicit casting may be
specified between any numerical data type, as well as with some other
compatible data types. Explicit conversion can, however, lead to data loss.

double d = 3.14;
int i = (int)d * 2;

In the above example, the double value d is converted to an integer before


multiplying it by 2. The end result of this calculation would be 6, as converting
a double to an integer removes all the data following the decimal point. There
will be situations where explicit casting is required, but they are far less
common than those where implicit casting is sufficient.

1.4.4 Enumeration

An enum is a special kind of variable that allows a set of related constants to


be created. These constants are generally more meaningful than just using a
set of integers. The enum variable types often start with the letter e, to make
identification of them easier. For example:

// Declare the enumerator.


public enum eColour
{
RED,
GREEN,
BLUE
};

static void Main(string[] args)


{
// Declare two variables of type eColour.
eColour backgroundColour = eColour.GREEN;
eColour fontColour = eColour.BLUE;

Basic C# Programming | V1.0 August 2015 Page 52 of 276


// Retrieve the two values and display them.
Console.WriteLine("Background Colour: " + backgroundColour);
Console.WriteLine("Font Colour: " + fontColour);

Console.ReadLine();
}

The result is:

Background Colour: GREEN


Font Colour: BLUE

The usefulness of enum will become more evident as experience in working


with the C# language grows.

Basic C# Programming | V1.0 August 2015 Page 53 of 276


1.4.5 Exercises
1. Describe how data loss can occur when using explicit
casting.

2. What happens when an array element that does not exist


is accessed?

3. Converting from a string to int is referred to as:

1.4.6 Revision questions


1. True/False: You can convert from int to a string using
.ToString().

2. True/False: Conversion of an integer to a double is


handled automatically.

3. True/False: An enum is a set of unrelated constants.

4. True/False: Each object stored in an array is referred to


as an element.

Basic C# Programming | V1.0 August 2015 Page 54 of 276


1.5 Coding object-oriented applications

At the end of this section you will be able to:


 Understand how to create and code your own classes in
C#.
 Understand how to use those classes to create a
functional application.

1.5.1 Creating classes in C#

 Open Visual Studio.


 Create a new Console Application project and call it vehicleTracking.

1.5.1.1 The Program class


Look at the code that is automatically generated by the IDE:

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

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

This code shows the layout of a basic class called Program. The code will now
be studied in detail.

using System;

This is a using statement. It imports the code from another namespace (in
this case, the System namespace) into the application so that it may be used
without having to specify the full path name. This will be discussed in greater
detail later on.

namespace vehicleTracking

This is a namespace declaration. This declares that all the code between its
opening and closing brackets is part of the vehicleTracking namespace.

class Program

Basic C# Programming | V1.0 August 2015 Page 55 of 276


This is a class declaration. This declares that all the code between its
opening and closing brackets is part of the Program class.
static void Main(string[] args)

This is a method declaration. A method is a section of code that is designed


to perform a specific operation. All the code between the declaration’s opening
and closing brackets is part of the Main method. The Main method is a special
case – the code within it is executed when the application starts.

1.5.1.2 Creating the basic Vehicle class


Continuing on from the example shown in the last section, a Vehicle Tracking
System intended to be used by a dealership will be developed. For now, no
actual functionality will be created, but attention will be focused on the
structure of the classes.

 Click PROJECT on the main menu bar.


 Click Add Class.
 Type in the name Car.
 Click Add.

Notice how the new class generated by the IDE is very similar to the Program
class, except that there are no method declarations.

1.5.2 Implementing the Vehicle class

Before the Vehicle class can be implemented, it is important to know what


function it must actually perform. Figure 14 shows a class diagram of the
Vehicle class.

Vehicle

Make
Model
Condition
Price

Figure 14 – Class diagram for the Vehicle class

Note that the class diagram does not show any method declarations. This is
because none are needed; the Vehicle class is only going to be used to store
information.

Basic C# Programming | V1.0 August 2015 Page 56 of 276


Modify the Vehicle class so that it looks like the following code segment:

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

namespace vehicleTracking
{
class Vehicle
{
// Variable declaration.
public string make = "";
public string model = "";
public int condition = 0;
public double price = 0;
}
}

The code declares the four variables shown in the class diagram. The reason
that there is a public keyword before each of them is that these variables need
to be accessible outside of the class. There are other access modifier
keywords, but these will be discussed in detail later on in the guide.

The class is not yet complete; a constructor must be created. A constructor is a


special method that is called when the object is instantiated (when an instance
of the class is created). If a constructor is not created for a class, the C#
compiler will automatically create one that has no code. However, a
constructor with no code in it is not suitable for the purpose here. The
constructor must allow the four Vehicle class variables to be set.

Type in the following code below the variable declarations:

// Empty constructor.
public Vehicle()
{
}

// Constructor.
public Vehicle(string newMake, string newModel, int newCondition, double
newPrice)
{
Make = newMake;
Model = newModel;
Condition = newCondition;
Price = newPrice;
}

Note that two constructors have been created above: one empty constructor,
and one that takes parameters. The basic Vehicle class is now complete.
Objects will now be created from this class.

Use the Solution Explorer (Figure 15) to open Program.cs.

Basic C# Programming | V1.0 August 2015 Page 57 of 276


Figure 15 – Solution Explorer

Instantiate an object of the Vehicle class in order to test it.

Type the following code inside the Main method of the Program class:

Vehicle testVehicle = new Vehicle("Opel", "Corsa", 3, 85000);

This code creates a new instance of the Vehicle class called testVehicle. The
testVehicle instance has its variables set by the constructor, using the values
passed to it in this line of code. In order to test this code out, another line of
code must be added.

Type the following code inside the Main method of the Program class, after the
previous line:

Console.WriteLine("Car: " + testVehicle.Make + " " + testVehicle.Model


+ " – R" + testVehicle.Price + ". Condition: " +
testVehicle.Condition + "/5");

Console.ReadLine();

The above code displays all the variable values of the testVehicle in a format
that is easily understandable. The Console.ReadLine(); statement is used to
prevent the console window from closing after the program has finished its
execution.

Run the application now to see how it looks.

The result is:

Car: Opel Corsa – R85000. Condition: 3/5

Now it is time to complete the Vehicle class.

Basic C# Programming | V1.0 August 2015 Page 58 of 276


1.5.3 Code regions

When coding C# applications, classes often end up having a fair amount of


code in them, which can make it quite hard to find a specific section to work
on. Fortunately, C# has a way of splitting code into smaller sections (known as
regions). The code for this application will be split into three separate regions,
namely: Properties, Constructors and Methods.

To create a code region in Visual Studio, simply:

 Type in #region where the region is to start.


 Press Tab.

The following will be displayed:

#region MyRegion

#endregion

 Replace the word MyRegion with the desired name for the region. In this
case, the first region will be called Properties.

Any code typed between the opening (#region) and the closing (#endregion)
tags will be part of that region. The primary advantage of a code region is the
option of whether or not to display the code in it, merely by clicking the small
minus (-) sign to the left of the region name.

 Create 3 regions: Properties, Constructors, and Methods.

1.5.4 Properties

In C#, a property is a special type of instance variable which can execute code
to calculate a return value or validate a set value (among other uses).

The syntax for a property is as follows:

public datatype propertyName


{
get
{
// Code to return a value.
}
set
{
// Code to set a value.
}
}

Convert each of the Vehicle instance variables into properties. This will allow
for more control over the values that those properties can accept and return.
Each of the following properties created should be placed inside the Properties
code region.

Basic C# Programming | V1.0 August 2015 Page 59 of 276


1.5.4.1 The Make property
The first property is fairly simple. Replace the Make instance variable
declaration with the following code:

// The 'Make' property.


private string mMake = "";
public string Make
{
get
{
return mMake;
}
set
{
mMake = value;
}
}

This property actually consists of two parts: the first being a private string
variable called mMake, and the second being a public string property called
Make. The get method of the Make property simply returns the value stored in
the mMake variable. Similarly, the set method takes the value it receives and
stores it in the mMake property. Note that in the set method the value
keyword represents the value to which the property has been set.

With this property, only the Vehicle class itself will have access to the mMake
variable as it is private. The property itself, however, is public and provides
access to the value through its get and set methods. This is part of the
encapsulation principle – the inner workings of the class are not directly
accessible.

Note that properties do not need to have both a get and a set property. Read-
only properties and write-only properties will only accept values.

1.5.4.2 The Model property


The Model property is very similar to the Make property.

// The 'Model' property.


private string mModel = "";
public string Model
{
get
{
return mModel;
}
set
{
mModel = value;
}
}

Basic C# Programming | V1.0 August 2015 Page 60 of 276


1.5.4.3 The Condition property
For the Condition property an enum, which specifies exactly in what condition
the vehicle is, is created.

// The 'eVehicleCondition' enumerator.


public enum eVehicleCondition
{
GOOD,
BAD,
UGLY
};

// The 'Condition' property.


private eVehicleCondition mCondition;
public eVehicleCondition Condition
{
get
{
return mCondition;
}
set
{
mCondition = value;
}
}

The constructor has to be modified such that the newCondition parameter is


now of the eVehicleCondition data type rather than int.

1.5.4.4 The Price property


The Price property is very similar to the Make and Model properties. However,
the data type is double, and the property will only accept positive values.

// The 'Price' property.


private double mPrice = 0;
public double Price
{
get
{
return mPrice;
}
set
{
if (value > 0)
{
mPrice = value;
}
else
{
// If the value given is smaller than equal to zero.
mPrice = 0;
}
}
}

Notice that the set method for the Price property ensures that no matter what
value is passed to it, the stored value is never less than zero.

Basic C# Programming | V1.0 August 2015 Page 61 of 276


1.5.5 Methods

A method is a block (section) of code within a program designed to perform a


specific task. Generally, a method is mostly independent of the rest of the
program, although this is not always the case.

public void SayHello()


{
Console.WriteLine("Hello!");
}

The above code shows a very simple method which will display the text Hello!
on the screen when this method is called. Methods, such as this one, are used
to avoid repetitive code.

1.5.5.1 Parameters
Methods can also accept parameters, i.e. values to work with. The following
code shows how a parameter can be used in a basic method. Note that there is
no limit to the number of parameters that may be passed to a method, and
that the parameters may be of any type.

public void SayHello(string name)


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

Dynamic functionality is provided by passing parameters to methods. The way


in which the method executes can be different, depending on the parameters
passed to it.

1.5.5.2 Access modifier and returning values


The keywords public and void are explained below:
• Public – as with variable declarations, making a method public means
that it may be called from outside the class.
• Void – this is a specification of the return type of the method. Methods can
return values, which means that they can, for example, perform
calculations and return the result. The return type specifies what type of
value is returned. Void literally means nothing, which means that this
method does not return a value.

The following code shows a method that adds the two parameters that are
passed to it, and returns the result as an integer:

public int Add(int a, int b)


{
return a + b;
}

If a return type other than void is specified, then the method must have a
return statement at some point, or the application will not compile.

Basic C# Programming | V1.0 August 2015 Page 62 of 276


When the application reaches a return statement in a method, it will
immediately stop executing the method and return the specified value (much
like the break statement breaks out of a control statement). This means that
any code after a return statement will not be executed. For example:

public int Add(int a, int b)


{
return a + b;

Console.WriteLine("This will not be displayed.");


}

This does not prevent the application from compiling or executing, but it can
lead to logic errors. Because of this, a return statement may be used as a
break statement inside a method that returns void.

It is also possible to have multiple return statements inside a method. This can
be useful. For example:

public bool StartsWith(string str, char character)


{
// If the first character of string str == character.
if (str[0].ToLower() == character.ToLower())
{
return true;
}
else
{
return false;
}
}

The example above returns true if the first character in string str is equal to
the char character, regardless of whether the character is upper case or lower
case (which is why both have been converted to lower case before comparing
them). While the above example is perfectly acceptable, it is possible to reduce
the amount of code needed to perform this operation by leaving out the else
statement. The reason for this is that when the if code block is executed (and
this will happen when the condition is true), then the return true; statement is
executed and the execution of the method will not continue.

The simplified code would look as follows:

public bool StartsWith(string str, char character)


{
// If the first character of string str == character.
if (str[0].ToLower() == character.ToLower())
{
return true;
}
// If this point is reached, then the condition was false.
return false;
}

Basic C# Programming | V1.0 August 2015 Page 63 of 276


This method may be further simplified. Conditions always return bool values
which are checked by control statements. The if statement may be entirely
removed.

public bool StartsWith(string str, char character)


{
return (str[0].ToLower() == character.ToLower());
}

Remember that the example given is a very simple method. Most methods will
be more complex and are not usually so easy to simplify.

It is possible to have more than one method declared with the same name.
These methods are differentiated from one another by the parameters they
take. This means that there may be only one method with a particular name
that takes a certain set of parameters. This is known as overloading the
method.

Whenever a method is used in an application, the compiler looks for a method


that has the specified name and takes the same parameters. If one is found,
that method is called. If not, then the application will not compile.

1.5.5.3 The ToString() method and the override keyword


According to the class diagram, the Vehicle class has no methods. However,
there is one method which all classes share – the ToString() method. The
reason for this is that the ToString() method is defined in the Object class from
which all other classes are derived. The method will convert the properties of
the class into a human readable format and return them as a string.

// ToString method.
public override string ToString()
{
return Make + " – " + Model + ", in " + Condition +
" condition. Price : R" + Price;
}

The override keyword specifies that this method must override a method in the
base class (in this case Object). If the override keyword is not used, the
compiler will show a warning message during compilation. The
ToString()method is a special method that is called whenever an object is
written to the console. Many examples of this method are shown further on in
the guide.

1.5.6 Inheritance

Three classes that inherit from the Vehicle class (the Car, Truck and Motorbike
class) will now be created. This is actually a fairly simple process, because
most of the code needed has already been written for the Vehicle class, and
the new classes will inherit all of that functionality. What needs to be written is
the functionality that differs from the Vehicle class.

Basic C# Programming | V1.0 August 2015 Page 64 of 276


 Click PROJECT on the main menu bar.
 Click Add Class.
 Type in the name Car.
 Click Add.

The empty Car class, as shown below, will be displayed:

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

namespace vehicleTracking
{
class Car
{
}
}

Now that there is a Car class, ensure that it inherits from the Vehicle class by
making the following modification:

class Car : Vehicle


{
}

Adding the code : Vehicle after the class declaration instructs the compiler that
this class inherits from the Vehicle class. Adding different constructors,
properties and methods as necessary will define how the Car class differs from
the Vehicle class.

The Car class is going to differ from the Vehicle class in that it will have a
property that stores the number of passengers the car can carry. In addition to
this, a custom constructor which will allow that property to be set when the
object is created, as well as an updated ToString() method which will display
this property in addition to the other information, is required.

The PassengerCapacity property looks as follows:

private int mPassengerCapacity = 0;


public int PassengerCapacity
{
get
{
return mPassengerCapacity;
}
set
{
mPassengerCapacity = value;
}
}

Basic C# Programming | V1.0 August 2015 Page 65 of 276


It is now time to create the constructor.

// Constructor.
public Car() :base()
{
}

// Constructor.
public Car(string make, string model, eVehicleCondition condition, double price,
int passengerCapacity)
:base(make,model,condition,price)
{
PassengerCapacity = passengerCapacity;
}

In the above example, the constructor of the Vehicle class has been extended
using the base() command. The base() command specifies that the matching
method or constructor from the base class should be called before executing
the code of the method/constructor. Naturally, if the base() command is
omitted, then only the code in the method or constructor will be executed.
There are two constructors and the first ‘empty’ constructor is necessary to
store instances of the class in an array.

There is only one more requirement to complete the Car class: its own
implementation of the ToString() method. Once again, the base command may
be used. In this situation, however, a value is being returned, which means
that the use of the command will be slightly different.

Notice that the Visual Studio automatically generates some of the code as code
is being entered. The method should end up looking as follows:

// ToString method.
public override string ToString()
{
return base.ToString() + ", Passenger Capacity : " + PassengerCapacity;
}

This ToString()method in the Car class returns a string value made up of:

a. The return value of the ToString() method in the Vehicle class


(base.ToString())
b. The PassengerCapacity property (", Passenger Capacity : " +
PassengerCapacity)

The Car class is now complete.

Ensure that the Car class has been completed according to the instructions in
this section, with the property, constructor and ToString() method.

Now create the Truck and Motorbike classes. They are both very similar to the
Car class, except that the Truck class will have a CargoCapacity property, and
the Motorbike class will have an EngineCapacity property. These properties will
take the place of PassengerCapacity for these two classes.

Basic C# Programming | V1.0 August 2015 Page 66 of 276


Create the Truck and Motorbike classes using the same procedure used to
create the Car class.

The following code shows what the code for the Truck class should look like:

// The ‘Truck’ Class.


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

namespace VehicleApplication
{
class Truck : Vehicle
{
private int mCargoCapacity = 0;
public int CargoCapacity
{
get
{
return mCargoCapacity;
}
set
{
mCargoCapacity = value;
}
}

// Constructor.
public Truck()
: base()
{
}

// Constructor.
public Truck(string make, string model, eVehicleCondition condition,
double price, int cargoCapacity)
: base(make, model, condition, price)
{
CargoCapacity = cargoCapacity;
}

// ToString method.
public override string ToString()
{
return base.ToString() + ", Cargo Capacity : " + CargoCapacity;
}
}
}

Basic C# Programming | V1.0 August 2015 Page 67 of 276


The code for the Motorbike class should look as follows:

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

namespace VehicleApplication
{
class Motorbike : Vehicle
{
private int mEngineCapacity = 0;
public int EngineCapacity
{
get
{
return mEngineCapacity;
}
set
{
mEngineCapacity = value;
}
}

// Constructor.
public Motorbike()
: base()
{
}

// Constructor.
public Motorbike(string make, string model, eVehicleCondition condition,
double price, int engineCapacity)
: base(make, model, condition, price)
{
EngineCapacity = engineCapacity;
}

// ToString method.
public override string ToString()
{
return base.ToString() + ", Engine Capacity : " + EngineCapacity;
}
}
}

1.5.7 Implementing functionality

There are four classes that will be used in the vehicleTracking application. The
functionality that will put these classes to practical use will now be
implemented.

Return to the Program class (Use either the File tab or the Solution Explorer).

The vehicleTracking application needs to have the following functionality:

1. The user needs to be able to add new Cars, Trucks and Motorbikes.
2. The program must be able to display a list of Vehicles by type.
3. The program must be able to display a list of all Vehicles.

Basic C# Programming | V1.0 August 2015 Page 68 of 276


First, an array is required to store all the vehicles. Because the three types of
vehicles all inherit from the Vehicle class, they may all be stored in the same
array.

// Variable declaration.
Vehicle[] vehicleArray = new Vehicle[50];
int numVehicles = 0;

Notice that an integer variable is used to hold the count of how many vehicles
are stored in the array. This will be used later to display the vehicles.

A method must be created to perform each of the functionalities listed above.


The first method will display all the vehicles, regardless of their type.

// Lists all vehicles.


public void DisplayAllVehicles()
{
Console.WriteLine("Display All Vehicles");
Console.WriteLine("------------------------------------");
for (int loop = 0; loop < numVehicles; loop++)
{
Console.WriteLine(vehicleArray[loop]);
}
}

This method moves through the array and displays each of the vehicles, one
after the other. The numVehicles variable is used to ensure that the program
does not display vehicle objects that have not been instantiated.

The other three display methods must now be created. These methods will all
be very similar to each other, the only difference being the type of vehicle that
they display.

// Lists all Cars.


public void DisplayAllCars()
{
Console.WriteLine("Display All Cars");
Console.WriteLine("------------------------------------");
for (int loop = 0; loop < numVehicles; loop++)
{
// The 'is' operator returns true if the object 'is' of the specified type
if (vehicleArray[loop] is Car)
{
Console.WriteLine(vehicleArray[loop]);
}
}
}

// Lists all Trucks.


public void DisplayAllTrucks()
{
Console.WriteLine("Display All Trucks");
Console.WriteLine("------------------------------------");
for (int loop = 0; loop < numVehicles; loop++)
{
// The 'is' operator returns true if the object 'is' of the specified
type

Basic C# Programming | V1.0 August 2015 Page 69 of 276


if (vehicleArray[loop] is Truck)
{
Console.WriteLine(vehicleArray[loop]);
}
}
}

// Lists all Motorbikes.


public void DisplayAllMotorbikes()
{
Console.WriteLine("Display All Bikes");
Console.WriteLine("------------------------------------");
for (int loop = 0; loop < numVehicles; loop++)
{
// The 'is' operator returns true if the object 'is' of the specified type
if (vehicleArray[loop] is Motorbike)
{
Console.WriteLine(vehicleArray[loop]);
}
}
}

The above methods all make use of the is operator. The is operator is a special
operator that C# uses to determine if an object is of a specific class. In this
case, there is an array of Vehicles, but it is not known which one may belong
to the type Cars, Trucks or Motorbikes.

A method to add vehicles to the array is required. This method will be


significantly more complicated than any of the previous methods attempted, as
it needs to be able to add vehicles of any type.

// Prompts the user for information and adds a vehicle to the array.
public void AddVehicle()
{
// Variable declaration.
Vehicle v;
char vehicleType;
int vehicleCapacity;
string vehicleMake;
string vehicleModel;
Vehicle.eVehicleCondition vehicleCondition;
double vehiclePrice;

// This program cannot store more than 50 vehicles.


if (numVehicles >= 50)
{
Console.WriteLine("The array is full.");
// Stop executing the method.
return;
}

// Prompt the user for information and read it in.


Console.WriteLine("Add Vehicle");
Console.WriteLine("------------------------------------");
Console.WriteLine("Please fill in the following information : ");

Console.Write("Vehicle Make : ");


vehicleMake = Console.ReadLine();
Console.Write("Vehicle Model : ");
vehicleModel = Console.ReadLine();

Basic C# Programming | V1.0 August 2015 Page 70 of 276


Console.Write("Vehicle Price : ");
vehiclePrice = Double.Parse(Console.ReadLine());

Console.Write("Vehicle Condition (0 == Good, 1 == Bad, 2 == Ugly) : ");


// ‘Cast’ the user’s input to the eVehicleCondition type.
vehicleCondition =
(Vehicle.eVehicleCondition)Int32.Parse(Console.ReadLine());

Console.Write("Vehicle Type : ");


// We only need to check the first letter.
vehicleType = Console.ReadLine()[0];

switch(Char.ToLower(vehicleType))
{
case 'c': // Car
// Prompt for correct capacity type.
Console.Write("Passenger Capacity : ");
// Parse the input.
vehicleCapacity = Int32.Parse(Console.ReadLine());
// Create a new instance of the Car class.
v = new Car(vehicleMake, vehicleModel, vehicleCondition,
vehiclePrice, vehicleCapacity);
break;

case 't': // Truck


// Prompt for the correct capacity type.
Console.Write("Cargo Capacity : ");
// Parse the input.
vehicleCapacity = Int32.Parse(Console.ReadLine());
// Create a new instance of the Truck class.
v = new Truck(vehicleMake, vehicleModel, vehicleCondition,
vehiclePrice, vehicleCapacity);
break;

case 'm': // Motorbike


// Prompt for the correct capacity type.
Console.Write("Engine Capacity : ");
// Parse the input.
vehicleCapacity = Int32.Parse(Console.ReadLine());
// Create a new instance of the Motorbike class.
v = new Motorbike(vehicleMake, vehicleModel, vehicleCondition,
vehiclePrice, vehicleCapacity);
break;

default: // Invalid input.


Console.WriteLine("Invalid vehicle type. Returning to main menu...");
// Stop executing this method, return to the menu.
return;

break;
}

// Add the new vehicle to the array.


vehicleArray[numVehicles] = v;
// Increment the count.
numVehicles = numVehicles + 1;

// Clear the console.


Console.Clear();
Console.WriteLine("Vehicle Added!");
}

Basic C# Programming | V1.0 August 2015 Page 71 of 276


Methods for adding and displaying the vehicles have been implemented, and a
menu that allows the user to choose which operations he or she wants to
perform will now be added.

Creating the menu is simple:

// Displays a menu and prompts the user to make a selection.


public void DisplayMenu()
{
// This method clears the screen.
Console.Clear();

Console.WriteLine("Vehicle Tracking");
Console.WriteLine("------------------------------------");
Console.WriteLine("1. Add a vehicle");
Console.WriteLine("2. Display all vehicles");
Console.WriteLine("3. Display all cars");
Console.WriteLine("4. Display all trucks");
Console.WriteLine("5. Display all motorbikes");
Console.WriteLine("6. Exit");
Console.WriteLine("------------------------------------");
Console.Write("Please make your choice : ");
}

A switch … case statement determines which choice the user has made:

// Executes the user's choice.


public void ExecuteChoice(char c)
{
// This method clears the screen.
Console.Clear();

switch (c)
{
case '1': // Add a Vehicle
AddVehicle();
break;
case '2': // Display sll vehicles
DisplayAllVehicles();
break;
case '3': // Display all cars
DisplayAllCars();
break;
case '4': // Display all trucks
DisplayAllTrucks();
break;
case '5': // Display all motorbikes
DisplayAllMotorbikes();
break;
case '6': // Exit
Console.WriteLine("Goodbye!");
break;
default: // Invalid input
Console.WriteLine("Please enter a number between 1 and 6");
break;
}

// Pause.
Console.WriteLine("Please hit any key to continue...");
Console.ReadLine();
}

Basic C# Programming | V1.0 August 2015 Page 72 of 276


The DisplayMenu() and ExecuteChoice() methods must be called appropriately.
This is done in the constructor of the Program class.

// constructor
public Program()
{
char choice = ' ';

while (choice != '6')


{
// Display the menu.
DisplayMenu();
// Read in the user's choice.
choice = Console.ReadLine()[0];
// Perform the requested operation.
ExecuteChoice(choice);
}
}

The above while loop will repeat, displaying the menu until the user decides to
exit by choosing 6.

Now for the final touch:

static void Main(string[] args)


{
new Program();
}

In the Main method, we simply need to create a new instance of the Program
class. We do not need to assign it to a variable as we do not refer to it again; it
is completely self-contained. Remember that when an instance is created, the
constructor is called. Thus, when the new Program instance is created, its
constructor is called and our application enters the menu loop.

Basic C# Programming | V1.0 August 2015 Page 73 of 276


1.5.8 Exercises
1. Describe the process of overloading a method.

2. Define the use of the is operator.

3. Describe the differences between a property and an


attribute

1.5.9 Revision questions


1. True/False: Methods declared with a return type of void
cannot use return statements.

2. True/False: If a return statement is reached inside a


method, then the application stops executing that method
immediately.

3. True/False: Methods can be used to avoid writing


repetitive code.

Basic C# Programming | V1.0 August 2015 Page 74 of 276


1.6 Preprocessor directives

At the end of this section you will be able to:


 Understand what preprocessor declarations are and what
they are used for.

1.6.1 Preprocessor directives

Preprocessor directives are special C# statements that are executed during


compilation instead of at runtime. Preprocessor directives are primarily used
for testing purposes.

The preprocessor directives are shown in Table 7:

Table 7 – Preprocessor directives


Type Description
Similar to a standard if statement. If the condition tested is
true, then any preprocessor directives between the #if and
#endif statements are executed. In addition, any standard
#if
code between the statements will be included in the
compilation process. If the condition is not true, then that
code will not be compiled with the rest of the application.
#else Equivalent to a standard else statement for a #if directive.
Equivalent to a standard else … if statement for a #if
#elif
directive.
This statement defines the end of the #if, #elif, or #else
#endif
block.
Defines a symbol (much like a variable) that can be checked
#define by a #if statement. If the symbol is defined, then it will
evaluate to true and the #if statement will execute.
Undefines a symbol. If a symbol is undefined then it will
#undef evaluate to false, and any #if statement that uses it as a
condition will not execute.
#warning Forces the compiler to display a warning message.
Forces the compiler to throw a compilation error which will
#error
prevent the application from being compiled.
Defines the start of an area that can be collapsed/expanded in
#region
Visual Studio Professional 2013 and other IDEs.

#endregion Defines the end of a region.

Basic C# Programming | V1.0 August 2015 Page 75 of 276


1.6.2 Using preprocessor directives

#define TEST
//#undef TEST
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace preprocessorTest
{
class Program
{
static void Main(string[] args)
{
#if TEST
// This will only execute if TEST has been defined.
Console.WriteLine("TEST has been defined");
#else
// this will only execute if TEST has not been defined
Console.WriteLine("TEST has not been defined");
#endif

// Pause.
Console.ReadLine();
}
}
}

The above program shows how a basic #if … #else … #endif works. If the
comment before the line #undef TEST is removed (or if the line #define TEST
is commented-out), TEST would then no longer be defined and the if block
would no longer be compiled. The else block will be compiled instead. Notice
how the Visual Studio Professional 2013 automatically changes the colour of
code that will not be compiled so that it is greyed out.

The following code shows how the #warning directive is used:

#define TESTING_MODE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace preprocessorTest
{
class Program
{
static void Main(string[] args)
{
#if TESTING_MODE
#warning "Program compiled in testing mode..."
#endif

// Pause.
Console.ReadLine();
}
}
}

Basic C# Programming | V1.0 August 2015 Page 76 of 276


When the program is compiled, a warning message will be displayed in the
Error List, as illustrated in Figure 16:

Figure 16 – A warning message

The following code shows how the #error directive is used:

#define NO_COMPILE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace preprocessorTest
{
class Program
{
static void Main(string[] args)
{
#if NO_COMPILE
#error "An error message."
#endif
}
}
}

During compilation of this program an error is thrown and compilation is


halted, as shown in Figure 17.

Figure 17– A compilation error

Basic C# Programming | V1.0 August 2015 Page 77 of 276


1.6.3 Exercises
1. What are preprocessor directives most commonly used
for?

2. What does the #warning directive do?

3. Briefly explain how the #region directive is used.

1.6.4 Revision questions


1. True/False: The #define directive allows declaration of a
symbol which can be checked by a #if statement.

2. True/False: The #endregion directive declares the end of


the program.

3. True/False: Using the #define directive creates a value


the program can use during runtime.

Basic C# Programming | V1.0 August 2015 Page 78 of 276


1.7 Using the Math and Random classes

At the end of this section you will be able to:


 Understand how to use the Math class.
 Understand how to use the Random class.

1.7.1 The Math class

The C# language has many libraries (referred to as namespaces) which


contain additional classes and methods for use in applications. The Math class
is stored in one such namespace (System).

The Math class provides methods that are used to perform mathematical
operations, ranging from simple square roots to more complicated
trigonometry.

The Math class is static, which means that an instance of the class does not
need to be created in order to use its methods. To use its methods it is merely
necessary to specify the Math class before the method name, like this:

returnValue = Math.methodName(parameters);

Table 8 shows some of the Math class methods. In the Example column, the
value in the commented line is the answer to the given operation (i.e.
Math.Abs(-5.95) = 5.95). Note that NaN refers to Not a Number. Some
mathematical operations may return NaN if the equation is invalid.

Table 8 – Math class methods


Method Description Example
Math.Abs(-5.95)
Returns the absolute value of a //5.95
Abs(value)
specified number. Math.Abs(-15)
//15
Math.Acos(0.5)
Returns the angle whose cosine is
//1.0471975511966
Acos(value) the specified number. Parameter
Math.Acos(2)
can be any number from -1 to 1.
//NaN
Math.Asin(0.5)
Returns the angle whose sine is the
//0.523598775598299
Asin(value) specified number. Parameter can
Math.Asin(2)
be any number from -1 to 1.
//NaN

Basic C# Programming | V1.0 August 2015 Page 79 of 276


Math.Atan(0.5)
//0.463647609000806
Returns the angle whose tangent is Math.Atan(200)
Atan(value)
the specified number. //1.56579636846094
Math.Atan(-200)
//-1.56579636846094
Returns the smallest whole number Math.Ceiling(15.88)
greater than or equal to the //16
Ceiling(value)
specified number. Parameter and Math.Ceiling(-15.88)
return types are both double. //-15
Math.Cos(30)
Returns the cosine of the specified
Cos(angle) //0.154251449887584
angle.
Returns e raised to the specified Math.Exp(2)
Exp(value)
power. //7.38905609893065
Returns the largest whole number Math.Floor(15.88)
less than or equal to the specified //15
Floor(value)
number. Parameter and return Math.Floor(-15.88)
types are both double. //-16
Returns the natural logarithm of a
Math.Log(2)
Log(value) specified number.
//0.693147180559945
Returns the logarithm of a
Math.Log(2, 8)
Log(val,base) specified number in a specified
//0.333333333333333
base.
Returns the base 10 logarithm of a Math.Log10(2)
Log10(value)
specified number. //0.301029995663981
Returns the larger of two specified Math.Max(23, 23.55)
Max(val1,val2)
numbers. //23.55
Returns the smaller of two Math.Min(23, 23.55)
Min(val1,val2)
specified numbers. //23
Returns a specified number raised Math.Pow(2, 3)
Pow(val, pow)
to the specified power. //8
Returns a value rounded to the
Math.Round(5.55)
Round(val) nearest whole number.
//6
Returns a value rounded to the
Math.Round(5.55,1)
Round(val,pos) nearest number of specified
//5.6
decimal positions.
Returns the sine of the specified Math.Sin(30)
Sin(angle)
angle. //-0.988031624092862
Returns the square root of a Math.Sqrt(16)
Sqrt(value)
specified number. //4
Returns the tangent of the Math.Tan(30)
Tan(angle)
specified angle. //-6.40533119664628

In addition to its methods, the Math class also contains some mathematical
constants. These constants are displayed in Table 9.

Basic C# Programming | V1.0 August 2015 Page 80 of 276


Table 9 – Math class constants
Constants Explanation Example
PI contains the value for ratio of the circumference of a
PI circle to its diameter. PI is an infinite value returned as Math.PI
3.14159265358979 by means of the double type.
The natural logarithm lnx is the logarithm having a
base E, where E is returned as 2.71828182845905,
E Math.E
although it is in fact an infinite value. The value of E is
also returned as double type.

The following example shows how Math class methods can be used:

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

namespace MathClassTest
{
class Program
{
static void Main(string[] args)
{
Console.Write("Please enter a number: ");
int num = Int32.Parse(Console.ReadLine());

Console.WriteLine();
Console.WriteLine("The square root of " + num + " is " +
Math.Sqrt(num) + ".");

// num ^ 2 == num exponent 2 (squared)


Console.WriteLine(num + "^2 == " + Math.Pow(num, 2));
Console.WriteLine("log(" + num + ") == " + Math.Log(num));
Console.WriteLine("Square root of num rounded off == " +
Math.Round(Math.Sqrt(num)));

Console.ReadLine();
}
}
}

You will receive the following output after entering 5:

Please enter a number: 5

The square root of 5 is 2.23606797749979.


5^2 == 25
log(5) == 1.6094379124341
Square root of num rounded off == 2

Basic C# Programming | V1.0 August 2015 Page 81 of 276


1.7.2 The Random class

When creating applications, it may be necessary on occasion to generate


random numbers. The Random class (like the Math class) is stored in the
System namespace. Unlike the Math class, however, the Random class is not
static. This means that an instance of the class must be created before its
methods may be used.

Numbers generated by the Random class are not true random numbers;
because the numbers are generated by an algorithm, they are in reality only
pseudo-random numbers. What this means is that if the starting point
(referred to as the seed) of the algorithm is the same in two separate cases,
then the ‘random’ numbers generated will be the same. The current time (in
milliseconds) is used if no seed is specified for the Random class.

1.7.2.1 Creating an instance of the Random class

Random random = new Random(); // Create a new instance of the Random class
// without specifying a seed.

Random random2 = new Random(8); // Create a new instance of the Random class
// specifying a seed value of 8

1.7.2.2 Using the Random class


The syntax for retrieving a random number from an instance of the Random
class is as follows:

// Get the next random number in the sequence.


int randomNumber = random.Next();

To get another number, simply call the Next()method again.

A maximum value may be specified for the random number. Note that the
returned value will always be less than the maximum value.

// Get the next random number between 0 and 4.


int randomNumer = random.Next(5);

Both the minimum and the maximum value of the range for a random number
may be specified.

// Get the next random number between 3 and 11.


int randomNumer = random.Next(3, 12);

The Random class can also return numbers as the double data type.

// Get the next random number between 0.0 and just below 1.0.
int randomNumer = random.NextDouble();

Basic C# Programming | V1.0 August 2015 Page 82 of 276


1.7.3 Exercises
1. In which namespace are the Math and Random classes both
stored?

2. Write a console program that calculates the area of a semi-


circle based on the radius supplied by the user (semi circle
area = (π * r2) / 2).

3. Write a console program that generates random numbers


until the user chooses to stop.

1.7.4 Revision questions


1. True/False: It is possible to round a number off to any
decimal position.

2. True/False: To obtain the value of PI for a calculation you


can simply call Math.PI.

3. True/False: An instance of the Math class is needed to


generate random numbers.

Basic C# Programming | V1.0 August 2015 Page 83 of 276


1.8 Test Your Knowledge (Unit 1 – Self-Test)

The questions in this section are similar to those asked in the


examination. Try answering these questions and then check the
answers with the lecturer. The questions are taken from the
study guide and textbook. The questions comprise theory and
application questions which will be in multiple choice, multiple
response, true/false and selection formats. Allow about 20
minutes for all the questions.

Multiple choice

1. Which one of the following is not contained within a class?


a. Methods
b. Properties
c. Namespaces
d. Variables

2. What is the output of the following code?

public static void Main(string[] args)


{
Console.Write("This ");
Console.WriteLine("is ");
Console.Write("a ");
Console.Write("test string.");
}

a. This is a test string.


b. This is
a
test string.
c. This is
a test string.
d. This is a
test string.

3. Which one of the following would be the most appropriate variable type
for variable x?

x = 'a';

a. uint
b. byte
c. int
d. char

Basic C# Programming | V1.0 August 2015 Page 84 of 276


4. What is the output of the following code?

public static void Main(string[] args)


{
string userName = "Gerald";

Console.WriteLine("Hello, " + "userName");


}

a. Hello, Gerald.
b. Hello, userName.
c. Hello, {0}.
d. Hello, {Gerald}.

5. Which one of the following is an example of explicit casting?


a. int x = 10 * 2;
b. int x = (int)3.14 * 2;
c. double x = 3.14*2;
d. double x = 3.14*2.0;

6. Which one of the following methods is inherited by every class?


a. StringValue()
b. ToString()
c. ValueOf()
d. Namespace()

True/False

1. True/False: The Common Intermediate Language was previously known


as the Microsoft Intermediate Language (MSIL).

2. True/False: The following code will compile:

public static void Main(string[] args)


{
int myResult = ((42/6) == 7) ? 42 : 7;
Console.WriteLine("The meaning of life, the universe and everything is "
+ myResult + ".");
}

Multiple response

1. A long value type can be implicitly converted to which of the following


three types?
a. decimal
b. float
c. int
d. double
e. ulong
f. char

Basic C# Programming | V1.0 August 2015 Page 85 of 276


2. Study the code below:

public static void Main(string[] args)


{
int x = 5;
int y = 12;
int z = 3;

if(***)
{
Console.WriteLine("Condition met!");
}
}

Which three of the following could be used in the above if statement to


make the program display the text ‘Condition met!’?

a. (x < y) & (z < y)


b. (x > y) & (z < y)
c. (x > z) & (x > y)
d. (x > z) | (x > y)
e. (z < x) & (y > z)
f. (z > x) | (y < x)

Selection

1. Match the description with its type:


a. Contains a numerical value that includes a decimal
float
point.
b. Contains a number of values that must all be of the
string
same type.
c. Can act as a flag to check whether something is true
struct
or false.
d. Contains a list of constant values. long
boolean
enum
array

Basic C# Programming | V1.0 August 2015 Page 86 of 276


Unit 2 – The C# Language

This unit introduces you to object and component programming with C#.
Classes and objects will be covered in more depth.

This unit counts 10% towards part A of the C# mark, and you will have 12
days to complete it. The time and marks are scheduled as follows:

Reading 10 days
Exam preparation and exam 2 days 10%

Basic C# Programming | V1.0 August 2015 Page 87 of 276


2.1 Using classes in C#

Atthe end of this section you will be able to:


 Understand the concepts behind classes.
 Understand what makes up a class.
 Use accessibility modifiers for instance and static members
and methods.
 Understand what constructors and destructors are.
 Use properties and indexers.

2.1.1 Basic anatomy of a class

A class is made up of class members and has the following structure:

class ClassName
{
// Variables you are going to use in the code below.
string myStr;

// Methods you are going to use in the code below.


public void DisplayStr()
{
Console.WriteLine(myStr);
}
}

Figure 18 shows the elements that form part of classes.

class ClassName { <Nested_types>


<Class_members> => <Nested_classes>
} => <Nested_structs>
=> <Nested_enums>

<Class_members>
=> <Data_members> <Function_members>
=> <Function_members> => <Methods>
=> <Nested_types> => <Constructors>
=> <Destructor>
=> <Properties>
=> <Indexers>
<Data_members>
=> <Operators>
=>
<Member_variables>
=> <Constants>
=> <Events>

Figure 18 – Elements that form part of classes

Basic C# Programming | V1.0 August 2015 Page 88 of 276


The components are explained in greater detail in Figure 19.

* Member variables are used to represent data and they


can belong to the class (static variables). If the
variables form part of an object, they are called
‘instance variables’.
class ClassName { * Events are declared similarly. Events will be covered in
<Data_members> later units.
=> <Member_variables> * The class members can be declared in different orders.
=> <Constants> * A function member can also be static (belonging to the
=> <Events> class), or an instance method.
<Function_members> * Constructors and destructors are called when objects
=> <Methods> are created and destroyed.
=> <Constructors> * Properties are treated as member variables, but they
=> <Destructor> contain statements which are executed when the
=> <Properties> property is accessed. Properties will be covered in this
=> <Indexers> unit.
* Indexers are used with classes which are mainly used as
=> <Operators>
arrays and allow convenient array-like access to an
<Nested_types>
array within a class.
=> <Nested_classes>
* You may want to have a statement such as:
=> <Nested_structs>
totObj = Obj1 + Obj2.
=> <Nested_enums> This can be achieved using operator overloading. This
} will be covered later in this unit.
* Nested types are classes, structs, enums, and interfaces
defined within the class body. They allow the
programmers to keep the types hidden from users and
reduce the number of classes at which an assembly user
needs to look.

Figure 19 – Class members explained

2.1.2 Instance and static methods

Methods are also known as ‘behaviours’ and ‘functions’. Furthermore, these are
divided into instance and static methods.

Static methods
A method that is static belongs to the class, not the instance from which it is
called. Due to this, static methods cannot access any members that are not
static themselves.

Static methods, unlike instance methods, can be used without instantiating an


object first. Static methods are most commonly used to perform calculations
where the data used is not part of the class to which the static method
belongs.

One additional benefit of static methods is not so obvious – as static methods


are specific to the class and not the instance, there is only ever one version of
that method stored in memory at any given time.

Instance methods
Instance methods are invoked on an instance of a class. In this case, the
method belongs to that instance, as opposed to belonging to the class itself.

Basic C# Programming | V1.0 August 2015 Page 89 of 276


Therefore, an instance method can access all members that belong to that
instance, in addition to any static members.

Note that any method that is not declared as static automatically becomes an
instance method.

Consider the following example of static methods:

public class MortgageCalculations


{
private MortgageCalculations()
{
}

public static decimal MonthlyPayment(decimal rate, decimal price, int


years)
{
// Implementation.
}

public static decimal TotalInterest(decimal rate, decimal price, int


years)
{
// Implementation.
}

public static void PrintSchedule(decimal rate, decimal price, int years)


{
// Implementation.
}
}

These methods could then be used as follows, without first declaring an


instance of the MortageCalculations class:

decimal myPayment = MortageCalculations.MonthlyPayment(0.45, 25000, 10);


decimal myTotalInterest = MortageCalculations.TotalInterest(0.45, 25000, 10);
decimal PrintSchedule = MortageCalculations.PrintSchedule(0.45, 25000, 10);

2.1.3 Accessibility modifiers

Accessibility modifiers are useful keywords that are incorporated when a


programmer wants to restrict access to certain classes or namespaces. They
are also useful when a programmer wants to restrict inheritance. The access
modifiers in Table 10 have been arranged from the least access to the most
access, as indicated by the arrow on the left.

Table 10 – Access modifiers


Access level Same class Same program Inheriting class Other classes
private  × × ×
protected  ×  ×
internal   × ×
protected internal    ×
public    

Basic C# Programming | V1.0 August 2015 Page 90 of 276


The three most commonly used accessibility modifiers will now be examined.

2.1.3.1 Public modifier


When a public modifier is used, the member or class can be accessed by any
other code in the same project or another project that references it.

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

namespace Test
{
class PubPoint
{
// Public variables declared.
public int x;
public int y;
}

class MainClass
{
static void Main()
{
PubPoint pp = new PubPoint();

// Direct access to public members:


pp.x = 10;
pp.y = 15;
Console.WriteLine("x = {0}, y = {1}", pp.x, pp.y);
}
}
}

The result is:

x = 10, y = 15

2.1.3.2 Protected modifier


When the protected modifier is used, the member is only accessible within (a)
the class in which it was declared, and (b) any derived classes.

The example below demonstrates how the protected modifier is used.

// Namespaces automatically added when a new Console project is created.


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

namespace Test
{
class P
{
// Protected variable is declared and initialized.
protected int x = 123;
}

class Q : P

Basic C# Programming | V1.0 August 2015 Page 91 of 276


{
static void Main()
{
P p = new P();
Q q = new Q();

/* Error CS1540, because x can only be accessed by


classes derived from P. */
// p.x = 10;

// Allowed because this class derives from P.


q.x = 10;
Console.WriteLine(q.x);
}
}
}

The result is:

10

2.1.3.3 Private modifier


When the private modifier is used, the member or class is accessible only
within the class in which it is declared. An example of how the private modifier
is used is given below:

class Employee
{
private int i;
// Private access by default.
double d;
}

2.1.4 Fields

Fields store the data that is necessary in order for the program to function. For
example, a class called ReleaseDate might contain three integer fields: one for
day, one for month and one for year. Fields are declared in the class block by
specifying the access level of the field, followed by the type of the field, and
then the name of the field.

public class ReleaseDate


{
public int month;
// Or initialize the month field in this step:
// public int month = 7;
public int day;
public int year;
}

It can be accessed in the following way:

ReleaseDate release = new ReleaseDate();


release.month = 7;

A field is an instance variable.

Basic C# Programming | V1.0 August 2015 Page 92 of 276


2.1.4.1 Static and instance fields
Static fields in a field declaration are introduced by a static modifier. When no
static modifier is present, those fields are instance fields. The static keyword
needs to be present otherwise it is an instance of the class. A static field is not
part of a specific instance. No matter how many instances of a class are
created, there will always only be one copy of a static field. A class of vehicles
such as Sedan or Truck, will have the methods/behaviours and attributes that
apply to that class in the class itself, and not in the Vehicle class. The Vehicle
class and its sub-classes are shown in Figure 20.

Vehicle

numWheels
numDoors
numPassengers
speedKPH

Move()
Fill()

Sedan Aeroplane Truck Taxi

numWheels = 4 numWheels = 8 numWheels = 2 numWheels = 6


numDoors = 4 numDoors = 6 numDoors = 4 numDoors = 3
numPassengers=4 numPassengers=300 numPassengers=2 numPassengers=125
speedKPH = 100 speedKPH = 500 speedKPH = 60 speedKPH = 130
openRoof airlineType tonnage

Fly() Load() Hoot()


Unload() StopAnywhere()

Figure 20 – The Vehicle class and its sub-classes

The Vehicle class has two methods: Move() and Fill(). It has four attributes
(fields) called numWheels, numDoors, numPassengers and speedKPH.
Remember that attributes describe the object, whereas methods are the
behaviours of the object.

Static fields belong to the class itself; instantiated objects cannot see this field.
Therefore, static fields need to be accessed using the className.VariableName
notation, as opposed to instanceName.VariableName.

2.1.4.2 read-only and const fields


It is important to know when to use read-only fields and when to use const
fields. When the value of a field is known and it remains unchanged, a constant
should be used. Constant fields can be read as many times as necessary, but
they cannot be modified. The example below shows how to declare a const
field:

Basic C# Programming | V1.0 August 2015 Page 93 of 276


const string http = "http://";

It is also important to know the difference between read-only and const fields.
The read-only and const fields are similar in that neither of them can be
modified. The difference between them is when they are initialised. Const fields
are initialised during compilation, and read-only fields are initialised during
runtime. A read-only field can only have a value assigned to it in two ways: (a)
in the initialisation statement, or (b) in the constructor of the class in which the
field was declared. Attempting to modify the value in any other manner will
throw a compilation error.

2.1.5 Constructors

The primary purpose of a constructor is to initialise an object. In other words,


constructors are intended to set the initial state of a class field. There are two
types of constructors: static and instance.

An instance constructor is meant to initialise instance fields. These constructors


provide a central place to instantiate class fields. They also have the ability to
alter the initial values of fields, based on arguments passed to the instance of
the class when it is created. Constructors are only invoked on instantiation and
cannot be called by other programs later. This is done to preserve the integrity
of the class.

Constructors have the same name as the class of which they are members.
Constructors do not return values (i.e. they have no return type) and they can
accept as many parameters as needed.

There is a defined order when an object is initialised:

1. Class field initialisation. Firstly, each field is initialised before any


constructor tries to access it.
2. Other constructors can then be called (using the this operator).
3. Statements within the code block of the constructor are then executed.

Constructors are normally declared as public, but sometimes a private


constructor will be necessary. A single private constructor can prevent a class
from being derived or instantiated, meaning that another class cannot inherit
from it.

The example given below is very similar to the one discussed earlier in static
methods.

Basic C# Programming | V1.0 August 2015 Page 94 of 276


public class MortgageCalculations
{
private MortgageCalculations() {}

public static decimal MonthlyPayment(decimal rate, decimal price, int


years)
{
// Implementation.
}

public static decimal TotalInterest(decimal rate, decimal price, int years)


{
// Implementation.
}

public static void PrintSchedule(decimal rate, decimal price, int years)


{
// Implementation.
}
}

A static constructor is invoked when a class is loaded, i.e. a static constructor


is only invoked once each time the program runs. Each class is also only
loaded once during the lifetime of the execution of a program. Static
constructors are invoked automatically before any instances of the class are
instantiated.

Static constructors can only access static fields. Classes are loaded before any
instances are created; thus instance fields may not yet have been initialised.
At this point, not even the instance constructor has been invoked. In some
cases, it may never be invoked. Static constructors are primarily used to
initialise the class.

Below is an example of a static constructor.

public class Randomizer


{
private static int result;

static Randomizer()
{
// The current date is stored in a variable.
DateTime dt = DateTime.Now;
result = dt.GetHashCode();
}
}

Static constructors are very similar to instance constructors in that (a) they do
not have a return type, and (b) they share their name with the class in which
they are declared. However, they cannot accept parameters.

Static constructors cannot be called by any programs. They are only invoked
when a class is loaded. Unlike an instance constructor, a static constructor has
no specific sequence of operations for when it is invoked, but there are a few
conditions.

Basic C# Programming | V1.0 August 2015 Page 95 of 276


The class is loaded:

 Before the first instance is created.


 Prior to accessing static members.
 Ahead of any derived types.
 Once per program execution.

2.1.5.1 Why are constructors needed?


When an object is created, memory needs to be allocated for that object. The
memory allocated must also be cleared. If the memory for variables is not
properly initialised, the result could be that garbage data is stored in the
variables. This concept is illustrated in Figure 21:

Got a new object. Need OK. Use this space. Used to have
memory. some data but anyway…

0001010101
Num newNum1

Figure 21– Assigning memory that contains garbage data

When the newNum1 variable is accessed, the garbage data that was stored in
memory is loaded. This is why C# offers many features to assist initialisation
of variables.

The instance variable declaration allows the initial value for the instance
variables to be specified, and any instance variables that have not been
explicitly assigned a value will automatically get default values during runtime.
Constructors are called whenever an instance of a class is created. If a
constructor is not provided, an empty one will be used.

The example below shows how constructors are used:

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

namespace ConstructorExample
{
class ConstructorEx
{
string greeting;
string name;

// The constructor is created.


public ConstructorEx()
{
// "this" keyword.
this.greeting = "Hello ";
Console.WriteLine("Enter your name: ");
// "ReadLine()" receives input from the user.

Basic C# Programming | V1.0 August 2015 Page 96 of 276


name = Console.ReadLine();
// "greeting" and "name" are displayed to the console.
Console.WriteLine(greeting + name);
}

static void Main(string[] args)


{
// Creates a new instance of the constructor.
ConstructorEx ce = new ConstructorEx();
}
}
}

The following output is produced when Angelique is entered:

Enter your name:


Angelique
Hello Angelique

In this example, a constructor called ConstructorEx() is created and in the


Main class a new instance of the constructor is created. The constructor
declares two string variables. The name variable is used to later store input
that is received from the user. Remember that constructors cannot return a
value.

2.1.5.2 The this keyword


The this keyword refers to the current instance of a class and is used to
avoid ambiguity. The this keyword cannot be used in static classes or methods
because it would be illogical. In a static method, there is no instance to which
the keyword can refer.

The following example shows the use of the this keyword:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace thisExample
7 {
8 class thisEx
9 {
10 string greeting;
11
12 public thisEx(string greeting)
13 {
14 this.greeting = "Hello there!";
15 Console.WriteLine("Instance variable greeting: " +
16 this.greeting);
17 Console.WriteLine("This is the parameter received: " + greeting);
18
19 // Setting the instance variable to the parameter:
20 this.greeting = greeting;
21 Console.WriteLine("Changed the instance variable to: " +
22 this.greeting);
23 }
24
25 static void Main(string[] args)

Basic C# Programming | V1.0 August 2015 Page 97 of 276


26 {
27 thisEx te = new thisEx("Set!");
28 }
29 }
30 }

The result is:

Instance variable greeting: Hello there!


This is the parameter received: Set!
Changed the instance variable to: Set!

To fully understand this concept, it is recommended that line 20 is


commented-out to see how the output changes.

If a constructor is declared as private, the C# compiler will not be able to call


the default constructor. The class cannot be instantiated because the
constructor is inaccessible. This can be useful if a class is used mainly for its
static members and therefore not meant to be instantiated (for example, the
Math class).

2.1.6 Destructors

A destructor implements finalisation code when an object is no longer being


referenced or is destroyed. A destructor, however, is not guaranteed to be
called and it is also unknown at what time exactly it will be called.

A destructor is defined as follows:

~WebSite() {}

The ‘~’ symbol is called a tilde and all destructors begin with this symbol. Their
parameter list is always empty and they do not return any values.

Also keep in mind:

 Each class can only have one destructor.


 Destructors cannot be inherited or overloaded.
 Destructors cannot be called. They are invoked automatically.
 A destructor does not use accessibility modifiers or take parameters.

2.1.6.1 Garbage collection


The Garbage Collector is a built-in mechanism that is used to free resources
used by objects. Memory is limited and it is therefore very important to reclaim
memory as soon as an object is no longer in use. The Garbage Collector has
two functions:

 Detecting unreachable objects and reclaiming their spaces in memory.


 Determining when an object is no longer in use and then destroying that
object. It calls the destructor method of the object when destroying an
object.

Basic C# Programming | V1.0 August 2015 Page 98 of 276


The Garbage Collector constantly checks which objects are no longer being
used and then calls the objects’ destructor in order to return the memory to
the collection of available memory. However, the Garbage Collector is not
guaranteed to collect at any point during execution. To prompt the garbage
collection, the following method is called:

System.GC.Collect();

However, this does not necessarily guarantee that garbage collection will
occur. It is always important to take care about how a destructor method is
implemented, or problems could arise.

2.1.6.2 Destructors’ work


Freeing up memory is important, but freeing up files and network/database
connections is even more important. To ensure that an object promptly frees
the resources, the actions to be taken when the object is destroyed must be
specified.

Just as every class has a default constructor, so every class has a default
destructor. The constructor is called when an object is instantiated with the
new keyword. Only the Garbage Collector can call destructors.

Specifying destructors is costly because the Garbage Collector has to do far


more work. An object without a destructor specified will still be claimed, but
objects with destructors are flagged first. The Garbage Collector always
executes the instructions within the destructor before claiming memory the
next time it works. Therefore, the object requires the Garbage Collector to
work more, and memory is occupied for longer periods of time. Unless there
are files or network/database connections that must be released, it is
recommended to avoid the use of destructors.

2.1.7 Indexers

Indexers allow instances of a class to be indexed just like an array. They are
similar to properties with one important difference: their accessors take
parameters. Recall that a get accessor returns a value and a set accessor
(referred to as a mutator) assigns a value.

The this keyword defines the indexers, and the value keyword is used to define
the value being assigned by the set indexer. Indexers can have more than one
formal parameter, for example, when accessing a two-dimensional array.

The following example shows how indexers can be used:

1 // Namespaces automatically added when a new Console project is created.


2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6

Basic C# Programming | V1.0 August 2015 Page 99 of 276


7 namespace Chocs
8 {
9 class ChocolateBars
10 {
11 private string[] chocolates = new string[3];
12
13 public string this[uint index] // uint is a type of integer which
14 { // only accepts positive values
15 get
16 {
17 return "on the shelf is: " + chocolates[index];
18 }
19
20 set
21 {
22 chocolates[index] = value;
23 }
24 }
25 }
26
27 class IndexerTest
28 {
29 static void Main()
30 {
31 ChocolateBars cb = new ChocolateBars();
32
33 cb[0] = "MintCrisp";
34 cb[1] = "BarOne";
35 cb[2] = "Tempo";
36
37 Console.WriteLine("The first chocolate " + cb[0]);
38 Console.WriteLine("The last chocolate " + cb[2]);
39 Console.WriteLine("The second chocolate " + cb[1]);
40 }
41 }
42 }

On line 11, a private string array is declared. On line 13, the indexer for this
class is declared. Note that the this keyword is used. This means that a static
indexer is not allowed. The this keyword is used because the indexer itself has
no name. On lines 37 to 39, the name of the object is simply being used to
access the indexer, e.g. cb[0]. The syntax cb.chocolates[0] is not used.

The result is:

The first chocolate on the shelf is: MintCrisp


The last chocolate on the shelf is: Tempo
The second chocolate on the shelf is: BarOne

Basic C# Programming | V1.0 August 2015 Page 100 of 276


2.1.8 Exercises
1. What are the different class members?

2. List the two types of methods and explain them.

3. When would you make use of a private modifier?

4. Read-only and const fields are very similar. What is the


characteristic that sets them apart?

5. What keyword can be used for the current instance of a


class?

6. What is another name for a field?

7. Why are constructors needed?

8. Explain what the System.GC.Collect() command is used


for.

9. Explain the difference between passing reference


arguments and passing value arguments.

10. Write a method that accepts an array of numbers as a


parameter. The method should multiply each number by
four and add one, and display the result. Call this
method, passing to it an array of any three integers.

2.1.9 Revision questions


1. What can be used to index instances of a class?
a. Methods
b. Contents
c. Constructors
d. Indexers

2. True/False: A class is loaded as the first instance is


created.

3. True/False: Only the Garbage Collector can call


destructors.

4. True/False: Garbage collection can happen automatically


in some instances.

5. Which one of the following is not a method modifier?


a. internal
b. abstract
c. external
d. virtual

Basic C# Programming | V1.0 August 2015 Page 101 of 276


2.2 Object-oriented programming basics

At the end of this section, you will be able to:


 Understand inheritance.
 Encapsulate object internals.
 Understand and apply polymorphism.

2.2.1 Inheritance

2.2.1.1 Base classes


In Unit 1 the concept of how one class can inherit from another was explored.
The following code is an example of inheritance in action:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace BaseClassExample
8 {
9 public class Mammal
10 {
11 protected string name = "Rudolph the Dolphin";
12 protected string species = "Bottle nose dolphin";
13
14 public virtual void GetInfo()
15 {
16 Console.WriteLine("Name: {0}", name);
17 Console.WriteLine("Species: {0}", species);
18 }
19 }
20
21 class Dolphin : Mammal
22 {
23 public string age = "6";
24
25 public override void GetInfo()
26 {
27 // Calling the base class GetInfo method:
28 base.GetInfo();
29 Console.WriteLine("Age: {0}", age);
30 Console.ReadLine();
31 }
32 }
33 class BaseClassEx
34 {
35 public static void Main()
36 {
37 Dolphin d = new Dolphin();
38 d.GetInfo();
39 }

Basic C# Programming | V1.0 August 2015 Page 102 of 276


40 }
41 }

On line 21, the Dolphin class (which inherits the Mammal class) is defined. On
line 25, the GetInfo() method, which was created on line 14, is overridden. This
means that the GetInfo() class is available to the Mammal class and to the
Dolphin class. On lines 11 and 12, variables are declared protected. This allows
the BaseClassEx class on line 33 (which is in the same file) to access the
variables. The protected keyword allows access to all of its sub-classes.

In the above example, three classes are defined, namely: Mammal, Dolphin and
BaseClassEx. The Mammal class has two variables that have been declared
using the protected modifier. Due to these variables being protected, they are
only accessible within (a) the class in which they were declared (Mammal), and
(b) any class that is derived from that class (in this case, Dolphin). The
Mammal class also implements a virtual method called GetInfo(). When a
method is declared as being virtual, derived classes can declare their own
implementations of the method and override the existing one.

The result is:

Name: Rudolph the Dolphin


Species: Bottle nose dolphin
Age: 6

2.2.1.2 Abstract classes


An abstract class cannot be instantiated. The purpose of an abstract class is to
provide a common definition for a base class that multiple derived classes can
share. For example: a class library may define an abstract class that is used as
a parameter for many of its functions, and require programmers using that
library to provide their own implementation of the class by creating a derived
class.

It makes sense that a Dolphin is a Mammal, and that there is an instance of a


Dolphin, but does it make sense to have a Mammal object? In this case, it
would be appropriate to make the Mammal class abstract. An abstract class
can declare abstract methods which can then be implemented in sub-classes
specific to their needs.

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace AbstractExample
7 {
8 abstract class Mammal
9 {
10 abstract public void MakeSound();
11 }
12
13 class Dolphin : Mammal
14 {
15 public override void MakeSound()

Basic C# Programming | V1.0 August 2015 Page 103 of 276


16 {
17 Console.WriteLine("Dolphin class entered: Dolphins live in " +
18 "the ocean");
19 }
20 }
21
22 class Bear : Mammal
23 {
24 public override void MakeSound()
25 {
26 Console.WriteLine("Bear class entered: Bears live on land");
27 }
28 }
29
30 class AbstractEx
31 {
32 static void Main(string[] args)
33 {
34 Dolphin d = new Dolphin();
35 Bear b = new Bear();
36 Console.WriteLine("Create a dolphin and a bear");
37 d.MakeSound();
38 b.MakeSound();
39 }
40 }
41 }

On line 8, the Mammal class is declared as abstract. On line 10, a method


called MakeSound() is declared as abstract. Note how abstract methods are
declared – they do not have method bodies. On lines 15 and 24, the abstract
method MakeSound() is implemented differently by two different classes which
inherit from the Mammal class. In other words, they are overridden in order to
produce an outcome specific to the class in which they are declared. Make sure
to remember the override keyword. This keyword specifies that the method is
overriding a method from the base class. On lines 37 and 38, the overriding
methods MakeSound() are called.

Run the program. The result is:

Create a dolphin and a bear


Dolphin class entered: Dolphins live in the ocean
Bear class entered: Bears live on land

2.2.1.3 Calling base class members


When a class inherits from a base class, and depending on the access level of
the base class member, the inheriting class can access the base class members
directly. The following example illustrates this:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace CallingBaseClassMembersExample
7 {
8 class Mammal
9 {
10 protected string declaration = "Dolphins swim faster than humans!";

Basic C# Programming | V1.0 August 2015 Page 104 of 276


11 }
12
13 class Dolphin : Mammal
14 {
15 static void Main(string[] args)
16 {
17 Dolphin d = new Dolphin();
18 Console.WriteLine(d.declaration);
19 }
20 }
21 }

The Dolphin class inherits from the Mammal class on line 13. On line 10, the
Mammal class only has one attribute, called declaration; because it is a
protected member, it can be accessed by inheriting classes.

Run the program. The result is:

Dolphins swim faster than humans!

2.2.1.4 Hiding base class members


It is impossible for a derived class to declare an operator with the same
signature as another operator in a base class. Thus, operators never hide one
another. Hiding an accessible name from an inherited scope causes a warning.
This concept is shown in the example below:

class Base
{
public void Var()
{

}
}

// The Derived class inherits from the Base class.


class Derived : Base
{
public void Var()
{
// Warning, hiding an inherited name.
}
}

The following example demonstrates this concept more clearly:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace HidingBaseClassMembersExample
8 {
9 class Mammal
10 {
11 protected string declaration = "Dolphins swim faster than humans!";
12 }
13
14 class Dolphin : Mammal

Basic C# Programming | V1.0 August 2015 Page 105 of 276


15 {
16 private string declaration = "Dolphins actually swim faster than" +
17 " ALL mammals!";
18
19 static void Main(string[] args)
20 {
21 Dolphin d = new Dolphin();
22 Console.WriteLine(d.declaration);
23 Console.ReadLine();
24 }
25 }
26 }

Although a warning message is produced, the program will still compile and
execute. This is because Dolphin.declaration is being hidden. The following
warning will be displayed in the Error List at the bottom of the screen shown in
Figure 22:

Figure 22 – Warning message

The result is:

Dolphins actually swim faster than ALL mammals!

The string declaration in the Dolphin class on line 16 is shadowing the


declaration variable in the Mammal class on line 9. Therefore, "Dolphins swim
faster than humans!" will not be printed.

2.2.1.5 Versioning
It may seem inconvenient that a class member which has the same name as
any of the names in the base class cannot be used. However, this is not true.
The compiler issues warning messages because such coding can cause subtle
bugs which were hard to trace in earlier programming languages.

The following example shows how the previous program has been modified to
run without any warning messages being displayed.

Basic C# Programming | V1.0 August 2015 Page 106 of 276


1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace HidingBaseClassMembersExample
8 {
9 class Mammal
10 {
11 protected string declaration = "Dolphins swim faster than humans!";
12 }
13
14 class Dolphin : Mammal
15 {
16 new private string declaration = "Dolphins actually swim faster” +
17 “ than ALL mammals!";
18
19 static void Main(string[] args)
20 {
21 Dolphin d = new Dolphin();
22 Console.WriteLine(d.declaration);
23 Console.ReadLine();
24 }
25 }
26 }

NOTE The declaration for declaration in the Dolphin class on line 16 now has
the new keyword in front of the declaration. This alerts the compiler
about the base class member declaration which is being hidden.

When the program is run, it should now compile and execute without any
warning messages being displayed.

2.2.1.6 Sealed classes


Declaring a class as sealed prevents other classes from inheriting it. Because
sealed classes cannot be derived from, they cannot be used as a base class. A
sealed class cannot be both sealed and abstract at the same time. When a
method is sealed, it means it cannot be overridden. The code below is an
example of how to create a sealed class:

abstract class Encryptor


{
public string Encrypt(string unencryptedString, string key)
{
}

public string Decrypt(string encryptedString, string key)


{
}
}

sealed class MyEncryptor : Encryptor


{
public string Encrypt(string unencryptedString, string key)
{
// Implementation.
}

Basic C# Programming | V1.0 August 2015 Page 107 of 276


public string Decrypt(string encryptedString, string key)
{
// Implementation.
}
}

In the above example, the abstract class called Encryptor is intended to be


used to encrypt and decrypt strings. The abstract class MyEncryptor is derived
from Encryptor. In this class, methods are created to encrypt and decrypt data
in a unique way which must not be modified by any other class.

To ensure this, the class is declared sealed, so that other classes cannot inherit
from it and modify its behaviour. If another class attempts to derive from the
MyEncryptor class, the application will not compile.

2.2.2 Encapsulating object internals

2.2.2.1 Data-hiding and modifiers supporting encapsulation


Data-hiding is one of the most useful forms of encapsulation. Encapsulation
allows programmers to hide critical data from users, thereby preventing data
corruption. Careful consideration should be given when deciding which classes
to encapsulate, and how to implement that encapsulation. The way in which
this is implemented varies according to the requirements of the program. A
thorough grasp of the access levels explained in section 2.1.3 Accessibility
modifiers, is recommended.

2.2.3 Polymorphism

2.2.3.1 Implementing polymorphism


The following example shows two classes, both of which inherit from the
Mammal class. Although the inheriting classes all override the Movement()
method, each one implements it differently.

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace ImplementingPolymorphismExample
8 {
9 class Mammal
10 {
11 public virtual void Movement() { }
12 }
13
14 class Dolphin : Mammal
15 {
16 public override void Movement()
17 {
18 Console.WriteLine("Dolphins swim!");
19 }
20 }
21

Basic C# Programming | V1.0 August 2015 Page 108 of 276


22 class Bear : Mammal
23 {
24 public override void Movement()
25 {
26 Console.WriteLine("Bears run!");
27 }
28 }
29
30 class ImpPolymorphismEx
31 {
32 static void Main(string[] args)
33 {
34 Console.WriteLine("Creating mammals...");
35 Mammal[] mammals = { new Dolphin(), new Bear() };
36
37 foreach (Mammal mam in mammals)
38 {
39 //Call the method.
40 mam.Movement();
41 }
42
43 Console.ReadLine();
44 }
45 }
46 }

On line 35, an array is created with two objects. On line 37, a foreach loop is
used to iterate through all the elements of the array. Note that the type is
declared as Mammal. They are implicitly of the Mammal type because all the
classes inherit from the Mammal class. They all share the Movement() method,
but each class implements it differently. This demonstrates the concept of
polymorphism.

The result is:

Creating mammals...
Dolphins swim!
Bears run!

2.2.3.2 Most-derived implementations


In the previous example, each of the three derived classes implemented their
own versions of the Movement() method. When the Movement() method was
called on instances of those classes, the most-derived implementation of the
method (i.e. the lowest implementation in the class hierarchy) was executed.

In Figure 23 three classes are declared, namely: Vehicle, LandVehicle and Car.
LandVehicle is derived from Vehicle, and Car is derived from LandVehicle.
Vehicle defines a virtual method called Drive(), and the Car class overrides that
method. LandVehicle does not override the Drive() method.

Basic C# Programming | V1.0 August 2015 Page 109 of 276


public virtual void Drive()
Vehicle {
Console.WriteLine(“Vehicle driving!”);
Drive()
}

LandVehicle

public override void Drive()


Car {
Console.WriteLine(“Car driving!”);
Drive() }

Figure 23 – Most-derived implementations

The following code could be used to test these classes:

// Declare an instance of each class.


Vehicle v = new Vehicle();
LandVehicle lv = new LandVehicle();
Car c = new Car();

// Call the Drive() method for each class.


v.Drive();
lv.Drive();
c.Drive();

The result is:

Vehicle driving!
Vehicle driving!
Car driving!

As is evident from the above example, when a method is called, the most-
derived implementation of that method is always executed. When the Drive()
method is called on the LandVehicle instance:

1. The application first checks the class itself (LandVehicle) to see if the
method exists, and finds that it does not.
2. The application then checks the Vehicle class (the class from which
LandVehicle is derived) to see if the method is defined there, and finds a
matching implementation.
3. That method implementation is then executed.

However, when the Drive() method is called on an instance of Car:

1. The application checks the class itself (Car) to see if the method exists,
and finds a matching implementation.
2. That method implementation is then executed.

Basic C# Programming | V1.0 August 2015 Page 110 of 276


2.2.3.3 Polymorphic properties
Properties, much like methods, can also be overridden. The following code is
an example of this:

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

namespace PolymorphicProperties
{
abstract class Person
{
protected string name;
protected string surname;

public virtual string Details


{
get
{
return name + " " + surname;
}
}

public Person(string name, string surname)


{
this.name = name;
this.surname = surname;
}
}
}

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

namespace PolymorphicProperties
{
class Friend : Person
{
protected string telNo;

public override string Details


{
get
{ // '\n' is a newline character.
return name + " " + surname + "\n" + telNo;
}
}

public Friend(string name, string surname, string telNo)


: base(name, surname)
{
this.telNo = telNo;
}
}
}

Basic C# Programming | V1.0 August 2015 Page 111 of 276


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

namespace PolymorphicProperties
{
class Program
{
static void Main(string[] args)
{
Friend f = new Friend("John", "Doe", "0119998823");

Console.WriteLine(f.Details);
Console.ReadLine();
}
}
}

The result is:

John Doe
0119998823

2.2.3.4 Polymorphic indexers


Indexers can be polymorphic. The same indexer may be used in both the base
and the derived classes. These indexers are ‘overridden indexers’ and, just like
methods, require the virtual keyword to be stated in their declaration in the
base class. The program below illustrates this concept.

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

namespace PolymorphicIndexers
{
class PersonList
{
protected string[] names;
protected string[] surnames;

// Constructor.
public PersonList(int numPeople)
{
names = new string[numPeople];
surnames = new string[numPeople];
}

// Indexer.
public virtual string this[int index]
{
get
{
// If the index is invalid.
if (names.Length < index || names[index] == "")
{
return "Nobody";
}

Basic C# Programming | V1.0 August 2015 Page 112 of 276


return names[index] + " " + surnames[index];
}
set
{
// If value is not null and at least 3 characters in length
// (must be at least 3 characters in length so that we can have
// a name and a surname)
// i.e. "n s" name == "n", surname == "s"
if (value != null & value.Length >= 3)
{
names[index] = value.Substring(0, value.IndexOf(' '));
surnames[index] = value.Substring(value.IndexOf(' ') + 1);
}
}
}
}
}

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

namespace PolymorphicIndexers
{
class FriendList : PersonList
{
string[] telNumbers;

public FriendList(int numPeople)


: base(numPeople)
{
telNumbers = new string[numPeople];
}

public override string this[int index]


{
get
{
return base[index] + "\n" + telNumbers[index];
}
set
{
if (value != null & value.Length >= 5)
{
// Split the input string into the appropriate pieces.
names[index] = value.Substring(0, value.IndexOf(' '));
surnames[index] = value.Substring(value.IndexOf(' ') + 1,
value.LastIndexOf(' ') – value.IndexOf(' '));
telNumbers[index] = value.Substring(value.LastIndexOf(' ') + 1);
}
}
}
}
}

Basic C# Programming | V1.0 August 2015 Page 113 of 276


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

namespace PolymorphicIndexers
{
class Program
{
static void Main(string[] args)
{
// Create an instance of each class.
PersonList pl = new PersonList(3);
FriendList fl = new FriendList(3);

// Add sample data (using the index operator).


pl[0] = "John Doe";
pl[1] = "Jane Doe";
pl[2] = "Cameron Doe";

fl[0] = "Elle Burger 011999220";


fl[1] = "Brian Stunt 120983092";
fl[2] = "Karl Labert 012332002";

// Display the sample data (using the index operator).


Console.WriteLine("Person List: ");
for (int loop = 0; loop < 3; loop++)
{
Console.WriteLine(pl[loop]);
}

Console.WriteLine();
Console.WriteLine("Friend List: ");

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


{
Console.WriteLine(fl[loop]);
}
Console.ReadLine();
}
}
}

The result is:

Person List:
John Doe
Jane Doe
Cameron Doe

Friend List:
Elle Burger
011999220
Brian Stunt
120983092
Karl Labert
012332002

Basic C# Programming | V1.0 August 2015 Page 114 of 276


2.2.4 Exercises
1. Why can an abstract class not be instantiated?

2. What is the sealed modifier used for?

3. What access does a class member need to have to be able to


be accessible from a derived class?

4. Which access modifier provides a program with the least


restrictions?

5. Which constructors are always called automatically?

6. What is the golden rule when it comes to hiding base class


members?

7. Write an abstract class, Worker. It must contain protected


fields for name, ID number and experience level as an
integer. Create properties for the worker’s name and ID
number. Add an abstract property for the experience field.
Create an abstract method called Experience. Add two
classes, Labourer and DeskJob. These two classes must be
derived from the Worker class. Make sure they override the
property for experience, as well as the Experience method.
For the Labourer class, experience must have a range from 0
to 10. For the DeskJob class, experience must range from 0
to 20. Use the Experience method to classify a worker as a
junior or a senior. In the Labourer class, a senior is someone
who has more than 5 experience points. In the DeskJob
class, a senior is someone who has more that 12 experience
points. Override the ToString method to display the worker’s
information, e.g.: Labourer (Senior): Jake Daniels
(7401233945085)

2.2.5 Revision questions


1. True/False: Polymorphic indexers must not have the same
indexer in the base and the derived classes.

2. True/False: A derived class can access a member from its


base class if that member has public access.

3. True/False: Abstract methods are not explicitly declared as


virtual, therefore they not have to be overridden in derived
classes.

Basic C# Programming | V1.0 August 2015 Page 115 of 276


4. Which one of the following accessibility modifiers provides
access to members of another program or derived classes?
a. Private
b. Internal
c. Protected Internal
d. Protected
e. Public

Basic C# Programming | V1.0 August 2015 Page 116 of 276


2.3 Overloading class members and operators

At the end of this section you will be able to:


 Overload methods, indexers and operators.

2.3.1 Overloading methods

Method overloading helps produce code that is both reusable and easy to
understand. Different versions of a method may be defined in a class. But how
does the C# compiler know which method to call? It decides which method to
invoke based on the number and type of arguments passed to it. This is also
referred to as the signature of the method. If there are two methods with the
same name and the same number and type of passed arguments, a compile-
time error occurs. However, it is possible to have two methods with the same
name and the same number of arguments as long as the argument types differ
(i.e. the methods have different signatures).

Below is an example of how a method can be overloaded:

public class AddNumbers


{
// The 1st overloaded method.
public int Add(int a, int b)
{
return a + b;
}

// The 2nd overloaded method.


public int Add(int a, int b, int c)
{
return a + b + c;
}
}

These methods are called as follows:

public int add(int x, int y)


public int add(int x, int y, int z)

The first overloaded method requires two integer values, so the compiler will
generate code that calls this overload. The second overloaded method requires
three integer values.

Basic C# Programming | V1.0 August 2015 Page 117 of 276


NOTE Consider overloading a method when several methods are needed
that take different parameters, but basically do the same thing. Do
not use overloads when two methods do very different things, as this
will just confuse anyone who has to use these classes.

The following example shows how a method can be overloaded several times:

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

namespace OverloadingExample
{
class Program
{
static void Main(string[] args)
{
// Create an instance of this class.
Program p = new Program();
// Pause.
Console.ReadLine();
}

public Program()
{
// Call the overloaded method.
Greet();
Greet("Joseph");
// Try changing 'false' to 'true' and observe the result.
Greet("Arnold", false);
}

public void Greet()


{
Console.WriteLine("Greetings!");
}

public void Greet(string name)


{
Console.WriteLine("Greetings, " + name + "!");
}

public void Greet(string name, bool clearScreen)


{
if (clearScreen)
{
// Clear the screen.
Console.Clear();
}

// Call another version of this method.


Greet(name);
}
}
}

Basic C# Programming | V1.0 August 2015 Page 118 of 276


2.3.2 Overloading indexers

The procedure for overloading indexers is very similar to that used for
overloading methods. Several declarations for this[] can be included, each with
a different set of parameters or signature. In the following example, a class is
created which acts much like an array, except that values are stored according
to a key instead of an index. However, the values can still be accessed via an
index due to an overloaded indexer.

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

namespace OverloadingIndexers
{
class KeyedList
{
protected string[] values;
protected string[] keys;
protected int num = 0;

public KeyedList(int size)


{
values = new string[size];
keys = new string[size];
}

public string this[int index]


{
set
{
// Only allow access to elements that exist.
if (index > num | index > keys.Length)
{
throw new IndexOutOfRangeException();
}
// Set the value.
values[index] = value;
}
get
{
// Only allow access to elements that exist.
if (index > num | index > keys.Length)
{
throw new IndexOutOfRangeException();
}
// Return the value.
return values[index];
}
}

public string this[string key]


{
set
{
// Get the index of the key.
int index = GetIndexByKey(key);
// If no matches were found.
if (index == -1)
{

Basic C# Programming | V1.0 August 2015 Page 119 of 276


// Add the key to the array.
keys[num] = key;
// Set the value.
values[num] = value;
// Increment the count variable.
num++;
}
else
{
// If there was a match, set the value.
values[index] = value;
}
}
get
{
// Get the index of the key.
int index = GetIndexByKey(key);
// If a match was found.
if (index != -1)
{
// Return the value.
return values[index];
}

// Otherwise, return nothing.


return null;
}
}

private int GetIndexByKey(string key)


{
// A value of -1 will indicate that a match was not found.
int index = -1;

if (keys.Contains(key))
{
for (int loop = 0; loop < num; loop++)
{
// If a match has been found.
if (keys[loop] == key)
{
index = loop;
// Break out of the loop.
break;
}
}
}

return index;
}

public string GetKeyByIndex(int index)


{
if (index < num & index < keys.Length)
{
return keys[index];
}

return null;
}
}
}

Basic C# Programming | V1.0 August 2015 Page 120 of 276


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

namespace OverloadingIndexers
{
class Program
{
static void Main(string[] args)
{
// Create a new KeyedList.
KeyedList jobList = new KeyedList(3);

jobList["Andrew"] = "Plumber";
jobList["Harry"] = "Electrician";
jobList["Edgar"] = "Unemployed";

Console.WriteLine("Displaying by index : ");

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


{
Console.WriteLine("[" + loop + "]" + jobList.GetKeyByIndex(loop)
+ " – " + jobList[loop]);
}

Console.WriteLine();
Console.WriteLine("Displaying by key : ");
Console.WriteLine("[Andrew] – " + jobList["Andrew"]);
Console.WriteLine("[Harry] – " + jobList["Harry"]);
Console.WriteLine("[Edgar] – " + jobList["Edgar"]);
Console.ReadLine();
}
}
}

The result is:

Displaying by index :
[0]Andrew – Plumber
[1]Harry – Electrician
[2]Edgar – Unemployed

Displaying by key :
[Andrew] – Plumber
[Harry] – Electrician
[Edgar] – Unemployed

Basic C# Programming | V1.0 August 2015 Page 121 of 276


2.3.3 Overloading operators

Overloaded operators only work in the class in which they are defined and not
all operators can be overloaded, as illustrated in Table 11.

Table 11 – Operators and overloading


Operator Overloadable? Explanation
+, -, !, ~, These unary operators can be overloaded,
++, --, true,  but note that ++ and – cannot be
false
overloaded separately.
+, -, *, /, %,
&, |, ^, <<,  These binary operators can be overloaded.
>>
==, !=, <, >, These comparison operators can be

<=, >= overloaded.
These conditional logical operators cannot
&&, ||
× be overloaded, but they are evaluated using
& and|, which can be overloaded.
The array indexing operator cannot be
[ ] ×
overloaded, but you can define indexers.
The cast operator cannot be overloaded, but
( ) ×
you can define new conversion operators.
+=, -=, *=, Assignment operators cannot be
/=, %=, &=,
|=, ^=, <<=, × overloaded, but += is evaluated using +,
>>= which can be overloaded.
=, ., ?:, ->,
new, is, × These operators cannot be overloaded.
sizeof, typeof

The following example should make this clear:

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

namespace OverloadingOperatorsExample
{
class Year
{
int totalMon = 0;
int numYear = 0;
static int increment = 1;

public static Year operator+(Year oldYear, int numYears)


{
oldYear.totalMon += (numYears * 12);
oldYear.numYear += numYears;
return oldYear;
}

public static Year operator++ (Year oldYear)


{
oldYear.totalMon += 12;
oldYear.numYear += increment;
return oldYear;

Basic C# Programming | V1.0 August 2015 Page 122 of 276


}

public static int Increment


{
get
{
return increment;
}
set
{
increment = value;
}
}

static void Main(string[] args)


{
Console.WriteLine("Testing overloaded operators.");
Year y = new Year();
Console.WriteLine("Total number of months: {0}", y.totalMon);
Console.WriteLine("Adding 1 year (year += 1)");
y += 1;
Console.WriteLine("Total number of months now: {0}", y.totalMon);
Console.WriteLine("Setting increment as 2, and y++");
Year.increment = 2;
y++;
Console.WriteLine("Total number of months now: {0}", y.totalMon);
}
}
}

The result is:

Testing overloaded operators.


Total number of months: 0
Adding 1 year (year += 1)
Total number of months now: 12
Setting increment as 2, and y++
Total number of months now: 24

Compound operators (i.e. operators that are made up of two other operators,
such as +=, *=, etc.) cannot be explicitly overloaded. However, when a binary
operator is overloaded, its corresponding compound operator will assume the
same overloaded behaviour. So, for example, if the + operator for a specific
class is overloaded, the += operator will use the new + operator to calculate
the result.

Basic C# Programming | V1.0 August 2015 Page 123 of 276


2.3.4 Exercises
1. Briefly explain why you would overload a method.

2. Describe when a method should be overloaded.

3. What is known as the signature of a method?

2.3.5 Revision questions


1. True/False: Compound operators cannot be overloaded.

2. Which of the following operators are not overloadable?


i. &&
ii. !
iii. []
iv. false
v. ||

Please choose the most correct answer.


a. (iii) and (v)
b. (i), (iii) and (v)
c. (i) and (ii)
d. (i), (ii) and (iv)

3. True/False: When overloading indexers, several


declarations for this[] can be included, each with a similar
set of parameters.

Basic C# Programming | V1.0 August 2015 Page 124 of 276


2.4 Exceptions and exception handling

At the end of this section you will be able to:


 Use try … catch … finally blocks to handle exceptions.
 Use predefined exception classes.
 Design your own exceptions.

2.4.1 Try … catch blocks

A try … catch block consists of a try section followed by one or more catch
clauses, each of which handles specific exceptions that can occur.

The simplest form of a try … catch block has the following layout:

try
{
// Try executing some code.
}
catch (Exception e)
{
// Error occurred. Handle error.
}

The try block contains the code that may cause an exception. The block will
execute until an exception is thrown. If no exception is thrown, then the
program will continue executing code after the catch statement.

Exceptions are used by C# to indicate that an error of some description has


occurred. There are many types of exceptions, each of which indicates what
type of error occurred. For example, attempting to divide by zero in an
application (an impossible mathematical operation) throws a
DivideByZeroException exception. Note that all exceptions are actually classes,
derived from the Exception class itself. Any class that derives from the
Exception class (directly or indirectly) is also an exception.

The argument that is passed to the catch statement (in this case Exception e)
specifies exactly which type of exception to catch. The catch block will then
catch any exception of that type, as well as any exception that is derived from
that type. Because of this, the catch block in the example above will catch any
type of exception (as every exception is derived from the Exception class).

It should also be noted that a catch clause can be used without any
arguments; if this is done, any type of exception will be caught. Such a clause
is referred to as a general catch clause.

Basic C# Programming | V1.0 August 2015 Page 125 of 276


It is possible to use more than one specific catch clause in the same try …
catch statement. Specific exceptions (i.e. DivideByZeroException) should be
caught before the less specific (i.e. Exception) ones. To throw an exception of
choice, simply use a throw statement as follows:

throw new Exception;

A throw statement can also be used inside the catch block to rethrow the
exception that has been caught by the catch statement. While it is not
common practice, this can be used, for example, if some specific operation
must be performed when an error occurs, but must still allow the exception to
be caught by another try … catch statement. To rethrow the exception
currently handled by a catch clause without parameters, use the throw
statement without an argument.

Exceptions can be caught at any level. What this means is that an exception
does not necessarily have to be caught in the same place as it was thrown – so
long as the exception ultimately falls within a try … catch statement. For
example, if a method in a class has the potential to throw an uncaught
exception, that exception will still be caught if the method call is placed inside
a try … catch statement.

The following example demonstrates various ways in which exceptions can be


used.

1 // Namespaces automatically added when a new Console project is created.


2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace ClassProgram
9 {
10 // Ordering catch clauses.
11 class MyClass
12 {
13 // Entry point of the application.
14 public static void Main()
15 {
16 // Create a new MyClass object.
17 MyClass x = new MyClass();
18
19 try
20 {
21 string s = null;
22 x.MyFn(s);
23 }
24
25 // Most specific exception:
26 catch (ArgumentNullException e)
27 {
28 Console.WriteLine("{0} First exception caught.", e);
29 Console.ReadLine();
30 }
31
32 // Least specific exception:

Basic C# Programming | V1.0 August 2015 Page 126 of 276


33 catch (Exception e)
34 {
35 Console.WriteLine("{0} Second exception caught.", e);
36 Console.ReadLine();
37 }
38 }
39
40 public void MyFn(string s)
41 {
42 if (s == null)
43 {
44 throw new ArgumentNullException();
45 }
46 }
47 }
48 }

The result is:

System.ArgumentNullException: Value cannot be null.


at ClassProgram.MyClass.MyFn(String s) in C:\<Your Visual Studio 2013 Projects
Folder>\ClassProgram\Program.cs:line 46
at ClassProgram.MyClass.Main() in C:\<Your Visual Studio 2013 Projects
Folder>\ClassProgram\Program.cs:line 22 First exception caught.

On line 17, a new class MyClass is created. Lines 19 to 37 include the whole try
… catch block. On line 26, the catch clause is specific as to which exception
(ArgumentNullException) must be caught. When this exception is caught, a
specific message is displayed on line 28 with the error that occurred.

The catch statement on line 33 is more general. This means that any other
exception that might occur, apart from the ArgumentNullException, will be
caught here. This is useful when it is not known exactly which exception will
occur. Once again, a specific message is displayed on line 35 when Exception e
occurs.

Lastly, a method, MyFn(), is created on line 40. This method is called on line
22 and includes string s (which was declared as null on line 20) and then puts
that value in the place of s on line 21, x.MyFn(s). This null value is then sent to
the method on line 39. The if statement checks if s is null and then throws the
ArgumentNullException if it is indeed null.

Below is an example that deals with multiple exceptions.

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

namespace MultipleExceptionProgram
{
class Program
{
static void Main()
{
string one = "5";

Basic C# Programming | V1.0 August 2015 Page 127 of 276


// string two = "five";
string[] strArr = new string[2];

try
{
Console.WriteLine("Trying to convert two strings.");
Console.WriteLine("First string: {0}", Int32.Parse(one));
// If uncommented, the following line will cause a
// FormatException error.

// Console.WriteLine("Second string {0}", Int32.Parse(two));

// Index out of bounds.


Console.WriteLine(strArr[5]);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine(e.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
Console.WriteLine("This will print whatever happens.");
Console.ReadLine();
}
}
}
}

The result is:

Trying to convert two strings.


First string: 5
Index was outside the bounds of the array.
This will print whatever happens.

The example below demonstrates how to handle and pass exceptions.

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

namespace ThrowException
{
class Program
{
static void Main()
{
Program te = new Program();

try
{

Basic C# Programming | V1.0 August 2015 Page 128 of 276


te.GenerateException();
}
catch (Exception e)
{
Console.WriteLine("Back in the Main method again.");

while (e != null)
{
Console.WriteLine("Inner: {0}", e.Message);
// Set e to the InnerException. This will go on until the
// chain of exceptions is exhausted.
e = e.InnerException;
}
}
finally
{
Console.WriteLine("Finally clause in the Main method.");
Console.ReadLine();
}
}

void GenerateException()
{
try
{
string one = "Not a number.";
Console.WriteLine(Int32.Parse(one));
}
catch (FormatException e)
{
// Throw a new exception:
Console.WriteLine("Format exception from GenerateException.");

throw new Exception("Thrown from GenerateException", e);


}
finally
{
Console.WriteLine("Finally from GenerateException.");
}
}
}
}

The result is:

Format exception from GenerateException.


Finally from GenerateException.
Back in the Main method again.
Inner: Thrown from GenerateException.
Inner: Input string was not in a correct format.
Finally clause in the Main method.

2.4.2 Finally blocks

When an exception occurs, execution of the code inside the try block is
stopped. This often means that lines of code are not necessarily executed.
Some resource clean up, such as closing a file, might still need to be
performed even if an exception is thrown. This can be accomplished by using a
finally block. A finally block is always executed, regardless of whether an
exception occurs or not.

Basic C# Programming | V1.0 August 2015 Page 129 of 276


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

namespace FinallyBlockProgram
{
class Program
{
static public void Main()
{
int[] array1 = { 0, 0 };
int[] array2 = { 0, 0 };

try
{
// This statement will thrown an exception.
Array.Copy(array1, array2, -1);
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine("Error: {0}", e);
}
finally
{
Console.WriteLine("This statement is always executed.");
Console.ReadLine();
}
}
}
}

The result is:

Error: System.ArgumentOutOfRangeException: Non-negative number required.


Parameter name: length
at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinat
ionArray, Int32 destinationIndex, Int32 length, Boolean reliable)
at System.Array.Copy(Array sourceArray, Array destinationArray, Int32 length)
at ArgumentOutOfRange.Main() in C:\\Program.cs: line 11
This statement is always executed.

2.4.3 Designing your own exception

As previously mentioned, any class that is derived from the Exception class (or
any of its sub-classes) is automatically also an exception. The following
example shows how a custom exception can be created. Note that the
exception has to inherit from the Exception class and call the constructor
method of the base Exception class.

Basic C# Programming | V1.0 August 2015 Page 130 of 276


1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace DesigningExceptionProgram
8 {
9 class Program
10 {
11 public class SillyException : Exception
12 {
13 public SillyException() : base("Silly exception.") { }
14 }
15
16 public class CreateSillyException
17 {
18 // Entry point of the application.
19 static void Main()
20 {
21 try
22 {
23 throw new SillyException();
24 }
25 catch (SillyException se)
26 {
27 Console.WriteLine("Threw a silly exception.");
28 Console.WriteLine(se.Message);
29 Console.ReadLine();
30 }
31 }
32 }
33 }
34 }

The result is:

Threw a silly exception.


Silly exception.

On lines 11 to 14, a new Exception called SillyException is created. Note that


the SillyException extends the Exception class. The base constructor is called
with a string error message as an argument. The SillyException is thrown on
line 23.

Basic C# Programming | V1.0 August 2015 Page 131 of 276


2.4.4 Exercises
1. Why would an exception be re-thrown?

2. What code block would be used in conjunction with try …


catch blocks that will run regardless of the outcome?

3. Briefly explain how DivideByZeroException exception occurs.

4. Write a program that prompts the user to enter two


numbers. The program should divide one number by
another. Use a try … catch block to prevent the user from
dividing by zero.

2.4.5 Revision questions


1. True/False: There can be many catch clauses per try … catch
statement.

2. True/False: The finally block only executes after an error has


occurred within a try … catch block.

3. True/False: An Exception is a specific exception.

4. When a custom exception is created, from which class must


the exception inherit in order for it to compile?
a. Any class.
b. Any class which is derived from the Exception class.
c. Only the Exception class itself, no other class is
acceptable.
d. Standard exceptions may be used.

Basic C# Programming | V1.0 August 2015 Page 132 of 276


2.5 Organising code with namespaces

At the end of this section you will be able to:


 Understand what namespaces are.
 Use namespace directives.
 Create namespaces.
 Understand what scope and visibility mean.

2.5.1 Why namespaces?

Consider the case of a group of children in a class. It is not unusual that two
children have the same first name, for example, John. If their surnames differ,
these two may be differentiated on this basis. But what if their surnames are
also the same?

One could be called ‘blonde John Smith’, and the other one ‘brunette John
Smith’. Or, age could be used as a criterion. If there is one John in the classA
and another John in the classB, the first John may be addressed as follows:

// Note: The names found here are the classmates in the class A.
// This John is the John in class A.
John went to play soccer.

Declaring a namespace makes it easier to distinguish different names. Not only


does it distinguish to which class name is being referred, it also allows the use
of shorthand. Instead of using:

ClassA.John

Use the following:

using ClassA;
John j = new John();

2.5.2 Namespace directives

Namespaces are used in two ways.

Declaring a namespace can help control the scope of the class and method
names in larger programming projects. The namespace keyword is used to
declare a scope. The ability to create scopes within the project helps organise
code. Syntax similar to the code snippet below could be used to name each
child without confusion.

Johannesburg.SunflowerSchool.ThirdGrade.SecondClass.John;

Basic C# Programming | V1.0 August 2015 Page 133 of 276


In a report referencing the Sunflower School, the following syntax may be
used:

using Johannesburg.SunflowerSchool;
/* Because of the namespace declaration, we know that ThirdGrade refers to the
ThirdGrade of the SunflowerSchool in Johannesburg. */
ThirdGrade.FourthClass.Sarah;

The name of a class being referenced may be abbreviated by creating an alias.


The name classInJoburg may be used instead of the name
Johannesburg.SunflowerSchool.ThirdGrade.FourthClass:

using classInJoburg = Johannesburg.SunflowerSchool.ThirdGrade.FourthClass;

This could prove to be helpful to distinguish it from another class in another


school:

using classInPretoria = Pretoria.SunflowerSchool.ThirdGrade.FourthClass;

Secondly, the .NET Framework classes use namespaces to organise the many
classes found in the class library. For example, declaring using System at the
top of the program allows for:

Console.WriteLine();

Instead of:

System.Console.WriteLine();

Basic C# Programming | V1.0 August 2015 Page 134 of 276


2.5.3 Exercises
1. What is the primary purpose of namespaces?

2. Why else are namespaces useful?

2.5.4 Revision questions


1. True/False: The following piece of code will compile.

using classInPretoria = Pretoria.SunflowerSchool.


ThirdGrade.FourthClass;

2. True/False: Console.WriteLine() has to be used with using


System;

Basic C# Programming | V1.0 August 2015 Page 135 of 276


2.6 Structs and conversions

At the end of this section you will be able to:


 Understand what classes and structs are used for.
 Understand what type system unification means.
 Design new value types.
 Understand what implicit and explicit conversions are.
 Use value type and reference type conversions.

2.6.1 Identifying the class/struct relationship

The main difference between a class and a struct lies in the way in which they
are stored in memory. Look at the following example of a struct declaration:

public struct Person


{
string name;
int height;
int weight;

public bool OverWeight()


{
// Some theoretical calculation.
return false;
}
}

It is evident from the above example that the way in which a struct and a class
are declared is very similar, the only noticeable difference being the use of the
struct keyword instead of the class keyword. There are, however, significant
differences between the two. As with classes, structs define new data types
which can then be used and reused in many applications. However, while
classes define a reference type, structs define a value type.

A reference type stores a reference to an object. The variable itself does not
actually contain the object, but it stores the memory address where that object
is stored. All reference types are stored on the heap. A value type, however,
actually contains its data within itself. All value types are stored on the stack.

The heap and the stack are two sections of memory. Memory on the heap is
allocated in chunks as necessary, and then released and reallocated over time.
This can cause fragmentation (where data becomes fragmented, i.e. it is
stored in several segments, each in a different memory location) which leads
to the need for additional memory management. Memory on the stack is
stored in a Last In-First Out (LIFO) manner whereby the data that was last
stored (last in) is the first that can be removed (first out). This is more efficient
than heap allocation, as it avoids the issue of fragmentation.

Basic C# Programming | V1.0 August 2015 Page 136 of 276


A hardware stack pointer (SP) normally controls the location of the next place
to allocate memory. Each time a new value is added on the stack, it is pushed
and SP is moved up by the size the value type requires. When a value is
removed from the stack, it is popped and SP moves back (by the size the value
was using). Refer to Figure 24.

Push
STACK HEAP
Pop

SP

Figure 24 – A simplified memory layout, showing the heap and the


stack

Objects on the stack are faster to allocate and de-allocate. However, the
amount of memory available on the stack is more limited than memory on the
heap. If the stack memory is exhausted, a StackOverflowException is thrown.
It is therefore generally better to use classes for larger, more complicated
objects. Because structs are stored on the stack, they are more efficient than
classes, but due to the limited availability of stack memory, structs are better
suited to smaller, less complicated objects.

Encapsulation also plays a large role in deciding whether to use classes or


structs,. Although structs encapsulate data and functionality, including large
amounts of encapsulation (which can increase the amount of stack memory
used) may make them impractical to use.

In C#, another difference between classes and structs is that structs do not
allow for inheritance. Because of this, a struct cannot be sealed or abstract,
nor can the protected modifier be used for any of the fields.

2.6.2 Type system unification

Many programming languages (C# included) have primitive types (such as


bool, int, char, etc.). In C#, however, primitive types are actually structs. This
is different from most other programming languages. In C#, both classes and
structs inherit from the Object class. Therefore, in C# everything is an object,
up to and including the primitive types, so everything in C# is ultimately
passed by reference. Refer to Figure 25:

Basic C# Programming | V1.0 August 2015 Page 137 of 276


Object

Class Struct
 System.Boolean (bool)
 System.Byte (byte)
Both class and struct  System.Char(char)
inherit from object  System.Double(double)
implicitly.  System.Int32 (int)
 System.String (string)

Figure 25 – Objects: classes and structs

In C#, this unified type system is referred to as the Common Type System
(CTS).

2.6.3 Boxing and unboxing

Sometimes it is required to use a primitive value as a reference, or an object


as a value. To this end, C# provides the concepts of boxing and unboxing.
When a value is boxed, it is stored as an object which can then be used as a
reference. Similarly, when an object is unboxed, it is converted from an object
back into a value type. This is made possible by the common type system of
C# – because everything is actually an object, it can be treated as such in an
application.

The following example shows how a value can be boxed and then unboxed
again:

class BoxingAndUnboxing
{
// Entry point of the application.
static void Main()
{
int value = 999;
// Boxing.
object boxedValue = value;
// Unboxing.
int unboxedValue = (int) boxedValue;
}
}

2.6.4 Designing a new value type

Because all value types in C# are actually structs, it follows that customised
value types can be created by using structs. This is very similar to creating a
new class.

Basic C# Programming | V1.0 August 2015 Page 138 of 276


Also note that structs cannot have default constructors or destructors; they
can only use those generated automatically by the compiler. The following
example shows how to design a new value type which can be used to store a
money value:

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

namespace StructExample
{
public struct Currency
{
private double amount;

public Currency(double amount)


{
this.amount = amount;
}

// Overriding the ToString method.


public override string ToString()
{
return String.Format("{0:C}", amount);
}

public static Currency operator +(Currency c1, Currency c2)


{
Currency cur = new Currency();
cur.Amount = c1.Amount + c2.Amount;
return cur;
}

public double Amount


{
get
{
return amount;
}
set
{
amount = value;
}
}
}

public class StructEx


{
public static int Main(string[] args)
{
Currency myCurrency1 = new Currency(2.0);
Currency myCurrency2 = new Currency(3.62);
Currency myCurrency3 = myCurrency1 + myCurrency2;

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


return 0;
}
}
}

Basic C# Programming | V1.0 August 2015 Page 139 of 276


The result is:

Amount = R 5.62

2.6.5 Implicit versus explicit conversions

Sometimes it will be necessary to convert between two numeric data types.


This is done through casting. There are two types of casting: implicit and
explicit.

Implicit casting happens automatically when data will not be lost when the
type is converted. For example, implicit conversion will not happen in
converting a double type to an integer, because the values following the
decimal point would be lost. However, an integer can be converted into a
double, because the double data type can store all that an integer can, and
more.

int radius = 5;
double c = 3.14 * 2 * radius

In the above example, the two integer values (2 and radius) are first implicitly
converted to the double data type before the calculation is performed. Implicit
conversion can also take place anywhere a mathematical operation is
performed, such as inside a condition. Implicit conversion will only take place if
it is necessary for the calculation being performed.

Explicit casting only happens if it is specified. Explicit casting may be specified


between any numerical data type. It can, however, lead to data loss in
situations such as a conversion between a double and an integer.

double d = 3.14;
int i = (int)d * 2;

In the above example, the double value ‘d’ is converted to an integer before
multiplying it by 2. The end result would be 6, as converting a double to an
integer removes all decimal information. Pay careful attention when using
explicit casting, and only use it only when necessary.

Figure 26 illustrates that implicit conversion is safe.

Basic C# Programming | V1.0 August 2015 Page 140 of 276


Long data type can store bigger numbers.

int long

Therefore the following is the problem:

looongNum int num


long

Integer num fits in


without any problems.
=> implicit conversion
num

Figure 26 – Demonstration of implicit conversion

Problems may arise when the data type is assigned to a type that is smaller
than itself, as shown in Figure 27.

Figure 27 – Demonstration of explicit conversion that causes problems

Basic C# Programming | V1.0 August 2015 Page 141 of 276


2.6.6 Exercises
1. Explain what a reference type is and where it is stored.

2. What happens when stack memory is exhausted?

3. What happens when converting a double type to an


integer?

4. Write a program that performs one implicit and one


explicit conversion using short and int types.

2.6.7 Revision questions


1. True/False: Classes and structs inherit from the Math
class.

2. True/False: Everything in C# is an object.

3. Which one of the following would not represent a valid


implicit conversion?
a. short to int
b. sbyte to int
c. int to ushort
d. float to double

4. Which of the following modifiers are not allowed to be


used in a struct?
i. public
ii. protected
iii. private
iv. sealed
v. abstract

Choose the most correct answer


a. (ii), (iv) and (v)
b. None of the given options.
c. (iii), (iv) and (v)
d. (i), (ii), (iii) and (iv)

5. True/False: Structs cannot inherit from another class or


struct but they cannot implement interfaces.

Basic C# Programming | V1.0 August 2015 Page 142 of 276


2.7 Using and implementing interfaces

At the end of this section you will be able to:


 Implement interfaces.
 Understand the difference between abstract classes and
interfaces.
 Understand and use implicit and explicit implementation.
 Understand and use inheritance with interfaces.

2.7.1 What is an interface?

Interfaces are used to define a set of related behaviours shared by several


classes which may not necessarily inherit from the same base class. However,
interfaces cannot define functionality, nor may they contain any variable
declarations.

When an interface is implemented in a class, then that class inherits all the
methods, properties and indexers of the interface declaration. However, that
class must implement all of those members or it will not compile. What then is
the point of using the interface if all the methods must be implemented
anyway?

Recollect in the earlier section on polymorphism that the different classes can
all be treated in the same way, so long as they are all derived from the same
base class. Interfaces function in much the same way. If two classes both
implement the same interface, then they can both, for example, have
instances of them stored in an array which is declared as storing the type of
that interface. It follows from this that those methods, properties and indexers
which were defined in the interface on these objects may be called, even if
their exact type is not known.

Interfaces can also inherit from other interfaces, so it is possible to have a


hierarchy of interfaces, much as with classes. This is generally used to
specialise the interface for a more specific purpose.

2.7.2 Interfaces versus abstract classes

Interfaces share many similarities with abstract classes, but they are not the
same thing. Abstract classes are used for abstraction, whereas interfaces
define specification. Members of an abstract class may only contain
implementations if they are not defined as abstract themselves. Derived
classes must implement abstract class members, but they do not have to
implement any other members that are declared as virtual. When
implementing an interface, however, all methods, properties and indexers
need to be overridden.

Basic C# Programming | V1.0 August 2015 Page 143 of 276


Unlike an abstract class, interfaces cannot define any functionality. They
merely declare the presence of certain class members that any implementing
classes must have. An interface cannot contain any fields, and all interface
members are public by default.

Classes and structs can implement interfaces in a manner that is similar to the
way in which classes inherit from base classes. A class or struct can implement
more than one interface. When a class or struct implements an interface, it
only inherits the method/property/indexer names and signatures.

In summary, an interface has the following properties:

 An interface is similar to an abstract base class. Any non-abstract class


implementing the interface must implement all its members.
 An interface cannot be instantiated directly.
 Interfaces can contain indexers, methods and properties.
 Interfaces contain no implementation of methods.
 Classes and structs can implement from more than one interface.
 An interface can inherit from one or more other interfaces.

2.7.3 Implicit and explicit implementation

2.7.3.1 Implicit implementation (one class implementing one


interface)
Additional comments have been placed in the programs as explanation. To
understand the examples fully, create and run the application.

// Comparable Interface. This interface will be implemented by one class.


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

namespace InterfaceExample
{
// Creating an interface.
interface Comparable
{
// Declaring three Boolean variables which will receive values from
// the MyInteger class.
bool IsEqualTo(Object o);
bool IsGreaterThan(Object o);
bool IsLessThan(Object o);
}
}

Basic C# Programming | V1.0 August 2015 Page 144 of 276


// MyInteger class. This class implements the interface created above.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InterfaceExample
{
class MyInteger : Comparable
{
// The value of this object.
int storedValue;
// Property used to retrieve the storedValue. It will be clear in the
// Main class that the storedValue will be either one or 15.
public int Value
{
get
{
return storedValue;
}
set
{
storedValue = value;
}
}

// Constructor.
public MyInteger(int newValue)
{
Value = newValue;
}

// Implement the interface methods. Methods will return true or false


// depending on the outcome of the calculation.
public bool IsEqualTo(Object other)
{
return Value == ((MyInteger)other).Value;
}

public bool IsGreaterThan(Object other)


{
return Value > ((MyInteger)other).Value;
}

// The IsLessThan method uses the IsGreaterThan method to test


// whether one value is less than the other.
public bool IsLessThan(Object other)
{
return !IsGreaterThan(other);
}
}
}

Basic C# Programming | V1.0 August 2015 Page 145 of 276


// Program Class. The class where the application will start.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InterfaceExample
{
class Program
{
// The Main() method of the application.
static void Main(string[] args)
{
// Creates an instance of the MyInteger class with two different
// values.
MyInteger one = new MyInteger(1);
MyInteger fifteen = new MyInteger(15);

// Calls the IsGreaterThan method.


Console.WriteLine("15 > 1 == " + fifteen.IsGreaterThan(one));
// Calls the IsLessThan method.
Console.WriteLine("1 < 15 == " + one.IsLessThan(fifteen));
// Calls the IsEqualTo method.
Console.WriteLine("1 = 15 == " + one.IsEqualTo(fifteen));
// Calls the IsEqualTo method.
Console.WriteLine("1 = 1 == " + one.IsEqualTo(one));

// Pause.
Console.ReadLine();
}
}
}

The result is

15 > 1 == True
1 < 15 == True
1 = 15 == False
1 = 1 == True

2.7.3.2 Polymorphism (two classes implementing one interface)

// Drivable interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Polymorphism
{
// Creating an interface.
interface Driveable
{
// Declaring variables which will receive values from the Vehicle class
void Drive();
void Steer(bool steerRight);
void Accelerate(double accelerationAmount);
void Break(double breakingStrength);
}
}

Basic C# Programming | V1.0 August 2015 Page 146 of 276


// Vehicle abstract class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Polymorphism
{
// Creating an abstract Vehicle class.
abstract class Vehicle
{
// Instance variables.
public string name;
public double maxSpeed;
public double currentSpeed;

// Constructor.
public Vehicle()
{
}

// Overloading the Vehicle() method with three parameters)


public Vehicle(string name, double maxSpeed, double currentSpeed)
{
this.name = name;
this.maxSpeed = maxSpeed;
this.currentSpeed = currentSpeed;
}

// Method to be defined by sub-classes, i.e. Car class and Truck


// class.
public abstract void Drive();
}
}

// Car Class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Polymorphism
{
// Inherit from Vehicle, implement Driveable.
class Car : Vehicle, Driveable
{
// Call the base class constructor.
public Car(string name, double maxSpeed, double currentSpeed)
: base(name, maxSpeed, currentSpeed)
{
}

// Take this car for a test drive.


public override void Drive()
{
Accelerate(20);
Steer(true);
Accelerate(40);
Break(40);
Steer(false);

Basic C# Programming | V1.0 August 2015 Page 147 of 276


Accelerate(120);
Break(40);
Steer(false);
Break(120);
}

// Turn the car.


public void Steer(bool steerRight)
{
if (steerRight)
{
Console.WriteLine("Car: Turning right...");
}
else
{
Console.WriteLine("Car: Turning left...");
}
}

// Go faster.
public void Accelerate(double accelerationAmount)
{
if (accelerationAmount > 0 & currentSpeed < maxSpeed)
{
// Change in velocity = acceleration * time;
// for this example, assume time = 1 second.
if (currentSpeed + accelerationAmount > maxSpeed)
{
currentSpeed = maxSpeed;
Console.WriteLine("Car: Maximum speed of " + maxSpeed +
"km/hr reached!");
}
else
{
currentSpeed += accelerationAmount;
Console.WriteLine("Car: Accelerated to " + currentSpeed +
"km/hr.");
}
}
else if (currentSpeed == maxSpeed)
{
Console.WriteLine("Car: Cannot accelerate, maximum speed " +
"reached!");
}
}

// Slow down.
public void Break(double breakingStrength)
{
if (breakingStrength > 0 & currentSpeed > 0)
{
if (currentSpeed – breakingStrength < 0)
{
currentSpeed = 0;
Console.WriteLine("Car: Breaked to a standstill.");
}
else
{
currentSpeed -= breakingStrength;
Console.WriteLine("Car: Decelerated to " + currentSpeed +
"km/hr.");
}
}
}

Basic C# Programming | V1.0 August 2015 Page 148 of 276


}
}

// Truck Class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Polymorphism
{
class Truck : Vehicle, Driveable
{
// Call the base class constructor.
public Truck(string name, double maxSpeed, double currentSpeed)
: base(name, maxSpeed, currentSpeed)
{
}

// Take this truck for a test drive.


public override void Drive()
{
Accelerate(10);
Steer(false);
Accelerate(80);
Break(60);
Steer(false);
Accelerate(90);
Break(40);
Steer(true);
Break(120);
}

// Turn the truck.


public void Steer(bool steerRight)
{
if (steerRight)
{
Console.WriteLine("Truck: Turning right...");
}
else
{
Console.WriteLine("Truck: Turning left...");
}
}

// Go faster.
public void Accelerate(double accelerationAmount)
{
if (accelerationAmount > 0 & currentSpeed < maxSpeed)
{
// Change in velocity = acceleration * time;
// for this example, assume time = 1 second.
if (currentSpeed + accelerationAmount > maxSpeed)
{
currentSpeed = maxSpeed;
Console.WriteLine("Truck: Maximum speed of " + maxSpeed +
"km/hr reached!");
}
else
{
currentSpeed += accelerationAmount;

Basic C# Programming | V1.0 August 2015 Page 149 of 276


Console.WriteLine("Truck: Accelerated to " + currentSpeed +
"km/hr.");
}
}
else if (currentSpeed == maxSpeed)
{

Console.WriteLine("Truck: Cannot accelerate, maximum speed "


+ "reached!");
}
}
// Slow down.
public void Break(double breakingStrength)
{
if (breakingStrength > 0 & currentSpeed > 0)
{
if (currentSpeed – breakingStrength < 0)
{
currentSpeed = 0;
Console.WriteLine("Truck: Breaked to a standstill.");
}
else
{
currentSpeed -= breakingStrength;
Console.WriteLine("Truck: Decelerated to " + currentSpeed
+ "km/hr.");
}
}
}
}
}

// Program class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Polymorphism
{
class Program
{
static void Main(string[] args)
{
Driveable[] vehicles = new Driveable[2];

// Create a new car.


vehicles[0] = new Car("Kit", 120, 0);

// Create a new truck.


vehicles[1] = new Truck("18 Wheels of justice", 100, 0);

// Take them for a test drive!


foreach (Driveable d in vehicles)
{
d.Drive();
}

// Pause.
Console.ReadLine();
}
}

Basic C# Programming | V1.0 August 2015 Page 150 of 276


}

The result is:

Car: Accelerated to 20km/hr.


Car: Turning right...
Car: Accelerated to 60km/hr.
Car: Decelerated to 20km/hr.
Car: Turning left...
Car: Maximum speed of 120km/hr reached!
Car: Decelerated to 80km/hr.
Car: Turning left...
Car: Breaked to a standstill.
Truck: Accelerated to 10km/hr.
Truck: Turning left...
Truck: Accelerated to 90km/hr.
Truck: Decelerated to 30km/hr.
Truck: Turning left...
Truck: Maximum speed of 100km/hr reached!
Truck: Decelerated to 60km/hr.
Truck: Turning right...
Truck: Breaked to a standstill.

2.7.3.3 Explicit implementation (one class implementing two


interfaces)

The following example creates a Rectangle class which can draw a rectangle on
the screen. This rectangle can be scaled up or down, as well as compared with
other rectangles:

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

namespace MutlipleInterfaceExample
{
// Creates new Comparable interface.
interface Comparable
{
bool IsEqualTo(Object o);
bool IsGreaterThan(Object o);
bool IsLessThan(Object o);
}
}

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

namespace MutlipleInterfaceExample
{
// Creates new Scaleable interface.
interface Scaleable
{
double Scale
{
get;
set;

Basic C# Programming | V1.0 August 2015 Page 151 of 276


}
}
}

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

namespace MutlipleInterfaceExample
{
// Creates the Rectangle class which implements the Scaleable and Comparable
// intefaces.
class Rectangle : Scaleable, Comparable
{
double width;
double height;

double scale = 1.0;

public double Scale


{
get
{
return scale;
}
set
{
if (value > 0)
{
scale = value;
}
}
}

// The Width property which would be used to draw the rectangle.


public double Width
{
get
{
return width * scale;
}
set
{
width = value;
}
}

// The Height property which would be used to draw the rectangle.


public double Height
{
get
{
return height * scale;
}
set
{
width = value;
}
}

// Property which calculates the area.


public double Area

Basic C# Programming | V1.0 August 2015 Page 152 of 276


{
get
{
return Width * Height;
}
}

// Constructor.
public Rectangle()
{
width = 0;
height = 0;
}

// Constructor.
public Rectangle(double width, double height)
{
this.width = width;
this.height = height;
}

// Compare two rectangles, are they equal.


public bool IsEqualTo(Object o)
{
if (o is Rectangle)
{
if (((Rectangle)o).Area == this.Area)
{
return true;
}
}

return false;
}

// Compare this rectangle to another, is its area bigger.


public bool IsGreaterThan(Object o)
{
if (o is Rectangle)
{
if (((Rectangle)o).Area < this.Area)
{
return true;
}
}

return false;
}

// Compare this rectangle to another, is its area smaller.


public bool IsLessThan(Object o)
{
if (o is Rectangle)
{
if (((Rectangle)o).Area > this.Area)
{
return true;
}
}

return false;
}

// Draw the rectangle.

Basic C# Programming | V1.0 August 2015 Page 153 of 276


public override string ToString()
{
string returnString = "";

// Math.Ceiling == round up.


for (int y = 0; y < Math.Ceiling(this.Height); y++)
{
for (int x = 0; x < Math.Ceiling(this.Width); x++)
{
// "\\" == "\"
Console.Write("/\\");
}

Console.WriteLine();
}

return returnString;
}
}
}

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

namespace MutlipleInterfaceExample
{
class Program
{
static void Main(string[] args)
{
// Create two rectangles, x and y.
Rectangle x = new Rectangle(5, 5);
Rectangle y = new Rectangle(5, 5);

// Display rectangle x.
Console.WriteLine(x);

// Increase the scale of rectangle x.


x.Scale = 2;

// Display rectangle x.
Console.WriteLine(x);

// See if rectangle x is bigger than rectangle y.


if (x.IsGreaterThan(y))
{
Console.WriteLine("Rectangle X is greater in area than " +
"Rectangle Y");
}
else
{
Console.WriteLine("Rectangle Y is greater in area than " +
"Rectangle X");
}

// Pause.
Console.ReadLine();
}
}
}

Basic C# Programming | V1.0 August 2015 Page 154 of 276


The result is:

/\/\/\/\/\
/\/\/\/\/\
/\/\/\/\/\
/\/\/\/\/\
/\/\/\/\/\

/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\

Rectangle X is greater in area than Rectangle Y

Basic C# Programming | V1.0 August 2015 Page 155 of 276


2.7.4 Exercises
1. What happens when an interface is implemented in a
class?

2. In which class will the new keyword will cause a compile


error?

3. What are the three things that an interface may contain?

2.7.5 Revision questions


1. True/False: An interface cannot inherit from another
interface.

2. True/False: Any non-abstract class implementing an


interface must implement all its members.

3. True/False: An interface cannot contain fields.

Basic C# Programming | V1.0 August 2015 Page 156 of 276


2.8 Test Your Knowledge (Unit 2 – Self-Test)

The questions in this section are similar to those asked in the


examination. Try answering these questions and then check the
answers with the lecturer. The questions are taken from the
study guide and textbook. The questions comprise theory and
application questions which will be in multiple choice, multiple
response, true/false and selection formats. Allow about 20
minutes for all the questions.

True/False

1. True/False: A sealed class cannot be sealed and abstract at the same


time.

Multiple choice

1. Which one of the following is the correct way to prompt garbage


collection?
a. GC.Collect();
b. Collect.Garbage();
c. System.Collect();
d. System.GC.Collect();

2. What is the concept called that uses a method in more than one way?
a. Operator overriding
b. Method overriding
c. Method overloading
d. Exception handling

3. What is the output of the following piece of code?

using System;

public class Example


{
string name = "Chalk";
string description = "Blue";
decimal price = Decimal.Parse("10.00");
Example ex;

public Example()
{
ex = new Example("Stamp", "Green", 10);
}

public Example(string name, string description, decimal price)


{
this.name = name;

Basic C# Programming | V1.0 August 2015 Page 157 of 276


this.description = "Colour: " + description;
price = this.price;
Print(this.name, this.description, this.price);
}

public static void Print(string name, string description, decimal


price)
{
Console.WriteLine(name + "" + description + "" + price);
}

public static void Main()


{
Example eg = new Example();
}
}

a. Chalk Colour: Blue


10.0
b. Stamp Colour: Green
10.00
c. Compilation Error
d. Chalk Colour: Green
5.00

4. What is wrong with the following piece of code?

using System;

public abstract class Car


{
}

public class Honda : Car


{
public static void Main()
{
Car c = new Car();
}
}

a. The Main method should have been in the Car class.


b. The Car class is incorrectly inherited.
c. The Car class cannot be declared as abstract.
d. One cannot make an instance of an abstract class.

5. How many errors are there in the following piece of code?

using dbz = System.Console;


namespace Stuff
{
class Test
{
static void Main(string[] args)
{
dbz.WriteLine(args[0] + ", Hello!");
}
}

Basic C# Programming | V1.0 August 2015 Page 158 of 276


}

a. 2
b. 0
c. 1
d. 3

Multiple response

1. Which three of the following parts of a method make up a method


signature?
a. Number of parameters
b. Brackets
c. Parameters
d. Return type
e. Method type
f. Name

2. Which three of the following are overloadable?


a. true
b. typeof
c. %
d. []
e. ==
f. ||

3. Which three of the following are incorrect when creating an interface?


a. string Sport (string rugby, string soccer, string cricket);
b. decimal Remainder (decimal income, decimal expenses)
{
return income – expenses;
}
c. public bool Attending
{
get { }
set { }
}
d. public interface ISport;
e. string sportLocation
{
get;
set;
}
f. public interface IRugby : ISport {}

Basic C# Programming | V1.0 August 2015 Page 159 of 276


Unit 3 – Graphical User Interfaces

This unit introduces you to object and component programming with C#.

This unit counts 80% towards part A of the C# mark, and 13 days have been
allocated to complete it. The time and marks are scheduled as follows:

Reading and project 10 days 5%


Exam preparation and exam 2 days 45%
Practical exam 1 day 30%

Basic C# Programming | V1.0 August 2015 Page 160 of 276


3.1 Delegates and events

At the end of this section, you will be able to:


 Understand what a delegate is.
 Use delegates to enable late-bound operations.

3.1.1 Delegates

Delegates allow programmers to call methods dynamically without having to


know at compile-time exactly which method will be invoked. Most of the time a
function is called directly. This works well in most cases, but at times the
function cannot be called directly; it is sent as an argument through another
method. This is very useful in the GUI (Graphical User Interface).

Delegates are used to enable late-bound operations. What this means is that a
delegate may be used to call a method, even if the exact method to call is only
decided at runtime.

When defining a delegate, the argument types and the return values need to
match those of the method. The signature of a single-cast delegate is shown
below.

delegate result-type identifier([parameters]);

 result-type: the result type, which matches the return type of the function.
 identifier: the delegate name.
 parameters: parameters that the function takes.

Examples:

public delegate void SimpleDelegate()

The declaration above defines a delegate named SimpleDelegate. It


encapsulates any method that takes no parameters and returns no value.

public delegate int buttonClickHandler (object obj1, object obj2)

This declaration above defines a delegate named buttonClickHandler. It will


encapsulate any method that takes two objects as parameters and returns an
integer value.

A delegate allows a definition of what a function looks like, without specifying


exactly which function needs to be called.
There are three steps in defining and using delegates:

Basic C# Programming | V1.0 August 2015 Page 161 of 276


 Declaration
 Instantiation
 Invocation

The example below is a very basic one, demonstrating how delegates work:

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

namespace DelegateExample
{
// Delegate declaration:
public delegate void myDelegate();

class DelegateEx
{
public static void function()
{
Console.WriteLine("The delegate called the function...");
Console.ReadLine();
}

static void Main(string[] args)


{
// Instantiation:
myDelegate myDelegate = new myDelegate(function);

// Invocation:
myDelegate();
}
}
}

The result is:

The delegate called the function...

The following example declares a delegate that takes a single string parameter
and has no return type:

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

namespace DelegateExample
{
class Program
{
// Define the CalculateFuelUsage delegate.
public delegate double CalculateFuelUsage(int seconds, double
vehicleWeight, int engineCC);

static void Main(string[] args)


{
new Program();
}

Basic C# Programming | V1.0 August 2015 Page 162 of 276


public Program()
{
// Test variables and values.
int seconds = 300; // 5 minutes
double vehicleWeight = 1.6; // tons
int engineCC = 1800; // 1800cc

// Declare an instance of the CalculateFuelUsage type.


CalculateFuelUsage calc;

// Make the delegate point to the CalculatePetrolUsage method.


calc = CalculatePetrolUsage;
// Call the method.
Console.WriteLine("Petrol Usage : " + calc(seconds, vehicleWeight,
engineCC) + " litres over " + seconds +
" seconds.");

// Make the delegate point to the CalculateDieselUsage method.


calc = CalculateDieselUsage;
// Call the method.
Console.WriteLine("Diesol Usage : " + calc(seconds, vehicleWeight,
engineCC) + " litres over " + seconds +
" seconds.");

// Pause.
Console.ReadLine();
}

public double CalculatePetrolUsage(int seconds, double vehicleWeight,


int engineCC)
{
// Fictional calculation.
return Math.Round((vehicleWeight * 2 / engineCC) * seconds, 2);
}

public double CalculateDieselUsage(int seconds, double VehicleWeight,


int engineCC)
{
// Fictional calculation.
return Math.Round((VehicleWeight / engineCC) * seconds, 2);
}
}
}

The result is:

PETROL USAGE : 0.53 LITRES OVER 300 SECONDS.


DIESOL USAGE : 0.27 LITRES OVER 300 SECONDS.

Delegates are multicast. In other words, they can point to more than one
method at a time. The implication of this is that when the delegate is called,
each of the methods to which it points will also be called.

Basic C# Programming | V1.0 August 2015 Page 163 of 276


The following is an example of a multicast delegate:

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

namespace DelegateExample2
{
class Program
{
// Define the functionDelegate delegate.
public delegate void functionDelegate();

static void Main(string[] args)


{
new Program();
}

public Program()
{
// Declare the delegate.
functionDelegate function;

// Add each of the functions.


function = Function1;
// += is equivalent to function = function + Function2
function += Function2;
function += Function3;

// Call the delegate.


function();

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

// Now remove a function from the delegate.


function -= Function1;

// Call the delegate.


function();

// Pause.
Console.ReadLine();
}

public void Function1()


{
Console.WriteLine("Function1 called...");
}

public void Function2()


{
Console.WriteLine("Function2 called...");
}

public void Function3()


{
Console.WriteLine("Function3 called...");
}
}
}

Basic C# Programming | V1.0 August 2015 Page 164 of 276


The result is:

FUNCTION1 CALLED...
FUNCTION2 CALLED...
FUNCTION3 CALLED...
======================
FUNCTION2 CALLED...
FUNCTION3 CALLED...

3.1.2 Events and delegates

When an event occurs (e.g. a button is clicked, or the user closes a window),
that event can trigger an event-handler which will execute code as necessary.
All Windows forms controls have several events, and many of them are
common to the different control types. These events are in fact delegates.
When the event occurs, the application will call the delegate, which will in turn
call any methods (the event-handlers) to which it may have been pointing.

The process of specifying which event-handler should be triggered and by


which event, is generally handled by the Visual Studio (the process will be
explained later in this unit).

Basic C# Programming | V1.0 August 2015 Page 165 of 276


3.1.3 Exercises
1. What is the main function of a delegate?

2. How is the correct delegate chosen?

3. Write a program to output a sequence of 10 numbers to


the console. The user must provide the starting number
and indicate whether the sequence should be ascending or
descending. Include a class in the program that writes the
sequence to the screen. Use a delegate to point to the
relevant method that either adds or subtracts from the
starting number to obtain the next number in the
sequence.

4. Write a program that uses a multicast delegate. This


delegate must perform two operations by invoking other
delegates, first a multiplication, then a division. The
output of each operation must be written to the console.

3.1.4 Revision questions


1. True/False: A delegate declaration looks as follows:
delegate parameter identifier([result-type]);

2. True/False: Multicast delegates can only point to one


method at the time.

3. Which one of the following declarations is correct?


a. delegate Calc(decimal d1, decimal d2) as decimal;
b. delegate decimal Calc(decimal d1);
c. delegate decimal Calc(decimal d1, decimal d2);
d. delegate private decimal Calc(decimal d1, decimal d2);

4. Which one of the following is not true about a multicast


delegate?
a. It must have a return type of void.
b. Delegates assigned to a multicast delegate cannot
have other return types.
c. It cannot have any out parameters.
d. (a) and (b).

Basic C# Programming | V1.0 August 2015 Page 166 of 276


3.2 Introduction to Windows forms

At the end of this section, you will be able to:


 Use various controls to create a GUI screen.
 Understand how events work.
 Understand the basic controls and their functions.
 Specify event-handlers to create interactive GUI
programs.

3.2.1 Windows forms

The Windows form is the base of all GUI programming and contains
functionality to create an application. A form contains all the components
needed to create these applications. The components include the Button,
Label, RadioButton, TextBox and many more. The Windows form is a square
container on the screen into which other components are placed.

All GUI components inherit from the Form class which is found in the
System.Windows.Forms namespace.

3.2.2 Controls in C#

The most common controls are listed and explained in Table 12. Each one of
these will be dealt with in greater detail later. It is a good idea to customise all
control names so that they are easier to identify. Give the control a descriptive
name with the control’s appropriate prefix.

Table 12 – Controls
Control Custom Prefix Description
Controls that are clicked to perform a certain
Button btn
action.
Clicking on a CheckBox causes it to switch
CheckBox chk
between a checked and unchecked state.
A drop-down list of choices. It performs
ComboBox cb similarly to the ListBox. The difference is that
a ComboBox is more compact than a ListBox.
Used to display text. Label controls cannot be
Label lbl
edited.
A list of items that is displayed inside a box.
ListBox lst
Multiple items can be selected.
A blank form used for organisation and
Panel pnl
layout.

Basic C# Programming | V1.0 August 2015 Page 167 of 276


RadioButton rdb A circle that can be selected or deselected.
Note that only one can be selected at a time
when used in a group.
ScrollBar scb Used to scroll either up or down, or to the left
or right of a container.
TextBox txt Allows text to be typed in via the keyboard. It
can be single or multiline.

Figure 28 should help to identify these controls.

Panel
control

ListBox
control

ScrollBar

Figure 28 – Common form components

3.2.3 Creating a GUI program in Visual Studio

3.2.3.1 Creating a new GUI program

 Select FILE > New > Project in Visual Studio (refer to Figure 29).

Basic C# Programming | V1.0 August 2015 Page 168 of 276


Figure 29 – New Windows Forms Application

The New Project dialog, as shown in Figure 30, is displayed.

Figure 30 – New Windows Forms Application project

 Click the Windows Forms Application icon, and enter a name for the
project, e.g. MyFormProject.

Visual Studio opens an empty form, as shown in Figure 31:

Figure 31 – An empty form

The Form1.cs [Design] tab is presented upon creation of a new Windows Form
Application while the Start Page tab closes automatically (as shown in Figure

Basic C# Programming | V1.0 August 2015 Page 169 of 276


32). The Start Page tab is opened upon launching Visual Studio. Code
generation only occurs once components are added.

Figure 32 – Form1.cs [Design] tab

The Toolbox tab appears on the left hand side of the screen, close to the top
where the page tabs are (as shown in Figure 32).

Table 13 contains common Form properties, methods and events.

Table 13 – Common properties, methods and events


Common Properties
AcceptButton The default button that is clicked when Enter is pressed.

CancelButton Button that is clicked when Esc is pressed.

Indicates whether ScrollBars appear when necessary


AutoScroll
(when data is bigger than the container it is in).

FormBorderStyle Border of the form (None, Single, Fixed3D, Sizable).

Font Font of text displayed on the form.

Text Text in the form’s title bar (at the top of the form).
Common Methods
Close Closes form and releases all resources.
Hides the form (does not release resources like Close
Hide
does).
Show Displays a hidden form.
Common Events
Occurs before a form is shown. The IDE generates a
Load default event-handler when the programmer double-clicks
on the form in the designer.

Basic C# Programming | V1.0 August 2015 Page 170 of 276


Click on the Toolbox tab and the Toolbox window will expand (as displayed in
Figure 33).

Figure 33 – The Toolbox window expanded

If the Toolbox tab is not displayed as described above, go to VIEW > Toolbox
(refer to Figure 34). It will then be displayed on the left-hand side of the
screen.

Figure 34 – Selecting the Toolbox window from View

3.2.3.2 Adding a Label and a Button control


 To add a Label, click on the Label icon in the Toolbox window.

A little cross appears and this can be used to position the component on the
Windows form. The control can also be dragged from the Toolbox to the
desired position (refer to Figure 35).

Basic C# Programming | V1.0 August 2015 Page 171 of 276


Figure 35 – Selecting a Label

 Click on the empty form after having selected Label control. A label will be
created as shown in Figure 36.

Figure 36 – Label on the form

The Properties window for the component that was added to the Windows form
appears in the bottom right hand corner. If it is not there, select View >
Properties Window. Figure 37 shows how the Properties Window may be
opened, and Figure 38 shows what the Properties window looks like.

Figure 37 – Properties Window

Figure 38 – Properties window

 Click on the Text property, and type ‘Hello World’.


 Press <Enter>.

Basic C# Programming | V1.0 August 2015 Page 172 of 276


The text on the Label changes to the text that is entered in the Text property
field. Figure 39 shows how to modify the property.

Figure 39 – Changing the text of the label

 Click on a Button control and add it to the form.


 Change the text of the Button control to ‘Press me!’.
 Change the (Name) of the Button control to ‘btnPress’.
 Change the (Name) of the Label control to ‘lblMessage’.

The size of a control can be changed by placing the cursor over the edges of
the control.

 Modify the Button control to the desired size.


 Double-click on the Button control to generate the code needed to make the
application work.

In the situation where some code is to be added, but not a control, simply
right-click on the empty form and select View Code. Alternatively, select
View > Code or simply press <F7>.

The following will be displayed in the editor window after the Button has been
double-clicked:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyFormProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void btnPress_Click(object sender, EventArgs e)

Basic C# Programming | V1.0 August 2015 Page 173 of 276


{
}
}
}

NOTE This creates another tab. There are now two .cs files open. One is
the Design file, and this is indicated by [Design] in square brackets
which appears after the file name. The other file, which has just been
opened, is the source code file.

Figure 40 shows the tabs that should be visible:

Figure 40 – Source code tab and Design tab

Notice how the class is defined as partial; this means that this source file is
not the entire class. The rest of it is defined elsewhere. In this case, there is
another source file that contains the definition needed to create the Form
interface. This file can be viewed by right-clicking on the Form1.Designer.cs in
the Solution Explorer and clicking View Code. However, this file should not be
modified as it is automatically generated by the Visual Studio Professional
Design View.

The result is:

Figure 41 – First GUI program

The current form does not contain much functionality, but this will be added in
the next section.

3.2.4 Events

Actions that are performed by clicking on a control are known as events;


however, clicking is not the only way to create events. The GUI was created to
be event-driven. In other words, the user interacts with the GUI by clicking a
control. Different events will occur for different components. The actions
determined when an event is triggered are specified by the programmer.

Basic C# Programming | V1.0 August 2015 Page 174 of 276


Both the Design view (at the top of the page) and the Toolbox window may be
used to drag and drop different components onto the form and then set their
properties in the Properties window. Note that it is not advisable to change the
code that is automatically generated when the component is double-clicked to
create an event (i.e. the event-handler declaration). Naturally it is safe to add
and modify user-code within the event-handler.

An event-handler for a component’s default event is automatically created


when that control is double-clicked in the design view. Do not change this
declaration.

private void btnPress_Click(object sender, EventArgs e)

The following concepts are important when looking at an event-handler:

 Event-handlers in the .NET Framework return void and take two


parameters.
 The first parameter is the object that identifies the source of event.
 The second parameter is an Object derived from EventArgs.
 The keyword EventArgs controls how the event property is accessed.
EventArgs is the_type_of variable e. Variable e specifies event details. For
example, the x-y location of a mouse-click for a Click event-handler.

Events and delegates are closely related. This is because flexible event-
handling requires that the response to the event is sent to the appropriate
handler.

Previously, the method of double-clicking on the Button control to create an


event-handler was used. There is, however, another way in which events may
be added.

 Click the Events button.

Figure 42 shows the Events window.

Events
Button

List of
Events

Current
Event
Handler

Figure 42 – Creating a Button event

 Double-click the Click event text box.

Basic C# Programming | V1.0 August 2015 Page 175 of 276


This creates an empty event-handler for the Click event of the Button. The
generated code automatically opens in the editor window. If another type of
event needs to be handled, then any one of those listed in the Event Properties
window (Figure 42) may be added by double-clicking the appropriate event
text box.

Modify the event-handler to look like the following:

private void btnPress_Click(object sender, EventArgs e)


{
// Message displayed in a label.
this.lblMessage.Text = "Thank you for pressing the button!";

// Message displayed in a separate message box.


MessageBox.Show("Button was pressed!");
}

 Run the program. The result is:

Figure 43

 Click Press me! and the MessageBox shown in Figure 44 appears:

Figure 44

 Click OK to go back to the Form1 window and the Label control changes as
shown in Figure 45:

Basic C# Programming | V1.0 August 2015 Page 176 of 276


Figure 45

3.2.5 Control properties and layout

The following table describes properties and methods that are common to all
controls:

Table 14 – Common properties and methods


Common Properties
BackColor Background colour of the control.
BackgroundImage Background image of the control.
Indicates whether the control is available for user
interaction. A button that can be pressed is enabled,
Enabled
whereas a grey button is disabled and cannot be
pressed.
Whether a control has focus. If a TextBox has focus,
Focused text can be entered with the keyboard. If a button has
focus, it is outlined with a dotted line.
The text for the control is displayed in the specified
Font
font.
Foreground colour of the control. It is usually used to
ForeColor
display the Text property of the control.
Sets the size of the control. The width is specified and
Size
then the height with a comma separating them.
The tab order of the control. It is set automatically
but can be reset by the programmer. When Tab is
TabIndex
pressed, focus is moved from one control to another
according to that control’s TabIndex value.
If its value is set to true, the Tab key can be used to
TabStop
select the control.
Text Text that will appear on the control.
The position of the text on the control. It can be left,
TextAlign centre, right (horizontal), top, middle, or bottom
(vertical).
Visible Sets whether a control is visible on the form.

Basic C# Programming | V1.0 August 2015 Page 177 of 276


Common Methods
Focus Transfers the focus to the control.
Hide Hides the control (sets the Visible property to false).
Show Shows the control (sets the Visible property to true).

3.2.5.1 Anchoring
Controls can be anchored or docked. When a control is anchored, it means that
control may be dynamically resized with the form. The Anchor property
describes an anchoring position for the control. When a control is anchored on
a form and the form is then resized, the control will remain a fixed distance
away from the form sides. Controls are anchored to Top, Left by default, so
there are no ‘un-anchored controls’.

Figure 46 demonstrates how the Anchor property is used.

Figure 46 – Original form, no problems

If the form above is resized without anchoring the control, the result is as
shown in Figure 47, since the position of the control does not depend on the
size of the form.

Figure 47 – Form resized, with un-anchored controls

Now change the Anchor property of both controls to Bottom, Left and Right.
The Anchor property is in the Properties window, as shown in Figure 48.

Basic C# Programming | V1.0 August 2015 Page 178 of 276


Figure 48 – Anchor property in the Properties window

The Button control will, in this case, always remain a fixed distance from the
bottom of the form and will either increase or decrease in size horizontally, and
the Label control will always remain a fixed distance from the top of the Button
control, as shown in Figure 49.

Figure 49 – Form resized, with the anchored controls

When the Anchor property is set to Bottom, Top, Left and Right, the control
will remain in the centre of the form. Play around with the Anchor property to
get a feel and understanding of it.

3.2.5.2 Docking
By using the Dock property, a control can be set to span one whole side of the
form. Using the Dock property attaches a control to the selected edge of the
form. The Fill dock option docks the control to all the sides of the form, and
causes it to fill up the entire form. Figure 50 shows how to modify the Dock
property of a control.

Figure 50 – Dock property in the Properties window

Basic C# Programming | V1.0 August 2015 Page 179 of 276


Even when the form is resized, Button will remain at the top of the form, as
shown in Figures 51 and 52.

Figure 51 – Form before resizing

Figure 52 – Form after resizing

3.2.6 TextBoxes

In this section the TextBox control is introduced with the use of Label controls
and Button controls. The TextBox control is designed to receive input from the
user of the program.

TextBox

Figure 53 – Form displaying a TextBox

 Create the form shown in Figure 53.


 Add a TextBox control (txtChange) and a Button control (btnChange).
 Now double-click on the TextBox control to create the event-handler.

The Source code view opens automatically when double-clicking on a control.


The Source code view can also be used to modify code. The TextBox control’s
event-handler is called TextChanged by default. Do not change the code that
has been generated as the event-handler may fail to perform any actions. Only
add code to the event-handler between the opening and closing brackets.

Basic C# Programming | V1.0 August 2015 Page 180 of 276


 Add the following code to the txtChange_TextChanged event-handler:

private void txtChange_TextChanged(object sender, EventArgs e)


{
// Set the text on the button to the text in the TextBox.
this.btnChange.Text = this.txtChange.Text;
}

 Run the program and enter some text into the TextBox control.

The text on the Button reflects the text entered into the TextBox, as shown in
Figure 54.

Figure 54 – The text in the TextBox is displayed on the Button

Table 15 contains the properties of TextBox controls that are frequently used.

Table 15 – TextBox properties


Properties Description
If set to True when <Enter> is pressed, a new line is
created if it is set as a multiline TextBox. If set to false,
AcceptsReturn
pressing Enter clicks the default button component of the
form.
If set to true, the TextBox control can span multiple lines.
MultiLine
The default value is false.
A single character (usually *) is used to display the value
PasswordChar entered instead of text. This is then a password TextBox. If
no character is specified, the typed text will appear.
If set to true, the user will not be able to enter any values or
ReadOnly text into the TextBox control. It will appear in grey and will
not be editable. The default is false.
When set as a MultiLine TextBox, this property specifies
ScrollBars which scrollbars will appear. They can be horizontal, vertical,
both or none.
Text This is the text to be displayed in the TextBox.
This indicates the position of the text in the TextBox. It can
TextAlign
be Left, Right, or Center. The default is Left.

In Figure 55, a password TextBox and a ReadOnly TextBox are demonstrated


in one.

 Create a new form as in Figure 55.

Basic C# Programming | V1.0 August 2015 Page 181 of 276


 Add a TextBox control (txtPassword) and a Button control (btnPassword).
 Change the TextBox control’s ReadOnly property to true.

Figure 55 – A password and read-only TextBox

 Double-click on the password TextBox to create the event-handler and add


the code snippet below to the source code:

private void txtPassword_TextChanged(object sender, EventArgs e)


{
// Set the text in the read-only TextBox to
// the text in the password TextBox.
this.btnPassword.Text = this.txtPassword.Text;
}

3.2.7 GroupBoxes and Panels

The GroupBox and Panel controls have very similar functions. They are both
used to group controls together. The GroupBox control displays a frame around
the group of controls and can contain a caption in the top left corner. The
reason for grouping certain controls is to create order.

When a GroupBox is added to the form, it has a border and a caption by


default. The caption can be changed or removed. Figure 56 shows what a
GroupBox looks like immediately after being added to a form.

Figure 56 – Newly added GroupBox

Table 16 shows the properties of a GroupBox control:

Basic C# Programming | V1.0 August 2015 Page 182 of 276


Table 16 – GroupBox properties
Property Description
The background colour of the GroupBox control can be
BackColor
changed as preferred.
BackgroundImage An image can be displayed in the background.
Gets a collection of the controls within the GroupBox
Controls
control.
If set to false, the controls within the GroupBox control will
Enabled
also be disabled.
The text contained within the caption in the top left hand
Text
corner.

The GroupBox control cannot use scrollbars. If this is desired, a Panel control
should be used instead. The difference between a GroupBox control and a
Panel control is that a GroupBox control contains a caption and a Panel control
can have a scrollbar.

Figure 57 shows what a GroupBox control looks like with controls added to it,
and what a Panel control looks like with scrollbars.

Figure 57 – GroupBox control and Panel control

Remember: containers need to be added first (the GroupBox control and/or the
Panel control), and only then may the other controls be placed within them.
These containers can be found in the Toolbox window, as previously described
(see Figure 58).

Basic C# Programming | V1.0 August 2015 Page 183 of 276


Figure 58 – The Toolbox window with GroupBox and Panel

Note that these controls are found under the sub-division called Containers. In
order to add scrollbars to the Panel control, go to the Properties window and
set the AutoScroll property to true (see Figure 59).

Figure 59 – Setting AutoScroll of the Panel control to true

3.2.8 Checkboxes and RadioButtons

CheckBox and RadioButton controls are state buttons. This means that they
have two states: true/false or on/off. There is a subtle but important difference
between a CheckBox and a RadioButton control. RadioButton controls are
generally grouped together and only one may be selected at a time. The
CheckBox control, on the other hand, is created to be ticked to indicate
selection, or to have the tick removed to indicate deselection. CheckBox
controls allow more than one option to be selected at any given time.

There are a few common CheckBox properties and events to note, as shown in
Table 17:

Basic C# Programming | V1.0 August 2015 Page 184 of 276


Table 17 – CheckBox/RadioButton properties and events
CheckBox RadioButton
Properties
Sets or gets the control’s
  Checked state. True if it is checked,
False otherwise.
Specifies or gets whether the
CheckBox is checked or
unchecked. It can be
 CheckState
CheckState.Indeterminate,
CheckState.Checked, or
CheckState.Unchecked.
Specifies the text displayed
  Text to the right of the square
box.
EVENTS
This event is raised every
time the CheckBox is either
checked or unchecked. This
  CheckedChange
is the default event when
this control is double-clicked
in the design view.
Raised when the CheckState
 CheckStateChanged
property changes.

 Create an application that looks like the one displayed in Figure 60.

 Add a Label control (lblText) and two CheckBox controls (chkBold and
chkItalics).

Figure 60– Testing CheckBox controls

 Add the event-handlers to the controls. Remember to double-click on


chkBold and then chkItalics to create the event-handlers:

private void chkBold_CheckedChanged(object sender, EventArgs e)


{
// Settings to change to Bold.
lblText.Font = new System.Drawing.Font(lblText.Font.Name,
lblText.Font.Size, lblText.Font.Style ^ System.Drawing.FontStyle.Bold);
}

private void chkItalics_CheckedChanged(object sender, EventArgs e)


{
// Settings to change to Italics.

Basic C# Programming | V1.0 August 2015 Page 185 of 276


lblText.Font = new System.Drawing.Font(lblText.Font.Name,
lblText.Font.Size, lblText.Font.Style ^ System.Drawing.FontStyle.Italic);
}

Using the Xor operator in the example above avoids having to test whether a
style is already bold or italic. The exclusive OR operator (Xor) tests two
conditions and returns true only if one of the conditions is true. If both of the
conditions are true, then it returns false. If both conditions are false, it also
returns false.

3.2.9 MessageBoxes

A MessageBox is used to display an appropriate message to the user when a


certain action is performed. In addition to displaying a message, a MessageBox
may also have a number of buttons which allows the user to make certain
choices. These include the Yes/No buttons, Yes/No/Cancel buttons, or a simple
OK button. There are also different icons available to suit the type of message
that is displayed to the user. The simplest MessageBox control only contains
some text together with an OK button that is used to close the MessageBox:

MessageBox.Show("This is a message box!");

Figure 61 shows what this will look like when it is run.

Figure 61 – A simple MessageBox displayed to the user

The following is the syntax used to add an icon and a title to the simple
MessageBox:

MessageBox.Show(Text, Title, MessageboxButtons, MessageBoxIcon);

MessageBoxButtons can have one of the following values:

 AbortRetryIgnore
 OK
 OKCancel
 RetryCancel
 YesNo
 YesNoCancel

Basic C# Programming | V1.0 August 2015 Page 186 of 276


MessageBoxIcon can have one of the following values:

 Asterisk
 Error
 Exclamation
 Hand
 Information
 None
 Question
 Stop
 Warning

The MessageBox control returns a DialogResult once a button has been


pressed. In the case of an OKCancel button, when the OK button is pressed the
DialogResult is DialogResult.OK.

The example below demonstrates this concept:

 Create a form as shown in Figure 62.


 Add a Button control (btnPress) and a Label control (lblResult).
 Create an event-handler for btnPress.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
// Add System.Windows.Forms to be able to use DialogResult.
using System.Windows.Forms;

namespace MessageBoxProgram
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void btnPress_Click(Object sender, EventArgs e)


{
// Creates the MessageBox with certain specifications.
DialogResult result = MessageBox.Show(
"Would you like to continue with this program?",
"Continue?", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question);

// If Yes is selected.
if (result == DialogResult.Yes)
{
lblResult.Text = "You pressed: Yes";
}
// If No is selected.
else if (result == DialogResult.No)
{

Basic C# Programming | V1.0 August 2015 Page 187 of 276


Application.Exit();
}
// If Cancel is selected.
else if (result == DialogResult.Cancel)
{
lblResult.Text = "You pressed: Cancel";
}
}
}
}

Figures 62, 63 and 64 show the various stages of this example program:

Figure 62 – Form when the program starts

Figure 63 – MessageBox displayed when btnPress is pressed

Figure 64 – Form after the Yes button was selected from the
MessageBox

When the user presses Cancel, the label will display ‘You pressed: Cancel’ and
when No is pressed, the application will simply exit.

Test the different MessageBoxButtons and MessageBoxIcons to get a proper


feel for them all.

3.2.10 Mouse events

All events may be added by clicking on the Events button in the Properties
window (see Figure 65).

Basic C# Programming | V1.0 August 2015 Page 188 of 276


Events
Button

Figure 65 – The events button in the Properties window

Table 18 contains the most common mouse events.

Table 18 – Common mouse events


Event Description
MouseClick Occurs when the control is clicked by the mouse.
Occurs when the mouse pointer is over the component
MouseDown
and a mouse button is pressed.
Occurs when the mouse enters the visible part of the
MouseEnter
control.
Occurs when the mouse remains stationary inside of the
MouseHover
control or for an amount of time.
Occurs when the mouse leaves the visible part of the
MouseLeave
control.
Occurs when the mouse pointer moves over the
MouseMove
component.
Occurs when the mouse pointer is over the component
MouseUp
and a mouse button is released.

 Create an application that looks like the one in Figure 67.


 Add a Button control (btnMouse).
 Click on the Button control and then the Events button.
 Double-click on the MouseEnter event.

The btnMouse_MouseEnter event-handler is automatically created, and the


Source Code tab is displayed (as explained earlier in this unit).

 Now create the btnMouse_MouseLeave event-handler by going back to the


Design tab and double-clicking on the MouseLeave event-handler.

The Event Properties window should now look like Figure 66.

Basic C# Programming | V1.0 August 2015 Page 189 of 276


Figure 66– The Mouse events of the Button control

Enter the following code into the generated event-handlers:

private void btnMouse_MouseEnter(object sender, EventArgs e)


{
// When the mouse enters the button.
this.btnMouse.Text = "Mouse entered here!";
}

private void btnMouse_MouseLeave(object sender, EventArgs e)


{
// When the mouse leaves the button.
this.btnMouse.Text = "Mouse just left!";
}

The results are (Figures 67 and 68):

Figure 67– MouseEnter event

Figure 68– MouseLeave event

3.2.11 Keyboard events

Keyboard events are generated when keys are pressed. These include
KeyPress, KeyDown and KeyUp. These are inherited from
System.Windows.Forms.Control.

Create the form shown in Figure 69.

Basic C# Programming | V1.0 August 2015 Page 190 of 276


Figure 69– KeyPress example form

Add the following code to the KeyPress, KeyDown and KeyUp event-handlers of
the form:

private void frmKeyPress_KeyPress(object sender, KeyPressEventArgs e)


{
// Display the character that was pressed. As the property keyChar
// suggests, it is used to retrieve the character pressed.
lblKeyPressed.Text = "Key pressed: " + e.keyChar;
}

private void frmKeyPress_KeyDown(object sender, KeyEventArgs e)


{
// Result from holding a key down. The ternary operator is used here to
// test whether a certain key has been pressed.
lblAlt.Text = "Alt: " + (e.Alt ? "Yes" : "No");
lblShift.Text = "Shift: " + (e.Shift ? "Yes" : "No");
lblCtrl.Text = "Ctrl: " + (e.Control ? "Yes" : "No");
lblKeyCode.Text = "KeyCode: " + e.KeyCode;
lblKeyData.Text = "KeyData: " + e.KeyData;
lblKeyValue.Text = "KeyValue: " + e.KeyValue;
}

private void frmKeyPress_KeyUp(object sender, KeyEventArgs e)


{
// Result from letting go of a key after holding it down, i.e. it is not
// being pressed anymore.
lblKeyPressed.Text = "Key pressed: ";
lblAlt.Text = "Alt: ";
lblShift.Text = "Shift: ";
lblCtrl.Text = "Ctrl: ";
lblKeyCode.Text = "KeyCode: ";
lblKeyData.Text = "KeyData: ";
lblKeyValue.Text = "KeyValue: ";
}

The result is:

Basic C# Programming | V1.0 August 2015 Page 191 of 276


Figure 70 – Output when Alt key is pressed

Basic C# Programming | V1.0 August 2015 Page 192 of 276


3.2.12 Exercises
1. Describe how to restore the Properties window to the screen,
should it not be visible.

2. Name six common controls.

3. What is the difference between anchoring and docking a


control?

4. Create a new Windows Forms application with Visual Studio


and place a Button control and a Label control onto the form.

 Change the Name property of the Button control to


btnClick, and its Text property to ‘Hello World’.
 Set the Label control’s Name property to lblHelloWorld
and its Text property to ‘Awaiting action’.
 Add code to the Button control’s Click event-handler to
change the Label control’s Text property to ‘Hello World!’

5. Create a new Windows Forms application with Visual Studio


and place a TextBox and a Button control on the form.

 Use the TextChanged event of the TextBox to change the


Button control’s text to that of the TextBox.
 Use the MouseEnter and MouseLeave event-handlers of
the TextBox to change the Button control’s text to ‘Mouse
Enter’ and ‘Mouse Leave’ respectively.

6. Create a new Windows Forms application with Visual Studio.

 Place one CheckBox, two RadioButtons and one TextBox


control on the form.
 Add code for the CheckBox to change the ReadOnly
property of the TextBox.
 Use the RadioButton controls to change the font size of
the TextBox to size 12 or 14.

3.2.13 Revision questions


1. True/False: The difference between the Panel control and the
GroupBox control is the ability to have a scrollbar.

2. The following are common properties of the components in


the C# GUI:
i. Invisible
ii. TabStop
iii. Size
iv. Color
v. BackgroundImage

Basic C# Programming | V1.0 August 2015 Page 193 of 276


Choose the most correct answer:
a. (iii) and (iv)
b. All of the given options.
c. (ii), (iii) and (v)
d. (i), (ii), (iii) and (iv)

3. True/False: AbortRetryIgnore is a type of MessageBoxButton.

Basic C# Programming | V1.0 August 2015 Page 194 of 276


3.3 More advanced controls

Atthe end of this section, you will be able to:


 Use PictureBox controls and the Image class.
 Add menu controls to an application.
 Use a LinkLabel.
 Identify the difference between the ListBox control, the
CheckedListBox control and the ComboBox control.
 Identify the different DialogBox types.
 Create and use an MDI application.

3.3.1 PictureBox controls and the Image class

The PictureBox control is a control that allows the user to displays an image.

The PictureBox control supports the following image formats:

 Bitmaps (*.bmp, *.dib)


 GIF images (*.gif)
 JPEG images (*.jpg)
 MetaFiles (*.wmf, *.emf)
 Icons (*.ico, *.cur)
 PNG images (*.png)

The Image class is found in the System.Drawing namespace. The most


commonly used method in the Image class is the FromFile() method, which
loads the file containing the image. Refer to Figure 71:

Figure 71 – Form with two PictureBox controls

Basic C# Programming | V1.0 August 2015 Page 195 of 276


 Create a new Windows Forms Application called PictureBoxDemo.
 Add two PictureBox controls to the form (pictureBox1 and pictureBox2).
 Click on the form and then the Events button in the Properties window.
 Double-click the Load event and add the following code:

private void Form1_Load(object sender, EventArgs e)


{
// Direct path to the images.
pictureBox1.Image = Image.FromFile("visualStudio.png");
pictureBox2.Image = Image.FromFile("fluid.png");
}

The whole source code document should look like the following:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PictureBoxDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)


{
// Direct path to the images.
pictureBox1.Image = Image.FromFile("visualStudio.png");
pictureBox2.Image = Image.FromFile("fluid.png");
}
}
}

Note that all the code is automatically generated except the Form1_Load
event. No other code is altered for this example. Merely add any
pictures/images to test the program above. Ensure that the name in the
FromFile() method matches the file in the bin\Debug folder. The SizeMode
property of the individual picture boxes may be altered. This places the image
either in the centre of the picture box or leaves it as normal. It may also be set
to AutoSize which adjusts the image to fit the picture box. Explore this option
to learn more. Also experiment with the option to change the background
colour.

It is, however, better to add any images to the project using the Solution
Explorer.

 Select pictureBox1 and select the Image property in the Properties


window.

Basic C# Programming | V1.0 August 2015 Page 196 of 276


 Click on the ellipsis button (…).

A dialog will open which is used to select images. This image will have to be
imported to the project first:

 Click Import.
 Use the file dialog to browse to the location of the image.
 Select the image and click Open.
 Select an image from the list of imported images and click OK.

This image will now be saved in the project’s Resources folder and is visible in
the Solution Explorer as show in Figure 72.

Figure 72 – Resources folder under the Solution Explorer

The selected image will now appear in pictureBox1. The image will, however,
be too big for the PictureBox control. To prevent this from happening, change
the PictureBox control’s SizeMode property.

Set the SizeMode property to AutoSize.

The image will now automatically resize and the whole image will be visible.

The next thing that needs to be possible is to change the image while the
application is running. The image has now been added to the project; however,
there is an easier way to do this via the Solution Explorer:

 In the Solution Explorer, right-click on the Resources folder.


 Select Add > Existing Item.
 Click on the drop-down menu on the right hand side of the File name: text
box and select Image Files.
 Browse to the location where the image is and select it.
 Click Add.

The image will now appear in the Resources folder in the Solution Explorer and
can be used in the application. The path provided to the image can be relative
or absolute. The relative path is from where the application’s .exe file is to

Basic C# Programming | V1.0 August 2015 Page 197 of 276


where the image is. The absolute path is the complete path from the drive
letter to the image.

NOTE Whenever possible, relative paths should be used. Applications that


use absolute paths are difficult to move between different computers,
as they will only work correctly if both the application and the files
which it uses or references, are in specific locations.

The image can be loaded with the following syntax in the Form_Load event-
handler:
pictureBox1.Image = Image.FromFile("../../Resources/visualStudio.png");
pictureBox2.Image = Image.FromFile("../../Resources/fluid.png");

A relative path is used to navigate from the bin/Debug directory to the


Resources directory. The PictureBox control’s SizeMode property can be set in
the Design view, or it can also be set in the code:

pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
pictureBox2.SizeMode = PictureBoxSizeMode.AutoSize;

The output will look the same as shown in Figure 71.

3.3.2 Menus

The main purpose of a menu control is to reduce the space taken up by


controls on the main form. Options placed in a Menu control are more
compact. This is done by adding a MenuStrip control to the MainForm and then
adding ToolStripMenuItems to the MenuStrip control. Menus can also be added
programmatically to the form.

3.3.2.1 Creating a menu using Visual Studio


 Start by creating a new Windows Forms Application and naming it.
 Add the MenuStrip control to the Form. This is found in the Toolbox
window under the Menus & Toolbars subsection. It will be necessary to
scroll down to find it (refer to Figure 73).

Figure 73 – Menus & Toolbars subsection

The form will look like Figure 74 once the MenuStrip has been added.

Basic C# Programming | V1.0 August 2015 Page 198 of 276


Figure 74 – MenuStrip on the MainForm

 Type ‘File’ in the box and press Enter.


 Select the box that appears below the File menu item, and type ‘Exit’.

The menu should now look like Figure 75:

Figure 75 – File and Exit added

More ToolStripMenuItems can be added to the MenuStrip by typing in one of


the ‘Type Here’ boxes. Each box represents a different location, and, if typed
in, will create a new menu item in that location. All ToolStripMenuItems can
have one or more sub-menus which are themselves made up of
ToolStripMenuItems. These sub-menus are added by typing in the box that
appears to the right of the currently selected ToolStripMenuItem. The process
used to create and modify a sub-menu is much the same as with a top-level
menu.

3.3.2.2 Adding event-handlers to menu items


 Select the Exit ToolStripMenuItem and click on the Events button.
 Double-click on the Click event to generate the Click event-handler for the
Exit ToolStripMenuItem.
 Add the following code to the event-handler:

private void exitToolStripMenuItem_Click(object sender, EventArgs e)


{
// Exits the application.
Application.Exit();
}

If the Exit ToolStripMenuItem is clicked while the application is running, the


application will close.

Basic C# Programming | V1.0 August 2015 Page 199 of 276


3.3.2.3 Creating a menu programmatically
Another way to add ToolStripMenuItems to the MenuStrip is to use the Add()
method in the source code.

 Create a new Windows Forms Application.


 Create a Load event-handler for the form.
 Add the code below to the event-handler:

1 private void frmMenuDemo_Load(object sender, EventArgs e)


2 {
3 MainMenu mnuFileMenu = new MainMenu();
4 this.Menu = mnuFileMenu;
5
6 MenuItem myMenuItemFile = new MenuItem("&File");
7 MenuItem myMenuItemNew = new MenuItem("&New");
8
9 mnuFileMenu.MenuItems.Add(myMenuItemFile);
10 myMenuItemFile.MenuItems.Add(myMenuItemNew);
11
12 MenuItem myMenuItemFolder = new MenuItem("&Folder");
13 myMenuItemNew.MenuItems.Add(myMenuItemFolder);
14
15 mnuFileMenu.MenuItems.Add("Save &As");
16 }

On line 3 the MainMenu is simply added to the Form. The order in which the
MenuItems are added to the form is also the order in which they will be
displayed.

3.3.2.4 Separators
To add a separator line in a menu, simply enter a hyphen (‘-’) where it says
‘Type Here’ or use the Design View. Separators are used to create logical and
ordered menu layouts as shown in Figures 76 and 77.

Figure 76 – Adding a separator

Figure 77– Separator added to the menu

Basic C# Programming | V1.0 August 2015 Page 200 of 276


3.3.2.5 Access shortcuts
Access shortcuts allow the user to access the menu options by pressing a
keyboard button. The menu items are accessed by using <Alt> together with
the underlined letter in the MenuItem. The access shortcut is created by
adding an ampersand (&) before the letter to be underlined. In the previous
example, the File MenuItem uses <F> as its access shortcut.

 Try holding down <Alt> and then pressing the access shortcut keys to see
how they function.

Figure 78 shows how access shortcuts are underlined in menus.

Figure 78 – Access shortcuts

3.3.3 LinkLabel controls

LinkLabel controls are similar to hyperlinks on a Web page. LinkLabel


properties are shown in Table 19.

Table 19 – LinkLabel properties


PROPERTY DESCRIPTION
Text The text that will be displayed in the LinkLabel control.
The colour of the link before it is clicked. Its default colour
LinkColor
is blue.
Determines if the link has been visited. Returns a Boolean
LinkVisited
value of true/false.
The colour of the link after it has been clicked. Its default
VisitedLinkColor
colour is purple.
The colour of the link while being clicked on. Its default
ActiveLinkColor
colour is red.

Basic C# Programming | V1.0 August 2015 Page 201 of 276


LinkLabel controls are very similar in functionality to Button controls, and may
be used as such in .NET applications.

3.3.4 ListBox, CheckedListBox and ComboBox

3.3.4.1 ListBox

The main purpose of a ListBox control is to list multiple items in one list. Some
common ListBox properties are shown in Table 20.

Table 20 – ListBox properties


PROPERTY DESCRIPTION
Specifies whether or not the ListBox allows
SelectionMode
the selection of multiple items.
Indicates if values should be displayed in
MultiColumn
columns horizontally.
Specifies a collection of currently selected
SelectedItems
items in the ListBox control.
Specifies a single selected item in the ListBox
SelectedItem
control.

The following example demonstrates how items can be added to a ListBox


control by programming code and how the MultiSimple SelectionMode property
is used in the ListBox control.

 Enter the code below into the FormLoad event of the application:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)


{
lstDemo.Items.AddRange(new object[]
{
"Golf",
"Mazda",
"Hyundai",
"VW",
"Honda",

Basic C# Programming | V1.0 August 2015 Page 202 of 276


"BMW",
"Mercedes"
});
}
}
}

The result is:

Figure 79 – Selecting multiple ListBox items

Many values can be added to the ListBox by clicking on the Items property in
the Property window. See Table 21 for a list of methods for the ListBox control.

In order to add one item at a time, the following code can be used:

lstDemo.Items.Add("Jaguar");

The result is:

Figure 80 – Adding an item to the ListBox control

In order to iterate through a collection in the ListBox control, the following


code can be used:

int numItems = 0;

for (int i = 0; i < lstDemo.Items.Count; i++)


{
numItems = numItems + 1;
}

lblCount.Text = "There are " + numItems.ToString() + " items in the ListBox";

Basic C# Programming | V1.0 August 2015 Page 203 of 276


The result is:

Figure 81 – Counting the number of items in a ListBox control

Table 21 – ListBox methods


Methods Description
Returns the index of the first item in the list that
FindString(String)
starts with the specified String.
Returns the index of the first item in the list that
FindStringExact(String)
matches the specified String exactly.
Returns a Boolean value that indicates whether
GetSelected(Integer) or not the item with the specified index is
selected.
ClearSelected() Deselects all items in the ListBox control.

3.3.4.2 CheckedListBox
The CheckedListBox is very similar to the ListBox control. When an item is
checked or unchecked, an ItemCheck event occurs. The CheckedItems
property specifies a collection of the currently selected items.

 Enter the code below into the FormLoad event:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)

Basic C# Programming | V1.0 August 2015 Page 204 of 276


{
chkLstDemo.Items.AddRange(new object[]
{
"Golf",
"Mazda",
"Hyundai",
"VW",
"Honda",
"BMW",
"Mercedes",
"Jeep",
"Fiat",
"Ford"
});
}
}
}

Figure 82 shows what a CheckedListBox looks like.

Figure 82 – CheckListBox

 Add the following line to the previous code to add individual items:

chkLstDemo.Items.Add("Lexus");

The result is:

Figure 83 – CheckListBox output 2

Basic C# Programming | V1.0 August 2015 Page 205 of 276


 Add the following code segment to the previous code to iterate through the
items:

int numItems = 0;

for (int i = 0; i < chkLstDemo.Items.Count; i++)


{
numItems = numItems + 1;
}

lblCount.Text = "There are " + numItems.ToString() +


" items in the CheckedListBox";

The result is:

Figure 84 – CheckListBox output 3

3.3.4.3 ComboBox
A ComboBox can be thought of as a drop-down box. Only one value is visible
until such time as the drop-down button is clicked, and the user may then
select any one of the values displayed. Once the selection has been made, the
other values are hidden again. Only one value can be selected at a time from
the ComboBox control. Figure 85 shows a typical ComboBox control.

 Add the following code to the FormLoad event of the application:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{

Basic C# Programming | V1.0 August 2015 Page 206 of 276


public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)


{
cmbDemo.Text = "Cars";

cmbDemo.Items.AddRange(new object[]
{
"Golf",
"Mazda",
"Hyundai",
"VW",
"Honda",
"BMW",
"Mercedes"
});
}
}
}

The result is:

Figure 85 – Typical ComboBox control

The ComboBox control has a Text property that can be changed when the
application is first run. If no text is entered into the Text property, the
ComboBox will be left blank. When the arrow on the right-hand side of the
ComboBox is clicked, the items will appear. In order to add items to the
ComboBox at design time, select the Items property from the Properties
window. Click on the ‘…’ button and a separate window appears where the
items are added one at a time.

When the application is run and a different item is selected from the list, the
SelectedIndexChanged event will be triggered. Another property that may be
of great use is the MaxDropDownItems property. It is used to specify the
maximum number of items that may be displayed when the arrow is clicked on
the right hand side of the ComboBox.

 Add the following line of code to the previous code:

Basic C# Programming | V1.0 August 2015 Page 207 of 276


cmbDemo.Items.Add("Jaguar");

The result is:

Figure 86 – Output using a ComboBox control

 Add the following code segment to the previous code:

int numItems = 0;

for (int i = 0; i < cmbDemo.Items.Count; i++)


{
numItems = numItems + 1;
}

lblCount.Text = ("There are " + numItems.ToString() + " in the ComboBox");

The result is:

Figure 87 – Output 2 using a ComboBox control

Basic C# Programming | V1.0 August 2015 Page 208 of 276


3.3.5 Dialogs

Dialogs are special windows designed to interact with the user, to provide
information and/or obtain information from them. In C#, Dialogs are derived
from the CommonDialog class. There are many different DialogBox controls.
They are found in the Toolbox window under the Dialogs section and are
listed below:

 ColorDialog
 FolderBrowserDialog
 FontDialog
 OpenFileDialog
 SaveFileDialog

 Create a new Windows Forms Application and call it ColorDialogAppl.


 Add a Button control (btnChange) and a ColorDialog control (colorDialog1)
to the form.
 Add the following code to the Source code view:

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10
11 namespace ColorDialogAppl
12 {
13 public partial class Form1 : Form
14 {
15 public Form1()
16 {
17 InitializeComponent();
18 }
19
20 private void btnChange_Click(object sender, EventArgs e)
21 {
22 if (colorDialog1.ShowDialog() == DialogResult.OK)
23 {
24 // Sets the background colour.
25 this.BackColor = colorDialog1.Color;
26 }
27 }
28 }
29 }

Take note of the reference made to the Colour Dialog. Whilst Dialogs can be
added to the form, remember to add the ShowDialog() method manually as
shown on line 22. The ColorDialog control is used in this example to change
the background colour. Explore the effect of placing different Dialogs on the
form.

Basic C# Programming | V1.0 August 2015 Page 209 of 276


3.3.6 MDI (Multiple-Document Interface)

MDI allows multiple windows or documents to be opened inside another


window. This concept is easy to understand and the example below is self-
explanatory.

 Set the IsMdiContainer property of the form to true.


 Alter the Text property to ‘Main Form’ and the Name property of the form to
‘MainForm’.
 Modify the code so that it looks like the following:

using System;
using System.Collections.Generic;
using System.Componentmodel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MDIExample
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComp();
}

private void MainForm_Load(object sender, EventArgs e)


{
// MainForm:
this.AutoScaleDimensions = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(300, 300);
this.IsMdiContainer = true;
this.Text = "Main Form";

// Creates four child forms in the parent form.


for (int i = 0; i < 4; i++)
{
ChildForm cf = new ChildForm();
cf.MdiParent = this;
cf.Show();
}
}
}

// Creates child forms with all settings.


class ChildForm : Form
{
public ChildForm()
{
InitializeComp();
}

void InitializeComp()
{
// ChildForm:
this.Text = "Child Form";
this.Size = new System.Drawing.Size(150, 150);

Basic C# Programming | V1.0 August 2015 Page 210 of 276


}
}
}

The result is:

Figure 88 – MDI with four Child Forms

In addition to showing how MDI works, this example also illustrates how
modifying form properties in the source code modifies how a program
functions at runtime.

Basic C# Programming | V1.0 August 2015 Page 211 of 276


3.3.7 Exercises
1. What does the SelectedItem property of the ListBox
control do?

2. How do you make use of an access shortcut?

3. What is the design purpose of a menu control?

4. Name five dialog types.

5. Write a line of code that loads an image called ‘pic.bmp’


into a PictureBox control named picBox. Assume the
image is located in the current directory.

3.3.8 Revision questions


1. Which three of the following are properties or methods
of a ListBox object?
a. SelectionMode
b. ModeSelection
c. SelectItems
d. SelectedItems
e. SelectItem
f. SelectedItem

2. True/False: Separators are added to menus by


specifying a star (‘*’) for the Text property of a
MenuItem.

3. The following image formats are supported:


i. Bitmaps
ii. GIF images
iii. JPEG images
iv. MetaFiles
v. Icons

Choose the most correct answer:


a. Options (i) – (v)
b. (iv) and (v)
c. None of the given options.
d. (i), (ii) and (iii)

Basic C# Programming | V1.0 August 2015 Page 212 of 276


3.4 String manipulation and regular
expressions

At the end of this section you will be able to:


 Use all the different methods with the String class and
the StringBuilder class.

3.4.1 The string class

3.4.1.1 The static methods

This section deals with the following static methods:

Table 22 – String class static methods


Method Description
Compare() Compares two string values.
Compares two string objects by evaluating their numeric
CompareOrdinal()
values.
Concat() Combines two string values.
Copy() Copies characters from one string into another string.
Equals() Compares two string values to check for equality.
Format() Changes a string into a certain format.
Checks if a value exists within a pool of values. If it does
Intern()
not exist, it is created.
Similar to Intern(), but does not create a string if it does
IsInterned()
not exist.
Concatenates an array of string values into a single
Join()
string value.

3.4.1.1.1 The Compare() method


The Compare() method compares two string values. Compare() returns an
integer indicating the equality of the two string values being compared.

 If the value is less than zero, then StringA (the first string) is less than
StringB (the second string).
 If the value is zero, then StringA is equal to StringB.
 If the value is greater than zero, then StringA is greater than StringB.

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace CompareExample
8 {

Basic C# Programming | V1.0 August 2015 Page 213 of 276


9 class Program
10 {
11 static void Main(string[] args)
12 {
13 CompareStrings();
14 }
15
16 static void CompareStrings()
17 {
18 string str1 = "HEY THERE";
19 string str2 = "hey there";
20 string str3;
21 int result;
22
23 // Compare() method:
24 Console.WriteLine("--The Compare method--");
25 Console.WriteLine("str1 = '{0}', str2 = '{1}'", str1, str2);
26 result = string.Compare(str1, str2);
27 str3 = ((result < 0) ? "less than" : ((result > 0) ?
28 "greater than" : "equal to"));
29 Console.WriteLine("str1 {0} is {1} {2}", str1, str3, str2);
30 // Compare() with ignore case set to true.
31 Console.WriteLine("Comparing, ignoring case");
32 result = string.Compare(str1, str2, true);
33 str3 = ((result < 0) ? "less than" : ((result > 0) ?
34 "greater than" : "equal to"));
35 Console.WriteLine("str1 {0} is {1} {2}", str1, str3, str2);
36 Console.ReadLine();
37 }
38 }
39 }

The ternary operator is used in the above example to determine which string
should be used for the result.

This is the result:

--The Compare method--


str1 = 'HEY THERE', str2 = 'hey there'
str1 HEY THERE is greater than hey there
Comparing, ignoring case
str1 HEY THERE is equal to hey there

Pay careful attention to line 32:

string.Compare(string strA, string strB, bool ignoreCase);

strA is the first string value.


strB is the second string value.
ignoreCase indicates whether or not case should be checked.

3.4.1.1.2 The CompareOrdinal() method


The CompareOrdinal() method compares two string objects by evaluating the
numeric values of the corresponding char objects in each string.

Basic C# Programming | V1.0 August 2015 Page 214 of 276


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

namespace CompareOrdinalExample
{
class Program
{
static void Main(string[] args)
{
string str1 = "ABCD";
string str2 = "abcd";
string str3;
int result;

Console.WriteLine();
Console.WriteLine("Compare the numeric values of the " +
"corresponding Char objects in each " +
"string.");
Console.WriteLine("str1 = '{0}', str2 = '{1}'", str1, str2);

result = string.CompareOrdinal(str1, str2);


str3 = ((result < 0) ? "less than" : ((result > 0) ?
"greater than" : "equal to"));

Console.WriteLine("String '{0}' is ", str1);


Console.WriteLine("{0}", str3);
Console.WriteLine("String '{0}'.", str2);
Console.ReadLine();
}
}
}

This is the result:

Compare the numeric values of the corresponding Char objects in each string.
str1 = 'ABCD', str2 = 'abcd'
String 'ABCD' is
less than
String 'abcd'.

3.4.1.1.3 The Concat() method


The Concat() method takes two string values and joins them together.

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

namespace ConcatExample
{
class Program
{
static void Main(string[] args)
{
string fName = "Suhayl ";
string lName = "Asmal";
// Concatenate the two strings.
Console.WriteLine("Hello {0}!", string.Concat(fName, lName));

Basic C# Programming | V1.0 August 2015 Page 215 of 276


Console.ReadLine();
}
}
}

This is the result:

Hello Suhayl Asmal!

3.4.1.1.4 The Copy() method


The Copy() method copies the characters in one string value into another.

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace CopyExample
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 string strA = "abc";
14 string strB = "xyz";
15
16 Console.WriteLine("strA BEFORE copying = '{0}'", strA);
17 Console.WriteLine("strB BEFORE copying = '{0}'", strB);
18 Console.WriteLine("Copying...");
19 // Copying strA and storing it in strB.
20 strB = string.Copy(strA);
21 Console.WriteLine("strA AFTER copying = '{0}'", strA);
22 Console.WriteLine("strB AFTER copying = '{0}'", strB);
23 Console.ReadLine();
24 }
25 }
26 }

This is the result:

strA BEFORE copying = 'abc'


strB BEFORE copying = 'xyz'
Copying...
strA AFTER copying = 'abc'
strB AFTER copying = 'abc'

The method on line 20 makes a copy of a strA. Here strB, which was previously
‘xyz’ on line 14, is now replaced with the copied string ‘abc’. This is then
displayed on line 22, and illustrates the difference clearly.

Basic C# Programming | V1.0 August 2015 Page 216 of 276


3.4.1.1.5 The Equals() method
The Equals() method determines if one string value is equal to another.

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace EqualsExample
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 string strA = "abcd";
14 string strB = "abcd";
15 Object obj = null;
16
17 Console.WriteLine();
18 Console.WriteLine("**strA's value is '{0}'.", strA);
19 Console.WriteLine();
20
21 obj = strB;
22 Console.WriteLine("The value of Object obj is '{0}'",
23 strA.Equals(obj));
24 Console.WriteLine();
25 Console.WriteLine("String.Equals(String)");
26 Console.WriteLine("The value of String strB is '{0}'."
27 , strB);
28 Console.WriteLine("Is strA equal to strB?: {0}",
29 String.Equals(strA, strB));
30 Console.WriteLine();
31 Console.WriteLine("String.Equals(String, String)");
32 Console.WriteLine("Is strA equal to strB?: {0}",
33 strA.Equals(strB));
34 Console.ReadLine();
35 }
36 }
37 }

This is the result:

**strA's value is 'abcd'.

The value of Object obj is 'True'.

String.Equals(String)
The value of String strB is 'abcd'.
Is strA equal to strB?: True

String.Equals(String, String)
Is strA equal to strB?: True

The Equals() method evaluates to either true or false. On lines 22 and 23, the
object obj is displayed and then checked against strA to see whether or not
they are equal. It should be found that the result is true. strA and strB are
then compared on line 29 and 30. This result is also true.

Basic C# Programming | V1.0 August 2015 Page 217 of 276


3.4.1.1.6 The Format() method
The Format() method functions in much the same way as formatting a string
when writing to the console:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace FormatExample
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 string result;
14 string strA = "String A";
15 string formatString = "{0, 10}";
16
17 // Format specified string.
18 result = string.Format(formatString, strA);
19 Console.WriteLine("string.Format({0}, {1}) = [{2}]",
20 formatString, strA, result);
21 Console.ReadLine();
22 }
23 }
24 }

Pay careful attention to lines 19 and 20:

string format, object arg0, object arg1, object arg2

string format is the string value to be displayed to the console.

object arg0 is the first object to write using format. In this case it is equal to
"{0, 10}".

object arg1 is the second object to write using format. In this case it is equal
to strA which is equal to "String A".

object arg2 is the third object to write using format. In this case it is equal to
the result on line 18.

This method returns a string value after a certain format string has been
applied to it. This is the result:

string.Format((0, 10), String A) = [ String A]

3.4.1.1.7 The Intern() method


The CLR stores strings by maintaining a table (called the intern pool) that
contains a single reference to each unique string value. Due to this, each
unique string value only needs to be stored in memory once, no matter how
many variables it might be assigned to. However, this optimisation is only
automatically performed on strings created at compile-time. The Intern()

Basic C# Programming | V1.0 August 2015 Page 218 of 276


method searches through the intern pool to see if the value already exists. If it
does, then the method will return a reference to that value. If not, then the
value will be stored in memory and a new reference will be returned.

This method is generally only used when creating large numbers of long,
complicated strings which have a high probability of being the same.

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

namespace InternExample
{
class Program
{
static void Main(string[] args)
{
string sA = "MySummer";

// Append the specified string:


// Usage of the StringBuilder class will be explained later in
// this unit. It is used here to bypass the standard method of
// string creation.

StringBuilder sBuilder = new StringBuilder();


sBuilder.Append("My");
sBuilder.Append("Summer");

string sB = sBuilder.ToString();
string sC = string.Intern(sB);

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


Console.WriteLine("sB == '{0}'", sB);
Console.WriteLine("sC == '{0}'", sC);
Console.WriteLine("Is sB the same reference as sA?: {0}",
(Object)sB == (Object)sA);
Console.WriteLine("Is sC the same reference as sA?: {0}",
(Object)sC == (Object)sA);
Console.ReadLine();
}
}
}

This is the result:

sA == 'MySummer'
sB == 'MySummer'
sC == 'MySummer'
Is sB the same reference as sA?: False
Is sC the same reference as sB?: True

3.4.1.1.8 The IsInterned() method


This method functions in a similar manner to the Intern() method. The
difference, however, is that should an existing reference not be found, then the
method will not create a new string and return the reference. Instead, it will
return null. It can therefore be used in an if statement to check whether a
string has been interned or not.

Basic C# Programming | V1.0 August 2015 Page 219 of 276


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

namespace IsInternedExample
{
class Program
{
public static void Main()
{
// String strA is known at compile-time, and is automatically
// interned.
String strA = "abcd";

// Create a string with the StringBuilder class


StringBuilder sb = new StringBuilder();
sb.Append("wx");
sb.Append("yz");

String strB = sb.ToString();

// Call the public method Run, sending two parameters: int and
// string.
Run(1, strA);
Run(2, strB);
Console.ReadLine();
}

// Static method Run receives two parameters: int and string.


static void Run(int sequence, String str)
{
Console.Write("{0}) The string, '", sequence);
String strInterned = String.IsInterned(str);

// Checks if strIntered is null and performs tasks accordingly.


if (strInterned == null)
{
Console.WriteLine("{0}', is not interned.", str);
}
else
{
Console.WriteLine("{0}', is interned.", strInterned);
}
}
}
}

The result is:

The string, 'abcd', is interned.


The string, 'wxyz', is not interned.

Basic C# Programming | V1.0 August 2015 Page 220 of 276


3.4.1.1.9 The Join() method
This method concatenates an array of string values together into one string
value.

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace JoinExample
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 String[] val = { "MintCrisp", "Tempo", "KitKat", "BarOne" };
14 String sep = ", ";
15 String result;
16 Console.WriteLine("sep = '{0}'", sep);
17 Console.WriteLine("val[] = {{'{0}' '{1}' '{2}' '{3}'}}",
18 val[0], val[1], val[2], val[3]);
19 result = String.Join(sep, val, 1, 3);
20 Console.WriteLine("String.Join(sep, val, 1, 3) = '{0}'",
21 result);
22 Console.ReadLine();
23 }
24 }
25 }

This is the result:

sep = ', '


val[] = {'MintCrisp' 'Tempo' 'KitKat' 'BarOne'}
String.Join(sep, val, 1, 2) = 'Tempo, KitKat, BarOne'

First an array of chocolate values is created on line 12 as well as a string ‘sep’


which contains a comma on line 13. Lines 15 and 16 print out all the values in
the array. Remember, an array always starts at zero. Therefore, when looking
at line 18, where the Join() method is used, the parameters will follow like
this: firstly the string that will be separating each value from the array is
specified, then the array which will be used, in this case val, and lastly two
array indexes which specify which elements to join (i.e. which element to start
at, and which element to stop at). These are all assigned to a newly created
string result on line 18, and then displayed using the console at the end of the
program.

3.4.1.2 The instance methods


Instance methods of the String class include: Clone(), CompareTo(), CopyTo(),
EndsWith(), Equals(), GetEnumerator(), IndexOf(), Insert(), LastIndexOf(),
PadLeft(), PadRight(), Remove(), Replace(), Split(), StartsWith(), SubString(),
ToCharArray(), ToLower(), ToUpper(), Trim(), TrimEnd() and TrimStart().

Note that none of these methods change the original string. Instead, they
return a changed version of the original string. If the original value needs to be

Basic C# Programming | V1.0 August 2015 Page 221 of 276


replaced by the new one, the returned value needs to be assigned to the
string.

The following example shows how some of these methods work:

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

namespace StringInstanceMethods
{
class Program
{
static void Main(string[] args)
{
// Declare a string to test the methods with .
String testString = "This is a test string";

// Various instance method tests.


Console.WriteLine("Original string : \"" + testString + "\"");
Console.WriteLine("ToLower() : \"" + testString.ToLower() +
"\"");
Console.WriteLine("ToUpper() : \"" + testString.ToUpper() +
"\"");
Console.WriteLine("EndsWith(\"string\") : "
+ testString.EndsWith("string"));
Console.WriteLine("StartsWith(\"string\") : "
+ testString.StartsWith("string"));
Console.WriteLine("Replace(' ', '-') : \""
+ testString.Replace(' ', '-') + "\"");
Console.WriteLine("CompareTo(testString.ToLower()) : "
+ testString.CompareTo(testString.ToLower()));
Console.WriteLine("SubString(5,10) : \""
+ testString.Substring(5, 10) + "\"");

// Convert to an array and display via a for loop.


Console.WriteLine("ToCharArray() (output via for loop): ");
char[] charArray = testString.ToCharArray();
for (int loop = 0; loop < charArray.Length; loop++)
{
Console.Write(charArray[loop] + " ");
}

// Pause.
Console.ReadLine();
}
}
}

This is the result:

Original string : "This is a test string"


ToLower() : "this is a test string"
ToUpper() : "THIS IS A TEST STRING"
EndsWith("string") : True
StartsWith("string") : False
Replace(' ', '-') : "This-is-a-test-string"
CompareTo(testString.ToLower()) : 1
SubString(5,10) : "is a test "

Basic C# Programming | V1.0 August 2015 Page 222 of 276


ToCharArray() (output via for loop):
T h i s i s a t e s t s t r i n g

Many other methods (and overloads) in the String class have not been shown
in the above example. Try using Visual Studio’s code completion feature to
learn more about them:

Figure 89 – Using code completion

3.4.1.3 Properties and indexers of the string class


The String class defines a single property and one indexer – the Length
property and the String indexer.

The Length property returns the number of characters in a string value. In the
following example, the Length property is used to get the number of characters
in str. The result is a value of 5.

int count;
string str = "hey";
count = str.Length;
Console.WriteLine("str.Length: {0}", count);

The String indexer returns a character within the string at a specific location.
In the example below, the indexer extracts the second character from a zero-
based count on str. The result is the character ‘t’.

char count;
string str = "hey there";
count = str[4];
Console.WriteLine("str[4]: {0}", count);

3.4.2 The StringBuilder class

The StringBuilder class is designed to create strings.

3.4.2.1 The instance methods


Append(), AppendFormat(), EnsureCapacity(), Equals(), Insert(), Remove(),
Replace() and ToString() are all instance methods of the StringBuilder class.
The following example shows the basics of the Append() method:

Basic C# Programming | V1.0 August 2015 Page 223 of 276


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

namespace StringBuilderExample
{
class Program
{
static void Main(string[] args)
{
// Declare an instance of the StringBuilder class.
StringBuilder sb = new StringBuilder();
// Declare an array of strings.
string[] wordArray = { "This", "string", "has", "been",
"constructed", "using", "a",
"StringBuilder"};
for (int loop = 0; loop < wordArray.Length; loop++)
{
sb.Append(wordArray[loop]);
if (loop != wordArray.Length – 1)
{
sb.Append(" ");
}
else
{
sb.Append(".");
}
}

// Convert our StringBuilder back into a string.


string result = sb.ToString();
Console.WriteLine(result);
// Pause.
Console.ReadLine();
}
}
}

This is the result:

This string has been constructed using a StringBuilder.

Why use a StringBuilder when the same functionality is available simply by


using concatenation? Simply put, the StringBuilder is more efficient when
creating large complicated strings. For creating simple strings, concatenation is
more than adequate.

Note that the Append() method can be used to append values of almost any
type to the StringBuilder, not just other string values.

3.4.2.2 Properties and indexers of the StringBuilder class


The StringBuilder has several properties but only one indexer. The properties
include Capacity, Length and MaxCapacity. The Capacity property sets and
returns the number of characters the StringBuilder can hold.

StringBuilder myStringBuilder;
int count;

Basic C# Programming | V1.0 August 2015 Page 224 of 276


myStringBuilder = new StringBuilder("It's summer time");
count = myStringBuilder.Capacity;
Console.WriteLine("myStringBuilder.Capacity: {0}", count);

The result is:

myStringBuilder.Capacity: 16

The Length property returns the number of characters in the StringBuilder.

StringBuilder myStringBuilder;
int count;
myStringBuilder = new StringBuilder("It's summer time");
count = myStringBuilder.Length;
Console.WriteLine("myStringBuilder.Length: {0}", count);

The result is:

myStringBuilder.Length: 16

The MaxCapacity property is a read-only property that returns the maximum


number of characters this StringBuilder can hold.

StringBuilder myStringBuilder;
int count;
myStringBuilder = new StringBuilder("It's summer time");
count = myStringBuilder.MaxCapacity;
Console.WriteLine("myStringBuilder.MaxCapacity: {0}", count);

The result is:

myStringBuilder.MaxCapacity: 2147483647

The indexer allows reading and writing of a specific character at a specific


location.

StringBuilder myStringBuilder;
char count;
myStringBuilder = new StringBuilder("It's summer time");
count = myStringBuilder[3];
Console.WriteLine("myStringBuilder[3]: {0}", count);

The result is:

myStringBuilder[3]: s

3.4.3 String formatting

Table 23 lists all the format strings available. Note that the format string is not
case-sensitive, e.g. {0:c} and {0:C} will produce the same result. The
following shows the general syntax used for formatting a string:

{0: specifier}

Basic C# Programming | V1.0 August 2015 Page 225 of 276


Table 23 – String formatting specifiers
Output Output
Specifier Type Format (Passed double (Passed int
1.42) 12400)
c Currency {0:c} R1.42 R12,400
Decimal System.FormatExcepti
d {0:d} 12400
(whole) on
e Scientific {0:e} 1.420000e+000 1.240000e+004
f Fixed point {0:f} 1.42 12400.00
g General {0:g} 1.42 12400
Number
with
n commas {0:n} 1.42 12,400.00
for
thousands
Rounding System.FormatExceptio
r {0:r} 1.42
off n
Hexadecim {0:x} System.FormatExcepti
x cf90
al on

Table 24 shows how numbers can be formatted:

Table 24 – Custom number formatting


Output
(Passed
Specifier Type Example Note
double
1500.42)
0 Zero placeholder {0:00.0000} 1500.4200 Pads with zeroes.
# Digit placeholder {0:(#).##} (1500).42
. Decimal point {0:0.0} 1500.4
Thousand Must be between two
, {0:0,0} 1,500
separator zeroes.
Comma adjacent to
,. Number scaling {0:0,.} 2 Period (.) scales by
1000.
Multiplies by 100,
% Percent {0:0%} 150042%
adds % sign.
Exponent Many exponent
e {0:00e+0} 15e+2
placeholder formats available.
; Group separator See below

An example of how to use some of these formats is shown:

Basic C# Programming | V1.0 August 2015 Page 226 of 276


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

namespace FormatExample2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("I can write numbers like this: " +
" string + number + number");
Console.WriteLine("Or I can write them like.." +
" {0} {1} {2}", 1, 2, 3);

// Right align, length 10.


Console.WriteLine("Number :{0, 10}", 1234);

// Left align, length 10.


Console.WriteLine("Number :{0, -10}" + ".", 1234);

// Format specifier.
Console.WriteLine("Number : {0, -12:E2}, {1, 10:N}", 5000000,
1000000);
/* A currency : This setting is affected by the regional settings
of your machine, and you may see $ instead of R. */
Console.WriteLine("Money : {0:c}", 1970);

// To Hex:
Console.WriteLine("Hex : {0:x}", 1970);

// Exponent:
Console.WriteLine("Exponent: {0:00e+0}", 27893.23464345);

// Phone number:
Console.WriteLine("Phone number: {0:(###)###-####}", 1123456789);

Console.ReadLine();
}
}
}

The result is:

I can write numbers like this: string + number + number


Or I can write them like... 1 2 3
Number : 1234
Number :1234
Number : 5.00E+006 , 1,000,000.00
Money : R 1,970.00
Hex : 7b2
Exponent: 28e+3
Phone number: (112)345-6789

Basic C# Programming | V1.0 August 2015 Page 227 of 276


3.4.4 Regular expressions

A regular expression is a pattern of text that is generally used to determine if a


string matches a specified format. For example, a regular expression could be
used to determine if the user has entered a valid email address or ID number.

The two main functions are to match and then replace a string. Match checks if
the pattern is found within the string and if it is, it returns an object which can
be tested. Replace changes the string according to a user-defined pattern. It
finds a certain pattern within a string and then replaces it with that specified
pattern.

Table 25 shows the syntax used to create regular expressions:

Table 25 – Regular expression syntax


Pattern code Matches
[] Used to indicate the start/finish of a term.
Placed before a term to negate it. (Used
to ensure that certain characters are not
^
in the string, i.e. [^a] will match anything
but a.)
[A-Za-z0-9] Alphanumeric characters
[A-Za-z0-9_] Alphanumeric characters plus ‘_’
[^\w] Non-word character
[A-Za-z] Alphabetic characters
[ \t] Space and tab
[\x00-\x1F\x7F] Control characters
[0-9] Digits
[^\d] Non-digit
[\x21-\x7E] Visible characters
[a-z] Lower case letters
[\x20-\x7E] Visible characters and spaces
[-!"#$%&'()*+,./:;<=>?@[\\\]_`{|}~] Punctuation characters
[ \t\r\n\v\f] Whitespace characters
[^\s] Non-whitespace character

[A-Z] Upper case letters


[A-Fa-f0-9] Hexadecimal digits
Indicates that the previous expression
*
must be matched zero or more times,
e.g.: [a-z]* will match any number of
alphabetical characters.

Basic C# Programming | V1.0 August 2015 Page 228 of 276


Indicates that the previous expression
must be matched one or more times,
+ e.g.: [a-z]+ will match any number of
alphabetical characters, so long as there
is at least one.
Indicates that the previous expression
? must be matched zero or one times, no
more than that.

The example below demonstrates how regular expressions can be used:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions; // Needed for Regular Expressions

namespace RegularExpressionsExample
{
class Program
{
static void Main(string[] args)
{
// Pattern for an email address.
string pattern = "[A-Za-z0-9]*@[A-Za-z0-9]*[.][A-Za-z0-9]*";

// Create an instance of the Regex class to check 'pattern'.


Regex re = new Regex(pattern);

// An array of strings to test.


string[] testStrings = { "abcdef", "12123123", "test@test.com" };

// Iterate through the array and test the strings.


for (int loop = 0; loop < testStrings.Length; loop++)
{
Console.Write("'" + testStrings[loop] + "' ");

// re.Match returns an object of the Match class.


// The Success property indicates whether or not a match was
// made.
if (re.Match(testStrings[loop]).Success)
{
Console.WriteLine(" matched the pattern!");
}
else
{
Console.WriteLine(" did not match the pattern.");
}
}
// Pause.
Console.ReadLine();
}
}
}

Basic C# Programming | V1.0 August 2015 Page 229 of 276


The result is:

'abcdef' did not match the pattern.


'12123123' did not match the pattern.
'test@test.com' matched the pattern!

Basic C# Programming | V1.0 August 2015 Page 230 of 276


3.4.5 Exercises
1. Briefly explain what the static method Concat() of the string
class does.

2. How is Compare() of the string class different from


CompareOrdinal()?

3. What does the Length property in the string class do?

4. Write a program that prompts the user to enter two string


values. Compare these string values and display them using
the console. Display a message for when they are equal,
when the first string value is bigger than the second string
value, and when the first string value is smaller than the
second string value.

5. Write a program that prompts the user to enter two string


values. These two string values have to be concatenated and
the result displayed on the console.

6. Write a program that prompts the user to enter two string


values. First display these string values on the console. Now
take these string values and copy string one to string two.
Now display these copied string values on the console.

7. Write a program that prompts the user to enter four different


sports. Read these values from the console and add them to
a string array. Create a separator that will come between
these values as if creating a list. First display all the values
using the console without the separator. Then display on the
console the last three sports including the separator.

Basic C# Programming | V1.0 August 2015 Page 231 of 276


3.4.6 Revision questions
1. The result of the Equals() method of the String class:
i. int
ii. char
iii. bolean
iv. string

Choose the most correct answer.


a. (iii) only.
b. (ii) only.
c. (ii) or (iii).
d. All of the given options.

2. Which one of the following pieces of code will compile


successfully? Assume sep and val have been initialised to the
appropriate values.
a. string result = String.Join(sep, val, 1, 2);
Console.WriteLine
("String.Join(sep, val, 1, 2) = '{0}'", result);
b. string result = Join(sep, val, 1, 2);
Console.WriteLine
("Join(sep, val, 1, 2) = '{0}'", result);
c. string result = String.Join(val, 1, 2, sep);
Console.WriteLine
("String.Join(val, 1, 2, sep) = '{0}', result);
d. string result = Join(val, sep, 1, 2);
Console.WriteLine
("Join(val, sep, 1, 2) = '{0}'", result);

3. Which of the following methods are not instance methods of


the String class?
i. Append()
ii. TrimEnd()
iii. GetEnumerator()
iv. EnsureCapacity()
v. Clone()

Choose the most correct answer.


a. (i), (ii) and (iii)
b. (ii), (iii) and (v)
c. (i) and (iv)
d. All of the options (i) to (v)

Basic C# Programming | V1.0 August 2015 Page 232 of 276


3.5 Collections

At the end of this section you will be able to understand:


 The ArrayList collection
 The BitArray collection
 The HashTable collection
 The Queue collection
 The SortedList collection
 The Stack collection

Collections can be used to store data. Most of the collections in the


System.Collections package are present in other languages, and they operate
similarly. The most commonly used collection types are explored in this
section.

3.5.1 The ArrayList Collection

An ArrayList functions very much like a standard array. However, unlike an


array, an ArrayList dynamically resizes to fit its contents.

Here are a few essential facts about the ArrayList collection:

 It is able to expand automatically as needed.


 The lower bound is always zero, i.e. like an array, it starts counting from
zero.
 It always has one dimension. However, it is possible to have an ArrayList
that stores other ArrayLists, which would mimic a multi-dimensional array.
 It provides methods that add, insert, or remove a range of elements.
 It is contained within the System.Collections namespace.

NOTE In this section, methods listed with(s) in front of the method name
are static methods.

Table 26 shows the methods used when working with an ArrayList:

Table 26 – ArrayList methods


Method name Description
Add Adds an object to the end of the ArrayList.
Adds the elements of an ICollection to the end of the
AddRange
ArrayList.
Overloaded. Uses a binary search algorithm to locate a
BinarySearch
specific element in the sorted ArrayList or a portion of it.
Clear Removes all elements from the ArrayList.

Basic C# Programming | V1.0 August 2015 Page 233 of 276


Clone Creates a shallow copy of the ArrayList.
Contains Determines whether an element is in the ArrayList.
Overloaded. Copies the ArrayList or a portion of it to a
CopyTo
one-dimensional array.
Overloaded. Returns an enumerator that can iterate
GetEnumerator
through the ArrayList.
Returns an ArrayList that represents a sub-set of the
GetRange
elements in the source ArrayList.
Overloaded. Returns the zero-based index of the first
IndexOf
occurrence of a value in the ArrayList or in a portion of it.
Inserts an element into the ArrayList at the specified
Insert
index.
Inserts the elements of a collection into the ArrayList at
InsertRange
the specified index.
Overloaded. Returns the zero-based index of the last
LastIndexOf
occurrence of a value in the ArrayList or in a portion of it.
(s) ReadOnly Overloaded. Returns a list wrapper that is read-only.
Removes the first occurrence of a specific object from the
Remove
ArrayList.
Removes the element at the specified index of the
RemoveAt
ArrayList.
RemoveRange Removes a range of elements from the ArrayList.
Returns an ArrayList whose elements are copies of the
(s) Repeat
specified value.
Overloaded. Reverses the order of the elements in the
Reverse
ArrayList or a portion of it.
Copies the elements of a collection over a range of
SetRange
elements in the ArrayList.
Overloaded. Sorts the elements in the ArrayList or a
Sort
portion of it.
Overloaded. Copies the elements of the ArrayList to a
ToArray
new array.
Sets the capacity to the actual number of elements in the
TrimToSize
ArrayList.

The example below uses the Add() method:

Basic C# Programming | V1.0 August 2015 Page 234 of 276


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; // Required for ArrayList

namespace ArrayListExample
{
class Program
{
static void Main(string[] args)
{
// Declare an ArrayList.
ArrayList al = new ArrayList();
// Add some random values of varying types.
al.Add("Hello");
al.Add(true);
al.Add(new Object());
al.Add(5);

// Display the values.


for (int loop = 0; loop < al.Count; loop++)
{
Console.WriteLine(al[loop]);
}

// Now to test the use of an ArrayList with one type of object.


Console.WriteLine("======================");
// Empty the ArrayList.
al.Clear();
// Add instances of a class.
al.Add(new Random(5));
al.Add(new Random(7));
al.Add(new Random(33));

// Use the ArrayList.


for (int loop = 0; loop < al.Count; loop++)
{
// First check that the object is of the correct type.
if (al[loop] is Random)
{
// Cast the returned object to the Random class
// then call it's Next() method.
Console.WriteLine(((Random)al[loop]).Next());
}
}
// Pause.
Console.ReadLine();
}
}
}

This is the result:

Hello
True
System.Object
5
======================
726643700
822959691
2075067574

Basic C# Programming | V1.0 August 2015 Page 235 of 276


3.5.2 The BitArray Collection

The BitArray class can be used to store bits (a bit being either a 1 or a 0) in an
array-like structure. Each element can be set to true (1) or false (0). In many
ways, it is like an array of bool variables. Table 27 shows the methods used
when working with a BitArray.

Table 27 – BitArray methods


Method name Description
Performs the bitwise AND operation on the elements
And in the current BitArray against the corresponding
elements in the specified BitArray.
Copies the entire BitArray to a compatible one-
CopyTo dimensional array, starting at the specified index of
the target array.
Gets the value of the bit at a specific position in the
Get
BitArray.
Returns an enumerator that can iterate through the
GetEnumerator
BitArray.
Inverts all the bit values in the current BitArray, so
Not that elements set to true are changed to false, and
elements set to false are changed to true.
Performs the bitwise OR operation on the elements in
Or the current BitArray against the corresponding
elements in the specified BitArray.
Sets the bit at a specific position in the BitArray to the
Set
specified value.
SetAll Sets all bits in the BitArray to the specified value.
ToString (inherited
Returns a String that represents the current Object.
from Object class)
Performs the bitwise eXclusive OR operation on the
Xor elements in the current BitArray against the
corresponding elements in the specified BitArray.

The example below uses the And method:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; // Required for BitArray

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

Basic C# Programming | V1.0 August 2015 Page 236 of 276


{
// Create a BitArray with 8 elements each having the default
//value
// of 'true'.
BitArray ba = new BitArray(8, true);

// Display the array elements.


for (int loop = 0; loop < ba.Length; loop++)
{
Console.WriteLine(ba[loop]);
}

Console.WriteLine();

// Perform a binary operation (AND returns true if both are


//true).
ba.And(new BitArray(8, false));

// Display the array elements.


for (int loop = 0; loop < ba.Length; loop++)
{
Console.WriteLine(ba[loop]);
}

Console.ReadLine();
}
}
}

The result is :

True
True
True
True
True
True
True
True

False
False
False
False
False
False
False
False

3.5.3 The HashTable collection

Instead of using an index, a HashTable stores values by key. To add, retrieve,


or modify values a key must be specified. Each element in a HashTable is a
Key-Value Pair. These are represented in C# by KeyValuePair objects. Note
that while values in a HashTable can be null or duplicate, the keys cannot be,
as every key must be unique.

Table 28 shows the methods used when working with a HashTable.

Basic C# Programming | V1.0 August 2015 Page 237 of 276


Table 28 – HashTable methods
Method name Description
Adds an element with the specified key and value into
Add
the HashTable.
Clear Removes all elements from the HashTable.
Clone Creates a shallow copy of the HashTable.
Determines whether the HashTable contains a specific
Contains
key.
Determines whether the HashTable contains a specific
ContainsKey
key.
Determines whether the HashTable contains a specific
ContainsValue
value.
Copies the HashTable elements to a one-dimensional
CopyTo
Array instance at the specified index.
Returns an IDictionaryEnumerator that can iterate
GetEnumeration
through the HashTable.
Removes the element with the specified key from the
Remove
HashTable.
ToString (inherited
Returns a String that represents the current Object.
from Object class)

The example below uses the Add() method:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; // Required for HashTable

namespace HashTableExample
{
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();

ht.Add("Pick'nPay", "765-4321");
ht.Add("Spar", "678-9101");
ht.Add("Checkers", "123-4567");

Console.WriteLine("Checkers: {0}", ht["Checkers"]);


Console.ReadLine();
}
}
}

The result is:

Checkers: 678-9101

Basic C# Programming | V1.0 August 2015 Page 238 of 276


3.5.4 The Queue collection

A Queue is a First In-First Out (FIFO) collection. It is just like standing in a line
when going to the bank. The first person in the line should be the first person
to get service. A Queue is a good collection to use when a limited resource is
being managed. For example, a programmer may want to send messages to a
resource. This resource can only handle one message at a time. A message
queue could be used to store messages in the order they are received. Table
29 shows the methods used when working with the Queue class.

Table 29 – Queue methods


Method name Description
Clear Removes all objects from the Queue.
Clone Creates a shallow copy of the Queue.
Contains Determines whether an element is in the Queue.
Copies the Queue elements to an existing one-
CopyTo
dimensional Array, starting at the specified array index.
Removes and returns the object at the beginning of the
Dequeue
Queue collection.
Enqueue Adds an object to the end of the Queue.
Returns an enumerator that can iterate through the
GetEnumerator
Queue.
Returns the object at the beginning of the Queue
Peek
without removing it.
ToArray Copies the Queue elements to a new array.
ToString (inherited
Returns a String that represents the current Object.
from Object class)
Sets the capacity to the actual number of elements in
TrimToSize
the Queue.

The example below uses the Enqueue() and Dequeue() methods:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; // Required for Queue

namespace QueueExample
{
class Program
{
static void Main(string[] args)
{
Queue q = new Queue();

q.Enqueue("message 1");
q.Enqueue("message 2");

Basic C# Programming | V1.0 August 2015 Page 239 of 276


q.Enqueue("message 3");

Console.WriteLine("First message: {0}", q.Dequeue());


Console.WriteLine("Next message: {0}", q.Dequeue());
Console.ReadLine();
}
}
}

The result is:

First message: message 1


Next message: message 2

3.5.5 The SortedList collection

The SortedList collection is much like a HashTable, but it also automatically


sorts its contents by their keys. The values are accessible by using either keys
or indexes. Table 30 shows the methods used when working with a SortedList.

Table 30 – SortedList methods


Method name Description
Adds an element with the specified key and value
Add
to the SortedList.
Clear Removes all elements from the SortedList.
Clone Creates a shallow copy of the SortedList.
Determines whether the SortedList contains a
Contains
specific key.
Determines whether the SortedList contains a
ContainsKey
specific key.
Determines whether the SortedList contains a
ContainsValue
specific value.
Copies the SortedList elements to a one-
CopyTo
dimensional Array instance at the specified index.
Gets the value at the specified index of the
GetByIndex
SortedList.
Returns an IDictionaryEnumerator that can iterate
GetEnumerator
through the SortedList.
Gets the key at the specified index of the
GetKey
SortedList.
GetKeyList Gets the keys in the SortedList.
GetValueList Gets the values in the SortedList.
Returns the zero-based index of the specified key
IndexOfKey
in the SortedList.
Returns the zero-based index of the first
IndexOfValue
occurrence of the specified value in the SortedList.

Basic C# Programming | V1.0 August 2015 Page 240 of 276


Removes the element with the specified key from
Remove
SortedList.
Removes the element at the specified index of
RemoveAt
SortedList.
Replaces the value at a specific index in the
SetByIndex
SortedList.
ToString (inherited from Returns a String that represents the current
Object class) Object.
Sets the capacity to the actual number of elements
TrimToSize
in the SortedList.

The example below shows how values can be stored and retrieved from a
SortedList:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; //Required for ArrayList Collections

namespace SortedListExample
{
class Program
{
static void Main(string[] args)
{
SortedList sl = new SortedList();

sl.Add("Pick'nPay", "765-4321");
sl.Add("Spar", "678-9101");
sl.Add("Checkers", "123-4567");

for (int i = 0; i < sl.Count; i++)


{
Console.WriteLine("{0}: {1}", sl.GetKey(i),
sl.GetByIndex(i));
}

// Access a value by its key.


Console.WriteLine(sl["Spar"]);
Console.ReadLine();
}
}
}

The result is:

Pick'nPay: 765-4321
Spar: 678-9101
Checkers: 123-4567
678-9101

Basic C# Programming | V1.0 August 2015 Page 241 of 276


3.5.6 The Stack collection

A Stack is a LIFO collection. Think of a stack of coins on a desk. If a coin is


added, it is placed on top, and it is also the first coin that would be taken off
the stack. The two primary methods of Stack are to add (Push()) or to remove
(Pop()). There is the Peek() method, which is a very similar to that available in
the Queue collection.

The significant methods of the Stack class are shown in Table 31:

Table 31 – Stack methods


Method name Description
Clear Removes all objects from the Stack.
Clone Creates a shallow copy of the Stack.
Contains Determines whether an element is in the Stack.
Copies the Stack to an existing one-dimensional Array,
CopyTo
starting at the specified array index.
GetEnumerator Returns an IEnumerator for the Stack.
Returns the object at the top of the Stack without removing
Peek
it.
Pop Removes and returns the object at the top of the Stack.
Push Inserts an object at the top of the Stack.
ToArray Copies the Stack to a new array.
ToString
(inherited from Returns a String that represents the current Object.
Object class)

The example below uses the Push and Pop methods:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; // Required for ArrayList Collections

namespace StackExample
{
class Program
{
static void Main(string[] args)
{
// Use the Stack collection.
Stack st = new Stack();

st.Push("animal 1");
st.Push("animal 2");
st.Push("animal 3");
st.Push("animal 4");

Console.WriteLine("Top of Stack: {0}", st.Pop());

Basic C# Programming | V1.0 August 2015 Page 242 of 276


Console.WriteLine("Next in Line: {0}", st.Pop());
Console.ReadLine();
}
}
}

The result is:

Top of Stack: animal 4


Next in Line: animal 3

3.5.7 Collection interfaces

Collection classes have many methods in common. This makes them more
predictable and easier to use in applications because they are consistent with
each other. This consistency is enforced by the interfaces they implement. The
standard interfaces which can be implemented when creating custom collection
types are shown in Table 32.

Table 32 – Collection interfaces


Name Description
Enumerator, size and synchronisation for all
ICollection
collections.
IComparer Compares two objects.
IDictionary Key/value pair collection.
IDictionaryEnumerator Enumerator for IDictionary
Exposes an enumerator which can be used to iterate
IEnumerable
through a collection.
IHashCodeProvider Obtains a hash code.
IList Indexed collection.

The interfaces the collection implements are dependent upon the type of the
collection. For example, a Hashtable implements IDictionary, stating that it
implements key/value semantics.

Basic C# Programming | V1.0 August 2015 Page 243 of 276


3.5.8 Exercises
1. Which principle does the Queue collection make use of?

2. What makes the Stack collection different from the


other collections explained in this unit?

3. What are the two primary methods of the Stack


collection?

4. If you had to copy a collection to a pre-existing one


dimension array, which method will you make use of?

5. Write a program that allows the user to enter as many


names as he or she wants to. Store these values into
an ArrayList collection. Display all the values in the
ArrayList using the console.

6. Write a program that allows the user to enter his or her


name and date of birth. Read these values from the
console and add them to a SortedList collection as
key/value pairs. Display these values to the console
with an appropriate message.

3.5.9 Revision questions


1. True/False: The Queue collection uses a Last In-First
Out principle.

2. Which of the following collections provide the CopyTo


method?
i. Stack
ii. SortedList
iii. Queue
iv. Hashtable
v. BitArray
vi. ArrayList

Choose the most correct answer.


a. All the options (i) to (vi)
b. (i), (ii) and (iv)
c. (i), (ii), (iii) and (v)
d. (i), (ii), (iii), (iv) and (vi)

3. True/False: Both Hashtable and ArrayList use key-value


pairs.

4. Which of the following methods apply to the Stack


collection?
i. Contains
ii. Dequeue

Basic C# Programming | V1.0 August 2015 Page 244 of 276


iii. Enqueue
iv. Pop
v. Push

Choose the most correct answer.


a. All of the options (i) to (v).
b. (i), (ii), (iii) and (v)
c. (i), (iv) and (v)
d. (i), (ii) and (iii)

Basic C# Programming | V1.0 August 2015 Page 245 of 276


3.6 Test Your Knowledge (Unit 3 – Self-Test)

The questions in this section are similar to those asked in the


examination. Try answering these questions and then check the
answers with the lecturer. The questions are taken from the
study guide and textbook. The questions comprise theory and
application questions which will be in multiple choice, multiple
response, true/false and selection formats. Allow about 20
minutes for all the questions.

True/False

1. True/False: The following line of code creates a new ColorDialog.

colorDialog cd = new System.Dialog.ColorDialog();

2. True/False: TextChanged is an event of the TextBox control.

3. True/False: The following line of code is an acceptable method of


displaying a MessageBox.

DialogResult result = MessageBox.Show("Text", "Title",


MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

4. True/False: C# variables are strongly typed.

Multiple choice

1. What is the function of the following line of code?

result = string.Compare(str2, str1, true);

a. Compares str1 with str2.


b. Compares str2, str1 and the true value.
c. Compares str2 with str1 and the true value to ensure that the
whole string is compared.
d. Compares str2 with str1 without being case-sensitive.

2. Which one of the following is not a format specifier?


a. n
b. X
c. #
d. ::

Basic C# Programming | V1.0 August 2015 Page 246 of 276


3. What data would the following regular expression match?

string pat = "[A-Za-z0-9]*@[A-Za-z0-9]*[.][A-Za-z0-9]*";

a. pat tests if the ‘@’ symbol is present.


b. pat tests if alphabetical letters and numbers are present.
c. pat defines the pattern for an email address.
d. pat defines a pattern for a street address.

4. Which of the following is not a method of the ArrayList collection?


a. AddRange
b. CopyTo
c. Repeat
d. Dispose

Multiple response

1. Which three of the following are common Form methods?


a. Display
b. Hide
c. Visible
d. Close
e. Open
f. Show

2. Which of the following controls are used to group other controls?


i. Button
ii. Groupbox
iii. Listbox
iv. Panel
v. Radiobutton

Choose the most correct answer:


a. All of the options (i) to (v).
b. ii and iv.
c. None of the options.
d. i, iii and iv.

3. Which three of the following types are basic C# data types?


a. double
b. short
c. float
d. Panel
e. longer
f. shorter

Basic C# Programming | V1.0 August 2015 Page 247 of 276


4. Which three of the following compound condition operators are not
valid?
a. II
b. !!
c. &
d. &&
e. &!
f. =*

5. Which three of the following image formats are not supported by .NET?
a. .jpg
b. .cs
c. .bmp
d. .ico
e. .ic
f. .bitmap

Basic C# Programming | V1.0 August 2015 Page 248 of 276


3.7 Projects

At the end of this section you will:


 Have completed one of the two projects listed below. Ask
the instructor which project to complete.
 Be able to explain and implement all the concepts
presented in the project you have done.

NOTE
When planning and creating the project, remember to follow the
guidelines as set out in the introduction to this guide.

3.7.1 Project 1 – Blackjack

Using Visual Studio, create a Blackjack game.

Blackjack is a popular card game where the aim of the game is to get a higher
score than the dealer without exceeding a value of 21.

A hand of Blackjack works as follows:


 When a new game is started, the dealer deals two cards to the player,
and two to him- or herself.
o The player’s cards are always facing up.
o The dealer has one card face up, and the second face down.
 The score of the player’s and dealer’s hands is worked out. The scoring is
as follows:
o 2–9 all have the value indicated on the card.
o 10, Jack, Queen and King all have a value of ten.
o An Ace counts as 11, unless drawing the card would bust the
player (i.e. take his/her score over 21), in which case it counts as
one. This is both before and after the Ace is dealt.
 If, at this point, the player has a score of 21, then he or she has a
Blackjack. A Blackjack will beat anything the dealer has unless, of
course, the dealer also has a Blackjack – in which case the hand is a tie.
 If the player has a score of less than 21, then there is the option to
either hit or stand.
o If the player opts to hit, then another card is dealt and the total is
recalculated.
o If the player opts to stand, then his/her score will stop at the
current total.
 Once the player has finished the hand (either by standing, going bust, or
getting a Blackjack), it is the dealer’s turn to play. The dealer must
reveal the card which was face down. The dealer, like the player, can opt
to hit or stand. However, the dealer has strict rules which must be
followed:

Basic C# Programming | V1.0 August 2015 Page 249 of 276


o If the total is greater than or equal to 17, then the dealer must
stand.
o If the total is below 17, then the dealer must hit.
 Once the dealer has finished the hand (either by standing, going bust, or
getting a Blackjack), the dealer’s total is compared with the player’s
total.
o If the player goes bust, then the player loses, even if the dealer
also goes bust.
o If the player has a score of 21 or less and the dealer goes bust,
then the player wins.
o If both the player and the dealer have scores of 21 or less, then
the numerical value is compared. The highest value wins.
o If both the player and the dealer have the same score, then the
hand is a tie.

Images of cards will be provided.

 Programming
o Commands to start a new game or quit the program must be
represented by command buttons on the main form.
o Use the card images provided to represent the current hand.
Remember that the dealer only shows one card until the player’s
turn has finished.
o Keep track of a player’s wins, losses and ties. This information
should be displayed on a scoreboard.
o The cards must be dealt randomly from the deck of 52 cards.
HINT: give each of the cards a number from 0 – 51 and store
information about each of them (i.e. which image to use, scoring
value).
 The Ace is a special case; store it with a value of 0. When an
Ace is dealt, determine at the time whether it should have a
value of 11 or a value of 1.
 Ensure that the same card is not dealt twice in one hand. A
good way to do this is to store the cards dealt to the player
and the dealer in separate collections, and then check any
card being dealt against those collections. The Contains
method can be useful here.
o Commands to either Hit or Stay must be present. These should be
disabled when not in use.
o A Deal command, which will be used to start a new hand, must be
present. This button should be disabled when a hand is being
played, and then enabled once the hand is over.
o The current total of the player’s cards must be displayed at all
times.
o Once a hand is complete, the result must be displayed to the user,
whether it is a win, a loss, or a tie.

Basic C# Programming | V1.0 August 2015 Page 250 of 276


Project Evaluation – C# (CSPAC) Unit 3 – Project 1 –
Blackjack

Student: Instructor:
Date Submitted: Date Marked:

Achievement: % Possible Achieved


Source code documentation
Comments (author, date, purpose) for each class 3
Comments for individual code segments 5
Correct indentation of code 2
Subtotal: 10
Program content
New game starts correctly as specified 5
Cards displayed on screen as specified 6
Options to hit or stand are available and work correctly 6
Hit and stay buttons are disabled and re-enabled as specified 5
Scoring (i.e. Blackjack, bust, tie) works correctly 6
Facility to quit works correctly 2
Subtotal: 30
Source code design
The Ace has a value of either 1 or 11 according to specifications 3
Cards are dealt randomly and according to specifications 6
Dealer’s initial cards: One face down, one visible 3
Cards one – King all have the correct values (1 – 10) 4
Player’s total is displayed (and updated) correctly 4
Dealer plays correctly (i.e. hit till 17, then stay) 4
General code efficiency 6
Subtotal: 30
Source code content
Descriptive naming of variables 4
All variables declared as the correct type 4
All control names changed from default 4
Descriptive naming of controls 4
Try/catch blocks used to catch exceptions if necessary 4
Subtotal: 20
User interface
Eye-pleasing form design – all controls neatly lined up, no garish
2
colour schemes
Appropriate controls used to present information 2
Controls display information completely (no cutting off) 2
Command buttons are present to start a game or quit the application 2
Player statistics are displayed appropriately 2
Subtotal: 10

Basic C# Programming | V1.0 August 2015 Page 251 of 276


Penalties
Program does not compile 5
Program causes unhandled error during execution or user input 5
Program documentation not handed in 10
Source code listing not handed in 5
Program documentation does not adequately describe program
5
operation

General comments

Total: 100

Basic C# Programming | V1.0 August 2015 Page 252 of 276


3.7.2 Project 2 – Editor

Using Visual Studio, create an editor window that will function in a similar
fashion to Microsoft Word.

The editor window is a platform on which text files can be opened and edited
as the user pleases.

NOTE A RichTextBox control is used instead of a normal TextBox control.


Although the RichTextBox control was not explained in the study
guide, it has much the same functionality as a normal TextBox
control. It is, however, more flexible and can be used to read selected
text.

The editor works as follows:


 The user can create a new document to work on or choose to open an
existing text document.
 The user can select text in the document and choose to make it Bold,
Italic, or Underline.
 There is functionality to change the colour of the text and the colour of
the background.
 The user must be given the option of changing the font and size of the
text.
 There must be functionality to add pre-set words to the document.
 The user must be able to set highlighted text to upper or lower case.
 The user must be able to add any of 15 emoticons.
 When the new document is selected again, the document text must be
cleared and the upper and lower case options must be deselected.

Images will be provided. You may use these images or create your own.

 Programming:
o Commands to create a new text document, to open an existing
document, exit the application, or display information about the
application must be represented by a menu item at the top of the
editor.
o There must be functionality to create a new document or open an
existing one in the form of button controls.
o Use an OpenFileDialog to open existing text documents only.
o All text in the RichTextBox control will be lost when opening an
existing text document. Inform the user of this by using a
MessageBox.
o Use the images provided (or those that you have created) to
illustrate each button control’s purpose.
o A further five button controls must be added to accommodate
changes that may occur to the document’s text. These will be
changes such as background colour, font colour, bold, italic and
underline.
o Use a ColorDialog to change the background and font colour.

Basic C# Programming | V1.0 August 2015 Page 253 of 276


o There must be a check in place to check that there is text in the
RichTextBox control before changing the font to bold, italic, or
underline.
o If there is no text in the RichTextBox control when the font colour
button is pressed, display a message informing the user of this.
o When only certain text is highlighted, change only that text’s font
colour. When no text is selected, change the font colour of all the
text in the RichTextBox control.
o The images provided (or those that you have created) must be
used to demonstrate the button control’s purpose.
o Functionality to change the text’s font and size can be represented
by a button control. Use a FontDialog in order to do this. If no text
is selected, change all the text. If some text is selected, change
only that text.
o A ComboBox control must be added to list words that could be
added to the text document.
o Use an ArrayList collection to add words to the ComboBox control.
The user can then select a word from the list to be appended to the
document text.
o The user must be able to either change all of the text to upper or
lower case, or change only selected text. Remember to add
functionality that will check whether or not the RichTextBox control
contains text.
o Add 15 emoticons (images are provided) in the form of button
controls. These emoticons must be appended to the RichTextBox
control when pressed.
o Remove the text from the button controls and add the image.
o Add ToolTips to the appropriate controls on the editor so that the
user can point the mouse cursor over the control and receive
information on what the control will do when pressed.

Appending an image to a RichTextBox control is much the same as


appending an image to a normal TextBox control. Try to use the
HINT
Clipboard and Paste functionality together with the functionality used
in the normal TextBox control.

Basic C# Programming | V1.0 August 2015 Page 254 of 276


Project Evaluation – C# (CSPAC) Unit 3 – Project 2 – Editor

Student: Instructor:
Date Submitted: Date Marked:

Achievement: % Possible Achieved


Source code documentation
Comments (author, date, purpose) for each class 3
Comments for individual code segments. 5
Correct indentation of code 2
Subtotal: 10
Program content
Menu – can create new document, open existing document, exit the
4
application, or display information
New document created correctly as specified (button and menu
4
control)
Functionality to change font to bold, italic, or underline displayed as
3
button controls
Functionality to change text to upper or lower case shown as
2
RadioButton controls
ArrayList collection used to add words to the ComboBox control 2
Facility to exit works correctly 2
Subtotal: 17
Source code design
Existing text document opened and added to RichTextBox control as
6
specified
Functionality to change background colour and font colour correct as
6
specified
Functionality to change font and size using a FontDialog as specified 6
Font is changed to upper or lower case as specified 4
Check whether or not there is text in the RichTextBox control before
6
proceeding
Images added to the Resource folder in the project 2
Emoticon added to the text as specified 4
Items from the ComboBox added to the RichTextBox control 3
General code efficiency 6
Subtotal: 43
Source code content
Descriptive naming of variables. 4
All variables declared as the correct type. 4
All control names changed from defaults. 4
Descriptive naming of controls. 4
Try/catch blocks used to catch exceptions if necessary 4
Subtotal: 20

Basic C# Programming | V1.0 August 2015 Page 255 of 276


User interface
Eye-pleasing form design – all controls neatly lined up, no garish
2
colour schemes.
Appropriate controls used to present information. 2
Controls display information completely (no cutting off). 2
Command buttons are present to create a new document or open an
2
existing one.
The user is informed that the text will be lost if an existing document
2
is opened.
Subtotal: 10
Penalties
Program does not compile. 5
Program causes unhandled error during execution or user input. 5
Program documentation not handed in. 10
Source code listing not handed in. 5
Program documentation does not adequately describe program
5
operation.

General comments

Total: 100

Basic C# Programming | V1.0 August 2015 Page 256 of 276


Language Comparison
C#, VB.NET and Java
Based on the work of Frank McCown, available online at: http://www.harding.edu/fmccown/resources.html
This work is licensed under a Creative Commons licence, available online at: http://creativecommons.org/licenses/by-sa/2.0/

C# VB.NET (v2) Java (v5)


PROGRAM STRUCTURE
using System; Imports System package hello;

namespace Hello Namespace Hello public class HelloWorld {


{ Class HelloWorld public static void main(String[] args) {
public class HelloWorld Overloads Shared Sub Main(ByVal args() _ String name = "Java";
{ As String)
public static void Main(string[] args) Dim name As String = "VB.NET" // See if an argument was passed from the
{ // command line
string name = "C#"; ' See if an argument was passed from the if (args.length == 1)
' command line name = args[0];
// See if an argument was passed from the If args.Length = 1 Then name = args(0) System.out.println("Hello, " + name +
// command line "!");
if (args.Length == 1) Console.WriteLine("Hello, " & name & "!") }
name = args[0]; End Sub }
End Class
Console.WriteLine("Hello, " + name + End Namespace
"!");
}
}
}
COMMENTS
// Single line Single line only // Single line
''' <summary>XML comments</summary> /* Multiple
line */
/* Multiple
/** Javadoc documentation comments */

line */

/// <summary>XML comments on single line</summary>


/** <summary>XML comments on multiple

lines</summary> */

Basic C# Programming | V1.0 August 2015 Page 257 of 276


C# VB.NET (v2) Java (v5)
DATA TYPES
// Value Types ‘ Value Types // Primitive Types
bool Boolean boolean
byte, sbyte Byte, SByte byte
char Char char
short, ushort, int, uint, long, ulong Short, UShort, Integer, UInteger, Long, ULong short, int, long
float, double, decimal Double, Decimal float, double
structures, enumerations structures, enumerations
// Reference Types ‘ Reference Types // Reference Types
object // superclass of all other classe) Object ‘ superclass of all other classes Object // superclass of all other classes
string String String
arrays, classes, interfaces, delegates arrays, classes, interfaces, delegates arrays, classes, interfaces
// Conversions ‘ Conversions // Conversions
// int to string ‘ Integer to String // int to String
int x = 123; Dim x As Integer = 123 int x = 123;
String y = x.ToString(); // y is "123" Dim y As String = x.ToString() ‘ y is "123" String y = Integer.toString(x); // y is "123"
// string to int ‘ string to Integer // String to int
y = "456"; y = "456" y = "456";
x = Int32.Parse(y); x = Int32.Parse(y) x = Integer.parseInt(y); // x is 456
// double to int ‘ Double to Integer // double to int
double z = 3.5; Dim z As Double = 3.5 double z = 3.5;
x = (int) z; // x is 3 (truncates decimal) x = CType(z, Integer) ‘ x is 3 (truncates decimal) x = (int) z; // x is 3 (truncates decimal)

CONSTANTS
const double PI = 3.14; Const MAX_STUDENTS As Integer = 25 // May be initialized in a constructor
// Can be set to a const or a variable. May be ' Can set to a const or var; may be initialized in final double PI = 3.14;
// initialized in a constructor. ‘ a constructor
readonly int MAX_HEIGHT = 9; ReadOnly MIN_DIAMETER As Single = 4.93

Basic C# Programming | V1.0 August 2015 Page 258 of 276


C# VBNET (v2) Java (v5)
ENUMERATIONS
enum Action {Start, Stop, Rewind, Forward}; Enum Action enum Action {Start, Stop, Rewind, Forward};
enum Status {Flunk = 50, Pass = 70, Excel = 90}; Start // Special type of class
// No equivalent [Stop] ' Stop is a reserved word enum Status {
Rewind Flunk(50), Pass(70), Excel(90);
Action a = Action.Stop; Forward private final int value;
if (a != Action.Start) End Enum Status(int value) { this.value = value; }
{ public int value() { return value; }};
Console.WriteLine(a); // Prints "Stop" Enum Status
} Flunk = 50 Action a = Action.Stop;
Status s = Status.Pass; Pass = 70 if (a != Action.Start)
Console.WriteLine((int) s); // Prints "70" Excel = 90 System.out.println(a); // Prints "Stop"
End Enum
Status s = Status.Pass;
Dim a As Action = Action.Stop System.out.println(s.value()); // Prints "70"
If a <> Action.Start Then _
' Prints "Stop is 1"
Console.WriteLine(a.ToString & " is " & a)
'Prints 70
Console.WriteLine(Status.Pass)
' Prints Pass
Console.WriteLine(Status.Pass.ToString())
OPERATORS
// Comparison ‘ Comparison // Comparison
== < > <= >= != = < > <= >= <> == < > <= >= !=
// Arithmetic ‘ Arithmetic // Arithmetic
+ – * / + – * / + – * /
% // (mod) Mod % // (mod)
/ // (integer division if both operands are ints) \ ‘ (Integer division) /// (integer division if both operands are ints)
Math.Pow(x, y) ^ ‘ (raise to a power) Math.Pow(x, y)
// Assignment ‘ Assignment // Assignment
= += -= *= /= %= &= |= ^= <<= >>= ++ - = += -= *= /= \= ^= <<= >>= &= = += -
- ‘ Bitwise = *= /= %= &= |= ^= <<= >>= >>>= ++ --
// Bitwise And Or Xor Not << >> // Bitwise
& | ^ ~ << >> ‘ Logical & | ^ ~ << >> >>>
// Logical AndAlso OrElse And Or Xor Not // Logical
&& || & | ^ ! ‘ Note: AndAlso and OrElse perform short-circuit && || & | ^ !
Note: && and || perform short-circuit logical ‘ logical evaluations Note: && and || perform short-circuit logical
evaluations ‘ String Concatenation evaluations
// String Concatenation & // String Concatenation
+ +

Basic C# Programming | V1.0 August 2015 Page 259 of 276


C# VB.NET (v2) Java (v5)
CHOICES
greeting = age < 20 ? "What's up?" : "Hello"; greeting = IIf(age < 20, "What's up?", "Hello") greeting = age < 20 ? "What's up?" : "Hello";
if (x < y) If(x < y) Then if (x < y) {
{ Console.WriteLine(“greater”) System.out.println("greater");
Console.WriteLine("greater"); EndIf }
} if (x != 100) {
if (x != 100) If(Not(X = 100)) Then x *= 5;
{ X = X * 2 y *= 2;
x *= 5; y = Y * 2 }
y *= 2; Else else
} Z = Z * 6 z *= 6;
else EndIf int selection = 2;
z *= 6; // Must be byte, short, int, char, or enum
Dim colour As String = “red” switch (selection) {
string colour = "red"; Select (colour) // Falls through to next case if no break
switch (colour) Case “red”: case 1: x++;
{ r = r + 1 case 2: y++; break;
// break is mandatory; no fall-through Case “green”: case 3: z++; break;
case "red": r++; break; g = g + 1 default: other++;
case "blue": b++; break; Case Else: }
case "green": g++; break; other = other + 1
// break necessary on default End Select
default: other++; break;
}

ARRAYS
int[] nums = {1, 2, 3}; Dim nums As Integer() = {1, 2, 3} int nums[] = {1, 2, 3}; or int[] nums = {1,
for (int i = 0; i < nums.Length; i++) Dim i As Integer 2, 3};
Console.WriteLine(nums[i]); For i = 0 To Nums.Length for (int i = 0; i < nums.length; i++)
Console.WriteLine(nums[i]) System.out.println(nums[i]);
string[] names = new string[5]; Next String names[] = new String[5];
names[0] = "David"; Dim names(5) As String names[0] = "David";
names(0) = "David" float twoD[][] = new float[rows][cols];
float[,] twoD = new float[rows, cols]; Dim twoD(rows-1, cols-1) As Single twoD[2][0] = 4.5;
twoD[2,0] = 4.5f; twoD(2, 0) = 4.5 int[][] jagged = new int[5][];
int[][] jagged = new int[3][] { Dim jagged()() As Integer = { _ jagged[0] = new int[5];
new int[5], new int[2], new int[3] }; New Integer(4) {}, New Integer(1) {}, _ jagged[1] = new int[2];
jagged[0][4] = 5; New Integer(2) {} } jagged[2] = new int[3];
jagged(0)(4) = 5 jagged[0][4] = 5;

Basic C# Programming | V1.0 August 2015 Page 260 of 276


C# VB.NET (v2) Java (v5)
LOOPS
while (i < 10) While (i < 10) while (i < 10)
{ i = i + 1 {
i++; End While i++;
} }
For i = 2 To 10 Step 2
for (i = 2; i <= 10; i += 2) Console.WriteLine(i) for (i = 2; i <= 10; i += 2)
{ Next {
Console.WriteLine(i); Console.WriteLine(i);
} Do While(i < 10) }
i = i + 1
do Loop do
{ {
i++; i++;
} ‘ foreach can be used to iterate through any }
while (i < 10); ‘ collection while (i < 10);
For Each i As Integer in numArray
sum = sum + i
// foreach can be used to iterate through any Next // foreach can be used to iterate through any
collection collection
foreach (int i in numArray) Dim list As ArrayList = new ArrayList() foreach (int i in numArray)
{ list.Add(10) {
sum += i; list.Add("Bisons") sum += i;
} list.Add(2.3) }

using System.Collections;. For Each o As Object In list using System.Collections;


ArrayList list = new ArrayList(); Console.WriteLine(o) ArrayList list = new ArrayList();
list.Add(10); Next list.Add(10);
list.Add("Bisons"); list.Add("Bisons");
list.Add(2.3); list.Add(2.3);

foreach (Object o in list) foreach (Object o in list)


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

Basic C# Programming | V1.0 August 2015 Page 261 of 276


C# VB.NET (v2) Java (v5)
FUNCTIONS
// Return single value ‘ Return single value // Return single value
int Add(int x, int y) Function Add(ByVal x As Integer, _ int Add(int x, int y) {
{ ByVal y As Integer) As Integer return x + y;
return x + y; return x + y }
} End Function int sum = Add(2, 3);
int sum = Add(2, 3); Dim sum As Integer = Add(2, 3)
// Return no value
// Return no value ‘ Return no value void PrintSum(int x, int y) {
void PrintSum(int x, int y) Sub PrintSum(ByVal x As Integer, ByVal y As Integer) System.out.println(x + y);
{ Console.WriteLine(x + y) }
Console.WriteLine(x + y); End Function PrintSum(2, 3);
}
PrintSum(2, 3); PrintSum(2, 3)

EXCEPTION HANDLING
Exception up = new Exception("Something is really Throw an exception // Must be in a method that is declared to throw
wrong."); Dim ex As New _ // this exception
throw ex; Exception("Something is really wrong.") Exception ex = new Exception("Something is really
Throw ex wrong.");
try ' Catch an exception throw ex;
{ Try try {
y = 0; y = 0 y = 0;
x = 10 / y; x = 10 / y x = 10 / y;
} ' Argument and When is optional } catch (Exception ex) {
catch (Exception ex) // Variable "ex" is Catch ex As Exception When y = 0 System.out.println(ex.getMessage());
{ // optional } finally {
Console.WriteLine(ex.Message); Console.WriteLine(ex.Message) // Code that always gets executed
} Finally }
finally Beep()
{ End Try
// Code that always gets executed
}

Basic C# Programming | V1.0 August 2015 Page 262 of 276


C# VB.NET (v2) Java (v5)
STRINGS
// String concatenation ‘ String concatenation // String concatenation
string school = "Harding "; Dim school As String = "Harding " String school = "Harding ";

// school is "Harding University" ‘ school is "Harding University" // school is "Harding University"


school = school + "University"; school = school & "University" school = school + "University";

// String comparison ’ String comparison // String comparison


string mascot = "Bisons"; string mascot = "Bisons"; String mascot = "Bisons";
if (mascot == "Bisons") // true If (mascot = "Bisons") Then ‘ true if (mascot == "Bisons") // incorrect method
if (mascot.Equals("Bisons")) // true If (mascot.Equals("Bisons")) Then ‘ true if (mascot.equals("Bisons")) // true
if (mascot.ToUpper().Equals("BISONS")) // true If (mascot.ToUpper().Equals("BISONS")) Then‘ true if (mascot.equalsIgnoreCase("BISONS")) // true
if (mascot.CompareTo("Bisons") == 0) // true If (mascot.CompareTo("Bisons") = 0) Then ‘ true if (mascot.compareTo("Bisons") == 0) // true

// Prints "son" ‘ Prints "son" // Prints "son"


Console.WriteLine(mascot.Substring(2, 3)); Console.WriteLine(mascot.Substring(2, 3)) System.out.println(mascot.substring(2, 5));

NAMESPACES
namespace CTIGroup.CTI.HO Namespace CTIGroup.Cti.HO package CTIGroup.CTI.HO;
{ ...
... End Namespace
} ' or
or Namespace CTIGroup
namespace CTIGroup Namespace CTI
{ Namespace HO
namespace CTI ... // Import single class
{ End Namespace import CTIGroup.CTI.HO.Table;
namespace HO End Namespace // Import all classes
{ End Namespace import CTIGroup.CTI.HO.*;
... Imports CTIGroup.CTI.HO

}
}
// Import all class. Can't import single class.
using CTIGroup.CTI.HO;

Basic C# Programming | V1.0 August 2015 Page 263 of 276


C# VB.NET (v2) Java (v5)
CLASSES / INTERFACES
Accessibility keywords Accessibility keywords Accessibility keywords
public Public public
private Private private
internal Friend protected
protected Protected static
protected internal Protected Friend
static Shared // Inheritance
// Inheritance ' Inheritance class FootballGame extends Competition {
class FootballGame : Competition Class FootballGame ...
{ Inherits Competition }
... ... // Interface definition
} End Class interface IAlarmClock {
// Interface definition ' Interface definition ...
interface IAlarmClock Interface IAlarmClock }
{ ... // Extending an interface
... End Interface interface IAlarmClock extends IClock {
} ‘ Extending an interface ...
// Extending an interface Interface IAlarmClock }
interface IAlarmClock : IClock Inherits IClock // Interface implementation
{ ... class WristWatch implements IAlarmClock, ITimer {
... End Interface ...
} ‘ Interface implementation }
// Interface implementation Class WristWatch
class WristWatch : IAlarmClock, ITimer Implements IAlarmClock, ITimer
{ ...
... End Class
}

Basic C# Programming | V1.0 August 2015 Page 264 of 276


C# VB.NET (v2) Java (v5)
CONSTRUCTORS / DESTRUCTORS
class SuperHero Class SuperHero class SuperHero {
{ Private _powerLevel As Integer private int mPowerLevel;
private int mPowerLevel; public SuperHero() {
Public Sub New() mPowerLevel = 0;
public SuperHero() _powerLevel = 0 }
{ End Sub public SuperHero(int powerLevel) {
mPowerLevel = 0; this.mPowerLevel= powerLevel;
} Public Sub New(ByVal powerLevel As Integer) }
Me._powerLevel = powerLevel // No destructors, just override the finalize
public SuperHero(int powerLevel) End Sub // method
{ protected void finalize() throws Throwable {
this.mPowerLevel= powerLevel; Protected Overrides Sub Finalize() // Always call parent's finalizer
} ' Desctructor code to free unmanaged resources super.finalize();
MyBase.Finalize() }
~SuperHero() End Sub }
{ End Class
// Destructor code to free unmanaged resources.
// Implicitly creates a Finalize method.
}

CONSOLE I/O
Console.Write("What's your name? "); Console.Write("What's your name? ") System.out.print("What's your name? ");
string name = Console.ReadLine(); Dim name As String = Console.ReadLine() string name = in.readline();
Console.Write("How old are you? "); Console.Write("How old are you? ") System.out.print("How old are you? ");
int age = Convert.ToInt32(Console.ReadLine()); Dim age As Integer = Val(Console.ReadLine()) int age = Integer.parseInt(in.readline());
Console.WriteLine(name + " is " + age + Console.WriteLine("{0} is {1} years old.", name, _ System.out.println(name + “ is “ + age + “ years
" years old."); age) old”);
' or
int c = Console.Read(); // Read single char Console.WriteLine(name & " is " & age & _ int c;
Console.WriteLine(c); // Prints 65 if user " years old.") c = in.read();
// enters "A" System.out.println(in);
Dim c As Integer
c = Console.Read() ' Read single char
Console.WriteLine(c) ' Prints 65 if user enters
‘ "A"

Basic C# Programming | V1.0 August 2015 Page 265 of 276


C# VB.NET (v2) Java (v5)
USING OBJECTS
SuperHero hero = new SuperHero(); Dim hero As SuperHero = New SuperHero SuperHero hero = new SuperHero();
' or hero.setName("SpamMan");
hero.Name = "SpamMan"; Dim hero As New SuperHero hero.setPowerLevel(3);
hero.PowerLevel = 3; With hero
hero.Defend("Laura Jones"); .Name = "SpamMan" hero.Defend("Laura Jones");
SuperHero.Rest(); // Calling static method .PowerLevel = 3 SuperHero.Rest(); // Calling static method
End With
// Both refer to same object hero.Defend("Laura Jones") // Both refer to same object
SuperHero hero2 = hero; hero.Rest() ' Calling Shared method SuperHero hero2 = hero;
' or
hero2.Name = "WormWoman"; SuperHero.Rest() hero2.setName("WormWoman");
' Both reference the same object
// Prints WormWoman Dim hero2 As SuperHero = hero // Prints WormWoman
Console.WriteLine(hero.Name); hero2.Name = "WormWoman" System.out.println(hero.getName());

// Free the object Console.WriteLine(hero.Name) ' Prints WormWoman hero = null; // Free the object
hero = null ; hero = Nothing ' Free the object if (hero == null)
If hero Is Nothing Then _ {
if (hero == null) hero = New SuperHero hero = new SuperHero();
{ Dim obj As Object = New SuperHero }
hero = new SuperHero(); If TypeOf obj Is SuperHero Then _
} Console.WriteLine("Is a SuperHero object.") Object obj = new SuperHero();
End If System.out.println("object's type: " +
Object obj = new SuperHero(); obj.getClass().toString());
Console.WriteLine("object's type: " + Using reader As StreamReader = _
obj.GetType().ToString()); File.OpenText("test.txt") if (obj instanceof SuperHero)
{
if (obj is SuperHero) Dim line As String = reader.ReadLine() System.out.println("Is a SuperHero object.");
{ While Not line Is Nothing }
Console.WriteLine(line)
Console.WriteLine("Is a SuperHero object."); line = reader.ReadLine()
} End While
End Using

Basic C# Programming | V1.0 August 2015 Page 266 of 276


C# VB.NET (v2) Java (v5)
PROPERTIES
private int mSize; Private mSize As Integer private int mSize;
public int Size { Public Property Size() As Integer public int getSize() { return mSize; }
get Get public void setSize(int value) {
{ Return mSize if (value < 0)
return mSize; End Get mSize = 0;
} else
set Set mSize = value;
{ If (value < 0) Then }
if (value < 0) mSize = 0
{ Else int s = shoe.getSize();
mSize = 0; mSize = value shoe.setSize(s+1);
} End If
else End Set
{ End Property
mSize = value;
} shoe.Size = shoe.Size + 1
}
}
shoe.Size++;

STRUCTS
struct StudentRecord Structure StudentRecord No structs in Java.
{ Public name As String
public string name; Public gpa As Single
public float gpa;
Public Sub New(ByVal name As String, _
public StudentRecord(string name, float gpa) ByVal gpa As Single)
{ Me.name = name
this.name = name; Me.gpa = gpa
this.gpa = gpa; End Sub
} End Structure
} Dim stu As StudentRecord = _
StudentRecord stu = new StudentRecord("Bob", 3.5f); New StudentRecord("Bob", 3.5)
StudentRecord stu2 = stu;
Dim stu2 As StudentRecord = stu
stu2.name = "Sue";
Console.WriteLine(stu.name); // Prints Bob stu2.name = "Sue"
Console.WriteLine(stu2.name); // Prints Sue Console.WriteLine(stu.name) ' Prints Bob
Console.WriteLine(stu2.name) ' Prints Sue

Basic C# Programming | V1.0 August 2015 Page 267 of 276


C# VB.NET (v2) Java (v5)
FILE I/O
using System.IO; Imports System.IO import java.io.*;

// Character stream writing ' Write out to text file // Character stream writing
StreamWriter writer = File.CreateText("myfile.txt"); Dim writer As StreamWriter = FileWriter writer = new FileWriter("myfile.txt");
writer.WriteLine("Out to file."); File.CreateText("myfile.txt") writer.write("Out to file.\n");
writer.Close(); writer.WriteLine("Out to file.") writer.close();
writer.Close()
// Character stream reading // Character stream reading
StreamReader reader = File.OpenText("myfile.txt"); ' Read all lines from text file FileReader reader = new FileReader("myfile.txt");
string line = reader.ReadLine(); Dim reader As StreamReader = BufferedReader br = new BufferedReader(reader);
while (line != null) File.OpenText("myfile.txt") String line = br.readLine();
{ Dim line As String = reader.ReadLine() while (line != null)
Console.WriteLine(line); While Not line Is Nothing {
line = reader.ReadLine(); Console.WriteLine(line) System.out.println(line);
} line = reader.ReadLine() line = br.readLine();
reader.Close(); End While }
reader.Close() reader.close();
// Binary stream writing
BinaryWriter out = new ' Write out to binary file // Binary stream writing
BinaryWriter(File.OpenWrite("myfile.dat")); Dim str As String = "Text data" FileOutputStream out = new
out.Write("Text data"); Dim num As Integer = 123 FileOutputStream("myfile.dat");
out.Write(123); Dim binWriter As New out.write("Text data".getBytes());
out.Close(); BinaryWriter(File.OpenWrite("myfile.dat")) out.write(123);
binWriter.Write(str) out.close();
// Binary stream reading binWriter.Write(num)
BinaryReader in = new binWriter.Close() // Binary stream reading
BinaryReader(File.OpenRead("myfile.dat")); FileInputStream in = new
string s = in.ReadString(); ' Read from binary file FileInputStream("myfile.dat");
int num = in.ReadInt32(); Dim binReader As New byte buff[] = new byte[9];
in.Close(); BinaryReader(File.OpenRead("myfile.dat")) // Read first 9 bytes into buff
str = binReader.ReadString() in.read(buff, 0, 9);
num = binReader.ReadInt32() String s = new String(buff);
binReader.Close() int num = in.read(); // Next is 123
in.close();

Basic C# Programming | V1.0 August 2015 Page 268 of 276


Glossary

Term Description

A keyword, such as private, protected, internal, or public,


Access modifier
that restricts access to a type or type member.

A member that can be accessed by a given type. An


Accessible member accessible member for one type is not necessarily
accessible to another type.
A code block that is passed as a parameter to
Anonymous method
a delegate.

Base class A class that is inherited by another 'derived' class.

A data type that describes an object. Classes contain


Class
both data, and the methods for acting on the data.
A special method on a class or struct that initializes
Constructor
the objects of that type.
A special type of user-defined variable that is declared
Delegate
globally, like a class.

A class that uses inheritance to gain, augment, or


Derived class
modify the behaviour and data of another 'base' class.

A special method on a class or struct that prepares the


Destructor
instance for destruction by the system.
A member of a class or struct that sends notifications of
event
a change.
Integrated Development Environment. The application
that provides the unified user interface for the various
IDE
development tools including the compiler, debugger,
code editor and designers.
A type whose instance data, fields and properties,
Immutable type does not change after the instance is created. Most
value types are immutable.
A member that cannot be accessed by a given type.
Inaccessible member An inaccessible member for one type is not necessarily
inaccessible to another type.
C# supports inheritance, so a class that derives from
another class, known as the base class, inherits the
Inheritance
same methods and properties. Inheritance involves
base classes and derived classes.

Basic C# Programming | V1.0 August 2015 Page 269 of 276


A type that contains only the signatures of public
methods, events and delegates. An object that inherits
Interface the interface must implement all of the methods and
events defined in the interface. Classes or structs may
inherit any number of interfaces.
A field, property, method, or event declared on
Member
a class or struct.
A named code block that provides behaviour for
Method
a class or struct.
A type whose instance data, fields and properties, can
Mutable type
be changed after the instance is created.
An instance of a class. An object exists in memory and
Object
has data and methods that act on the data.
A compound data type that is typically used to contain
a few variables that have some logical relationship.
Struct Structs can also contain methods and events. Structs
do not support inheritance but they do support
interfaces.
A value type is a data type that is allocated on the
Value type stack, as opposed to a reference type which is
allocated on the heap

Basic C# Programming | V1.0 August 2015 Page 270 of 276


Bibliography

Textbooks

Sharp, J. 2013. Microsoft Visual C# 2013 Step by Step. Microsoft Press

Dorman, S., 2010. Sams teach yourself Visual C# 2010 in 24 hours: Complete
Starter Kit. Boston: Pearson Education, Inc.

Deitel, PJ & Deitel, HM. 2009. C# 2008 for programmers. Third Edition.
Boston: Pearson Education, Inc.

Mayo, J. 2002. C# unleashed. Sams Publishing.

Websites

Blackwasp. www.blackwasp.co.uk [Accessed 17 March 2014].

Microsoft Developer Network (MSDN). www.msdn.microsoft.com [Accessed 17


March 2014].

Tutorialspoint: http://www.tutorialspoint.com/csharp/

Basic C# Programming | V1.0 August 2015 Page 271 of 276


C# – Exercise Checklist
BCSM-16V1.0

Student: ________________________________________ Start date: ______________

Students please note that unless all of your exercises have been signed off by an instructor
you will not be allowed to book for the exam.

DATE INITIAL DATE INITIAL DATE INITIAL

1.1.4 Introduction to C# 1.3.5 Writing C# expressions 1.4.6 Advanced coding


Exercises Exercises continued… techniques Revision questions
(Complete exercise on paper) (Complete exercise on paper) (Complete exercise on paper)

1 _______________ 2 _______________ 1 _______________

2 _______________ 3 _______________ 2 _______________

3 _______________ 4 _______________ 3 _______________


1.1.5 Introduction to C# Revision 5 _______________ 4 _______________
questions
(Complete exercise on paper)
6 _______________ 1.5.8 Coding object-oriented
applications Exercises
1 _______________ (Complete exercise on paper)
7 _______________
2 _______________ 1 _______________
8 _______________
3 _______________ 2 _______________
1.3.6 Writing C# expressions
Revision questions
1.2.3 Object-oriented
programming concepts Exercises
(Complete exercise on paper) 3 _______________
(Complete exercise on paper)
1 _______________ 1.5.9 Coding object-oriented
applications Revision questions
1 _______________ (Complete exercise on paper)
2 _______________
2 _______________ 1 _______________
3 _______________
3 _______________ 2 _______________
4 _______________
1.2.4 Object-oriented
programming concepts Revision 5 _______________ 3 _______________
questions
(Complete exercise on paper) 1.6.3 Preprocessor directives
6 _______________ Exercises
1 _______________ (Complete exercise on paper)
7 _______________
2 _______________ 1 _______________
1.4.5 Advanced coding techniques
Exercises
3 _______________ (Complete exercise on paper) 2 _______________

1.3.5 Writing C# expressions 1 _______________ 3 _______________


Exercises
(Complete exercise on paper) 2 _______________

1 _______________ 3 _______________

Basic C# Programming | V1.0 August 2015 Page 272 of 276


DATE INITIAL DATE INITIAL DATE INITIAL

1.6.4 Preprocessor directives Unit 1 – Test your knowledge 2.2.4 Object-oriented


Revision questions Multiple response programming basics Exercises
(Complete exercise on paper) (Complete exercise on paper) (Complete exercise on paper)

1 _______________ 1 _______________ 1 _______________

2 _______________ 2 _______________ 2 _______________

3 _______________ Unit 1 – Test your knowledge 3 _______________


Selection
(Complete exercise on paper)
1.7.3 Using the Math and 4 _______________
Random classes Exercises
(Complete exercise on paper) 1 _______________
5 _______________
1 _______________ 2.1.8 Using classes in C#
Exercises 6 _______________
(Complete exercise on paper)
2 _______________
7 _______________
1 _______________
3 _______________
2.2.5 Object-oriented
2 _______________ programming basics Revision
1.7.4 Using the Math and questions
Random classes Revision (Complete exercise on paper)
questions 3 _______________
(Complete exercise on paper)
1 _______________
4 _______________
1 _______________
2 _______________
5 _______________
2 _______________
3 _______________
6 _______________
3 _______________
4 _______________
7 _______________
Unit 1 – Test your knowledge
Multiple choice 2.3.4 Overloading class members
(Complete exercise on paper) 8 _______________ and operators Exercises
(Complete exercise on paper)
1 _______________ 9 _______________
1 _______________
2 _______________ 10 _______________
2 _______________
3 _______________ 2.1.9 Using classes in C# Revision
questions 3 _______________
(Complete exercise on paper)
4 _______________
2.3.5 Overloading class members
1 _______________ and operators Revision questions
5 _______________ (Complete exercise on paper)
2 _______________
6 _______________ 1 _______________
3 _______________
Unit 1 – Test your knowledge 2 _______________
True/False
(Complete exercise on paper) 4 _______________
3 _______________
1 _______________ 5 _______________

1 ______________

Basic C# Programming | V1.0 August 2015 Page 273 of 276


DATE INITIAL DATE INITIAL DATE INITIAL

2.4.4 Exceptions and exception 2.6.7 Structs and conversions Unit 2 – Test your knowledge
handling Exercises Revision questions Multiple response
(Complete exercise on paper) (Complete exercise on paper) (Complete exercise on paper)

1 _______________ 1 _______________ 1 _______________

2 _______________ 2 _______________ 2 _______________

3 _______________ 3 _______________ 3 _______________

4 _______________ 4 _______________ 3.1.3 Delegates and events


Exercises
(Complete exercise on paper)
2.4.5 Exceptions and exception 2.7.4 Using and implementing
handling Revision questions interfaces Exercises
(Complete exercise on paper) (Complete exercise on paper) 1 _______________

1 _______________ 1 _______________ 2 _______________

2 _______________ 2 _______________ 3 _______________

3 _______________ 3 _______________ 4 _______________

4 _______________ 2.7.5 Using and implementing 3.1.4 Delegates and events


interfaces Revision questions Revision questions
(Complete exercise on paper) (Complete exercise on paper)
2.5.3 Organising code with
namespaces Exercises
(Complete exercise on paper) 1 _______________ 1 _______________

1 _______________ 2 _______________ 2 _______________

2 _______________ 3 _______________ 3 _______________

2.5.4 Organising code with Unit 2 – Test your knowledge 4 _______________


namespaces Revision questions True/False
(Complete exercise on paper) (Complete exercise on paper)
3.2.12 Introduction to Windows
forms Exercises
1 _______________ 1 _______________ (Complete exercise on PC)

2 _______________ Unit 2 – Test your knowledge 1 _______________


Multiple choice
(Complete exercise on paper)
2.6.6 Structs and conversions 2 _______________
Exercises
(Complete exercise on paper) 1 _______________
3 _______________
1 _______________ 2 _______________
4 _______________
2 _______________ 3 _______________
5 _______________
3 _______________ 4 _______________
6 _______________
4 _______________ 5 _______________

Basic C# Programming | V1.0 August 2015 Page 274 of 276


DATE INITIAL DATE INITIAL DATE INITIAL

3.2.13 Introduction to Windows 3.4.6 String manipulation and Unit 3 – Test your knowledge
forms Revision questions regular expressions Revision Multiple choice
(Complete exercise on paper) questions (Complete exercise on paper)
(Complete exercise on paper)

1 _______________ 1 _______________
1 _______________
2 _______________ 2 _______________
2 _______________
3 _______________ 3 _______________
3 _______________
3.3.7 More advanced controls
Exercises 3.5.8 Collections Exercises 4 _______________
(Complete exercise on paper) (Complete exercise on paper)
Unit 3 – Test your knowledge
Multiple response
1 _______________ 1 _______________ (Complete exercise on paper)

2 _______________ 2 _______________ 1 _______________

3 _______________ 3 _______________ 2 _______________

4 _______________ 4 _______________ 3 _______________

5 _______________ 5 _______________ 4 _______________

3.3.8 More advanced controls 6 _______________ 5 _______________


Revision questions
(Complete exercise on paper)
3.5.9 Collections Revision
questions
1 _______________ (Complete exercise on paper)

2 _______________ 1 _______________

3 _______________ 2 _______________

3.4.5 String manipulation and 3 _______________


regular expressions Exercises
(Complete exercise on paper)
4 _______________
1 _______________
Unit 3 – Test your knowledge
True/False
2 _______________ (Complete exercise on paper)

3 _______________ 1 _______________

4 _______________ 2 _______________

5 _______________ 3 _______________

6 _______________ 4 _______________

7 _______________

Basic C# Programming | V1.0 August 2015 Page 275 of 276


Basic C# Programming – Evaluation form
BCSM-16 V1.0

Please follow the link below to evaluate the module.

CTI Education Group Module Evaluation

Note: Please ensure that you have Google Chrome browser installed on your
device before viewing the link.

Basic C# Programming | V1.0 August 2015 Page 276 of 276


Contact details
Bedfordview Campus Bloemfontein Campus
9 Concorde Road East, Bedfordview Tourist Centre, 60 Park Avenue, Willows, Bloemfontein
P.O. Box 1389, Bedfordview, 2008 P.O. Box 1015, Bloemfontein, 9300
Tel: +27 (0)10 595 2999, Fax: +27 (0)86 686 4950 Tel: +27 (0)51 430 2701, Fax: +27 (0)51 430 2708
Email: bedfordview@cti.ac.za Email: bloemfontein@cti.ac.za

Cape Town Campus


Durban Campus
The Brookside Building, 11 Imam Haron Str
1 Lunar Row, Umhlanga Ridge, Durban
(old Lansdowne Road), Claremont
P.O. Box 20251, Durban North, 4016
P.O. Box 2325, Clareinch, 7740
Tel: +27 (0)31 564 0570/5, Fax: +27 (0)31 564 8978
Tel: +27 (0)21 674 6567, Fax: +27 (0)21 674 6599
Email: durban@cti.ac.za
Email: capetown@cti.ac.za

Durbanville Campus East London Campus


Kaapzicht, 9 Rogers Street, Tyger Valley 12 Stewart Drive, Berea, East London
P.O. Box 284, Private Bag X7 PostNet Suite 373
Tyger Valley, 7536 Private Bag X9063, East London, 5200
Tel: +27 (0)21 914 8000, Fax: +27 (0)21 914 8004 Tel: +27 (0)43 721 2564, Fax: +27 (0)43 721 2597
Email: durbanville@cti.ac.za Email: eastlondon@cti.ac.za

Port Elizabeth Campus


Nelspruit Campus
50 Murray Street, Nelspruit Building 4, Ascot Office Park
P.O. Box 9497, Sonpark, Nelspruit, 1206 Cnr Ascot & Conyngham Roads, Greenacres
Tel: +27 (0)13 755 3918, Fax: +27 (0)13 755 3918 P.O. Box 40049, Walmer, 6065
Email: nelspruit@cti.ac.za Tel: +27 (0)41 374 7978, Fax: +27 (0)41 374 3190
Email: port_elizabeth@cti.ac.za

Potchefstroom Campus Pretoria Campus


12 Esselen Street, Cnr Esselen Street 22 Umgazi Street, Menlo Park, Pretoria
& Steve Biko Avenue, Die Bult, Potchefstroom PostNet Suite A147, Private Bag X18,
P.O. Box 19900, Noordbrug, 2522 Lynnwood Ridge, 0040
Tel: +27 (0)18 297 7760, Fax: +27 (0)18 297 7783 Tel: +27 (0)12 348 3060, Fax: +27 (0)12 348 3063
Email: potchefstroom@cti.ac.za Email: pretoria@cti.ac.za

Randburg Campus Vanderbijlpark Campus


6 Hunter Avenue, Cnr Bram Fischer Drive Building 2, Cnr Rutherford & Frikkie Meyer Boulevards
Ferndale, Randburg Vanderbijlpark
P.O. Box 920, Randburg, 2125 P.O. Box 6371, Vanderbijlpark, 1900
Tel: +27 (0)11 789 3178, Fax: +27 (0)11 789 4606 Tel: +27 (0)16 931 1180, Fax: +27 (0)16 933 1055
Email: randburg@cti.ac.za Email: vanderbijlpark@cti.ac.za

Group Head Office


Management Services Building
44 Alsatian Road, Glen Austin Extension 3, Midrand
P.O. Box 1398, Randburg, 2125
Tel: +27 (0)11 467 8422, Fax: +27 (0)86 583 6660
Website: www.cti.ac.za

CTI is part of Pearson, the world’s leading learning company. Pearson is the corporate owner, not a registered
provider nor conferrer of qualifications in South Africa. CTI Education Group (Pty) Ltd. is registered with
the Department of Higher Education and Training as a private higher education institution under the
Higher Education Act, 101, of 1997. Registration Certificate number: 2004/HE07/004. www.cti.ac.za.

You might also like