Professional Documents
Culture Documents
Course Book Intro To Programming 2 ATU Sligo Ireland
Course Book Intro To Programming 2 ATU Sligo Ireland
Course Book Intro To Programming 2 ATU Sligo Ireland
Introduction to Programming 2
Vivion Kinsella
2
Sources I have used when writing up these notes
1. Murach’s c# 2012
2. https://www.thecodingguys.net/tutorials/csharp/csharp-tutorial/
3. https://www.geeksforgeeks.org/c-sharp-namespaces/
4. https://www.tutorialspoint.com/csharp/
5. https://docs.microsoft.com/en-us/dotnet
6. https://rubygarage.org/blog/most-basic-git-commands-with-examples
Book Recommendations
1. All the above +
2. Visual C# 2017, An Introduction to Object-oriented Programming, Joyce Farrell
3
Contents
Chapter 1 :Introduction 4
Chapter 2 : Quick review 5
Data
Selection
Loops
Methods
Arrays
4
Chapter 1 : Introduction
What is this module going to cover?
This module shall build on the fundamentals of programming covered in semester 1. Initially
we will revisit some of the material from semester 1 and re-enforce our knowledge and
understanding.
Then we will learn how to develop solutions to problems that make use of string handling,
data validation, exception handling, file handling and object oriented techniques.
I’m really looking forward to it, I hope you are too!
5
Chapter 2 – A Quick Review
Data in programs
• Programs are made up of data and operations that work on that data
• C# programs contain variables that hold the data to be processed
• The program must declare each variable before it is used
• Variables are of a particular data type
• The type of a variable determines what a program can store in it
• The C# language is strongly typed in that the compiler will prevent you from combining
data types ways it things are wrong
• This is to make programs more reliable
C# is a strongly typed language which means, you must declare a variable type before you
can use it. But what if you don’t know the type of the variable? C# lets you declare local
variables without giving them explicit types. It is possible with the help of the var type
variable.
6
The var keyword is used to declare a var type variable. The var type variable can be
used to store a simple data type, a complex type, an anonymous type, or a user-defined
type. We have only used simple types so far.
// string value
var name = "Pat Ryan";
Console.WriteLine($"var holds a string = {name}");
// int value
var age = 25;
Console.WriteLine($"var holds an int = {age}");
// string value
var salary = 45000.65;
Console.WriteLine($"var holds a double = {salary}");
o Use var when you’re not sure what type of data will be stored in a variable.
o Use in anonymous types and anonymous collections
o Its real value will become more apparent in year2.
7
Selection
As we saw last semester, the structure mostly used for selection is if/if.. else.
A second structure which can be useful sometimes is switch. Here we look again at the
switch statement – it was in book 1, but we didn’t spend any time on it.
8
Switch statement
• The switch statement provides another means to decide which statement to execute
next when there are more than 1 alternative.
• The switch statement evaluates an expression, then attempts to match the result to
one of several possible cases.
• The flow of control transfers to statement list associated with the first value that
matches.
• The expression of a switch statement must result in an integral data type, like an
integer or character or a string.
• Note that the implicit boolean condition in a switch statement is equality - it tries to
match the expression with a value
• A switch statement can have an optional default case as the last case in the
statement
• The default case has no associated value and simply uses the reserved word default
• If the default case is present, control will transfer to it if no other case value matches
• If there is no default case, and no other value matches the expression, control falls
through to the statement after the switch
• A break statement is used as the last statement in each case's statement list
• A break statement causes control to transfer to the end of the switch statement.
9
Figure 1 Switch Syntax
10
Example
class Program
{
static void Main(string[] args)
{
switch (dayNum)
{
case 1: // when dayNum has a value of 1 execute this case
message = "Monday";
break;
case 2:
message = "Tuesday";
break;
case 3:
message = "Wednesday";
break;
case 4:
message = "Thursday";
break;
case 5:
message = "Friday";
break;
case 6:
message = "Saturday";
break;
case 7:
message = "Sunday";
break;
default:
message = "error";
break;
}
Console.WriteLine(message);
11
Example : multiple cases that result in the same outputs
class Program
{
static void Main(string[] args)
{
switch (dayNum)
{
case 1:
case 2:
case 3:
case 4:
case 5:
message = "Midweek day"; // when dayNum has a value of 1,2,3,4 or
5 execute this case
break;
case 6:
case 7:
message = "Weekend day";
break;
default:
message = "error";
break;
}
Console.WriteLine(message);
12
Loops
As we’ve already seen, there are three main structures used to enable repetition of
statements or blocks of statements. These work in slightly different ways.
13
Methods
As our programs have started to get bigger and the problems we are solving more complex,
the simple structure of putting all our code into the Main() method becomes very unwieldly
and doesn’t reflect our divide and conquer approach to problem solving. A better approach
is to use multiple methods where each method performs a specific task.
2. If the data is declared locally, i.e. inside a method we can share it by passing the
variable to the called method through its parameter list.
14
When passing values, we can either
1. Pass by value : we give a copy of our data to the called method, meaning the called
method has only read access to our data, it cannot modify it. This is the default
mechanism as it is the most secure.
2. Pass by reference : we give the address of our data to the called method, giving it
read/write access to our data-always ask are you happy to do this? We specify this
type of passing by placing Ref or Out in from of the parameters. Use Ref when
parameter has an initial value, Out when parameter has no initial value.
Example : Pass a bank balance to a method, update the balance if sufficient funds available,
return true if transaction successful otherwise return false.
15
Arrays
An array stores a fixed-size sequential collection of elements of the same type. An array is used to
store a collection of data, it is often more useful to think of an array as a collection of variables of
the same type stored at contiguous memory locations.
• This will create a variable which can hold a single integer value
• But if we have a lot of sales, image 4000, this could get very tedious and make
coding to manage these very difficult
• An array lets us create a row of variables which we can index using a subscript
• Once you have your array you can place values into the elements in it:
int [] sales = new int [4];
sales [0] = 5;
sales [1] = 7
sales [2] = 8
sales [3] = 10;
5 7 8 10
[0] [1] [2] [3]
16
Prints
Sales 1 = 5
• Watch out! - It’s common to introduce off-by-one errors when using arrays
• If you try to access an element which is not in the array (perhaps by using a subscript
which is too large or less than zero) your program will fail
• For example, if the array sales can hold 4 values, it can only be indexed using the
numbers 0 to 3
Subscripts
• Subscripts become very powerful when we discover that we can use a variable as a
subscript:
static void Main(string[] args)
{
}
}
• Each array has a public property called Length that stores the size of the array
- once an array is created, it has a fixed size
- It is referenced using the array name:
sales.Length
• Note that Length holds the number of elements, not the largest index
17
• This can be very handy when we want to write a method that will work with an array
of any length
// return the sum of all values stored in an array
// note how array is declared in parameter list
// note that by default arrays are passed by reference
// why do you think this is so?
static int AddUp(int[] myArray)
{
int sum = 0;
for (int i = 0; i < myArray[i]; i++)
{
sum = sum + myArray[i];
}
return sum;
}
Initialising Arrays
• An initialiser list can be used to instantiate and initialize an array in one step
18
Two – Dimensional Arrays
56
34
78
class Program
{
static void Main(string[] args)
{
// print contents of all elements in a 2d array
int[,] board = new int[3, 3];
board[1, 1] = 34; // board(row,column)
board[0, 2] = 56;
board[2, 0] = 78;
• Copy (array1,array2,length);
• BinarySearch(arrayName,value);
• Sort(arrayName)
19
Chapter 3 - String Handling
The String class has numerous methods that help you in working with the string objects.
There are lots of times when writing a program we will want to manipulate strings, for
instance.
Compares two specified string objects and returns an integer that indicates their relative
position in the sort order.
Compares two specified string objects and returns an integer that indicates their relative
position in the sort order. However, it ignores case if the Boolean parameter is true.
3 public static string Concat(string str0, string str1) // overloaded with 3 others
Concatenates two string objects. The other deal with 3 and 4 bjects
Returns a value indicating whether the specified String object occurs within this string.
Creates a new String object with the same value as the specified string.
8 public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
Copies a specified number of characters from a specified position of the String object to a
specified position in an array of Unicode characters.
20
9 public bool EndsWith(string value)
Determines whether the end of the string object matches the specified string.
Determines whether the current String object and the specified String object have the same
value.
Determines whether two specified String objects have the same value.
Replaces one or more format items in a specified string with the string representation of a
specified object.
Returns the zero-based index of the first occurrence of the specified Unicode character in the
current string.
Returns the zero-based index of the first occurrence of the specified string in this instance.
Returns the zero-based index of the first occurrence of the specified Unicode character in this
string, starting search at the specified character position.
Returns the zero-based index of the first occurrence of the specified string in this instance,
starting search at the specified character position.
Returns the zero-based index of the first occurrence in this instance of any character in a
specified array of Unicode characters.
Returns the zero-based index of the first occurrence in this instance of any character in a
specified array of Unicode characters, starting search at the specified character position.
21
19 public string Insert(int startIndex, string value)
Returns a new string in which a specified string is inserted at a specified index position in the
current string object.
Return a string that’s right aligned and padded on the left with spaces so it is the specified
length
Concatenates all the elements of a string array, using the specified separator between each
element.
22 public static string Join(string separator, string[] value, int startIndex, int count)
Concatenates the specified elements of a string array, using the specified separator between
each element.
Returns the zero-based index position of the last occurrence of the specified Unicode character
within the current string object.
Returns the zero-based index position of the last occurrence of a specified string within the
current string object.
Removes all the characters in the current instance, beginning at a specified position and
continuing through the last position, and returns the string.
Removes the specified number of characters in the current string beginning at a specified
position and returns the string.
Replaces all occurrences of a specified Unicode character in the current string object with the
specified Unicode character and returns the new string.
22
Replaces all occurrences of a specified string in the current string object with the specified
string and returns the new string.
Returns a string array that contains the substrings in the current string object, delimited by
elements of a specified Unicode character array.
Returns a string array that contains the substrings in the current string object, delimited by
elements of a specified Unicode character array. The int parameter specifies the maximum
number of substrings to return.
Substring(StartIndex[,length])
Return a string that starts at the specified position and has the specified length
Determines whether the beginning of this string instance matches the specified string.
Returns a Unicode character array with all the characters in the current string object.
Returns a Unicode character array with all the characters in the current string object, starting
from the specified index and up to the specified length.
36 public string Trim() : remove all leading and trailing white space characters from current strin
23
// Demo of some string functions
class Program
{
static void Main(string[] args)
{
string address = "pat ryan,sligo";
// write out the first character
24
// remove ' ', '$', '," and '*' from a string
// this has a 2 bugs... fix it
}
}
25
Chapter 4 - Data Validation – Checking for error conditions
Ok, let’s admit it, a lot of the programs that we have written up to now are brittle, that is
they will crash fairly easily or produce unexpected results. This can happen when we ask
the user
Can you think of other situations where your program has crashed?
Look what happened when we run this code and the user enters a string (I bet you’ve this
this quite a bit)
26
Dealing with wrong data types
To avoid these situations we need to check that a user has entered data in the correct
format before we proceed to process this data further. This is going to take a little more
effort but we will end up with a more robust program and happier user
TryParse
The TryParse method converts the string representation of a number to its 32-bit signed
integer equivalent (or other numeric format). A return value indicates whether the
conversion succeeded.
Syntax
Parameters
result : Integer value equivalent of the number contained in s, if the conversion succeeded,
or zero if the conversion failed. The conversion fails if the s parameter is null or Empty or is
not of the correct format. This parameter is passed uninitialized; any value originally
supplied in result will be overwritten.
TryParse returns true if s was converted successfully; otherwise, false. Note that an
overloaded version of TryParse allows us to check against min and max values.
27
Example : check that an integer value is entered
static void Main(string[] args)
{
string userInput;
int myAge;
Example : Here is a slightly more elaborate example where we read through an array of
values and check each value to see if it is an integer.
28
More Data Validation – to cover a number of possible errors
Below is a really nice program that demonstrates the use of generic methods to do data
validation. These are methods that we could reuse in any program we write from now on.
We could just copy and paste the code into new projects but a better way would be to
include these in a static class, compile this and reference this class in any project where we
need to use them.
Here we want to allow a user to repeatedly enter their age until a valid value is entered.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ValidationDemo
{
class Program
{
static void Main(string[] args)
{
string inputString;
int age;
// keep asking user for there age until we are happy with value entered
do
{
Console.Write("Enter your age : ");
inputString = Console.ReadLine();
}
while (IsValidData(inputString,"age") == false);
// from here we can proceed with normal processing
}
29
static bool IsPresent(string textIn, string name)
{
if (textIn == "")
{
Console.WriteLine(name + " is a required field.", "Entry Error");
return false;
}
return true;
}
static bool IsInteger(string textIn, string name)
{
int num;
return false;
}
static bool IsWithinRange(string textIn, string name, int min, int max)
{
int number = int.Parse(textIn);
if (number < min || number > max)
{
Console.WriteLine(name + " must be between " + min + " and " + max
+ ".", "Entry Error");
return false;
}
return true;
}
}
}
Notice the way these methods can be injected with different values, allowing them to be
used in many different situations, for example the IsWithInRange() method could be
injected with a different prompt, a different name and different min and max values.
30
Chapter 5 – Exception handling
Overview
Exceptions are unusual runtime errors that can make a program behave abruptly if not
handled in the right way. Hence, most programming languages add exception handling
capabilities to allow us deal with these and potentially recover from them –error recovery.
As we have seen in the previous section we can anticipate some errors and can have code
checks that check if the data is ok before we do any processing on it.
But sometimes we have no control over circumstances that might affect our program.
For example, if our program tries to reference an array index that does not exist or tries to
read a file that does not exist, it may abort.
C# provides exception handling facility to allow the programmer insert code to handle such
unexpected errors and allow the program to recover and continue executing, or to
terminate gracefully, whichever is appropriate.
31
Exception Classes in C#
C# exceptions are represented by classes. The exception classes in C# are mainly directly or
indirectly derived from the System.Exception class.
The following list provides some of the predefined exception classes derived from the
Sytem.Exception class −
• IndexOutOfRangeException
• OutOfMemoryException
• FormatException
• IOException
• FileNotFoundException
• Exception // unspecified
2. We use a try block around the statements that might throw exceptions.
3. Once an exception occurs within the try block, the flow of control immediately
jumps to an associated exception handler, if one is present.
5. If no exception handler for a given exception is present, the program stops executing
with an error message.
6. If a catch block defines an exception variable, you can use it to get more information
on the type of exception that occurred.
8. Exception objects contain detailed information about the error, including the state of
the call stack and a text description of the error.
9. When an exception occurs, execution stops and control is given to the appropriate
exception handler. This often means that lines of code you expect to be executed are
bypassed. Some resource cleanup, such as closing a file (or landing all planes!),
needs to be done even if an exception is thrown. To do this, you can use a finally
block. A finally block always executes, regardless of whether an exception is thrown.
32
Syntax
try
{
// statements causing exception
}
catch( ExceptionName e1 )
{
// error handling code
} catch( ExceptionName e2 )
{
// error handling code
}
catch( ExceptionName eN )
{
// error handling code
}
finally
{
// statements to be executed
}
33
Example 1 – Try Catch
static void Main(string[] args)
{
int num1, num2;
double quotient;
bool isValid;
}
while (isValid == false); // if there is a problem, try block is re
executed
}
34
Example 2 Try - Catch
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace TryCatch
{
class Program // demo of try catch exception handling
{
static void Main(string[] args)
{
int code;
string messageOut;
try
{
messageOut = msgArray[code];
} // end try
catch (IndexOutOfRangeException e)
{
Console.WriteLine("invalid code length");
Console.WriteLine(e.Message);
}
catch (FormatException e)
{
Console.WriteLine("code NOT numeric");
}
}
}
}
35
Exception Handling – When to use – Best Practice
The method to choose depends on how often you expect the event to occur.
• Use exception handling if the event doesn't occur very often, that is, if the event is
truly exceptional and indicates an error (such as index out of range). When you use
exception handling, less code is executed in normal conditions.
• Check for error conditions in code if the event happens routinely and could be
considered part of normal execution. When you check for common error conditions,
less code is executed because you avoid exceptions.
For conditions that are likely to occur but might trigger an exception, consider handling
them in a way that will avoid the exception. For example, if you try to divide a number by
zero, you'll get a DivisionByZeroException. You can avoid this by using an if
statement to check the divisor before trying to do division.
// two approaches
// alternative
try // using exception handler to deal with problem if it occurs
{
ans = a / b;
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.GetType().FullName);
Console.WriteLine(ex.Message);
}
36
Chapter 6 File Handling
Up to now all data that our programs have been working with has come directly from the
console or we have printed it to the console. When the execution of the program is finished
all data is lost. This is not always what we want, we may wish to have a record of the results
of our program or wish our program to take its data from a source other than the user.
Most applications will have this requirement. Just think of every time you go to an ATM,
you will enter some data directly, for example your PIN, but all your details like your bank
balance will be retrieved from some storage device that the bank is using, also when your
transaction is completed the ATM will want to have a record of the transactions and to
update your account, e.g. amend your balance.
We have a number of options as to how we might want to store this data, each has its own
merits and disadvantages. For example:
Over the coming years we will explore many of this techniques, but this year we will
concentrate on working with files:
37
File handling : Example1
Let’s write a program to read the first line of text in a file stored on the debug folder of a
project called messages. This file will have been created using a simple text editor like
NotePad.
Steps
1. Create a FileStream object that connects to the file
2. Create a StreamReader object to allow us read from the
stream
3. Read first record
4. Display record
5. Close the stream
// open connection
FileStream fs = new FileStream("products.txt", FileMode.Open,
FileAccess.Read);
inputStream.Close();
38
File handling : Example 2:
Let’s write a program to read in all the lines of text in a file stored in the debug folder called
messages
The ReadLine() method returns null when the end of file is reached. This will act as a
sentinel value to tell us to stop reading
Steps
string lineIn;
inputStream.Close();
39
Working with Comma Separated Value (CSV) files
A Comma Separated Values (CSV) file is a plain text file that contains a list of data. These
files are often used for exchanging data between different applications
These files may sometimes be called Character Separated Values or Comma Delimited files.
They mostly use the comma character to separate (or delimit) data, but sometimes use
other characters, like semicolons. The idea is that you can export complex data from one
application to a CSV file, and then import the data in that CSV file into another application.
For example an excel spreadsheet can be saved as a CSV file.
That’s all a CSV file really is. Some CSV files may have a headers at the top describing the
fields, they can contain thousands of lines and lots of entries on each line
Each line is often referred to as a record and the parts of each line the fields
It’s this simplicity of CSV files that allows us use them to easily export data and import it into
other programs.
40
// Program to read in all employees from the CSV file employee.txt
// print each employees details to a report
// calculate the total of all salaries paid
// calculate the average salary
// print total and average salary
// open connection
FileAccess.Read);
// print heading
Console.WriteLine("Employee Report");
Console.WriteLine($"{"Name",-10}{"Email",-10}{"Address",-
10}{"Salary",-10}");
// report body
{
fields = lineIn.Split(','); // split input where ',' is
count++;
Console.WriteLine($"{fields[0],-10}{fields[1],-10}{fields[2],-
10}{fields[3],-10}");
// report footing
Console.WriteLine($"Total = {totalSalaries}");
Console.WriteLine($"Average = {avgSalary}");
inputStream.Close();
}
41
42
Chapter 7- Object-Oriented Programming (OOP)
Object-Oriented Programming (OOP) is the term used to describe a programming approach
based on Objects and classes.
The object-oriented paradigm (fancy word for model) allows us to organise software as a
collection of objects that consist of both data and behaviour (methods).
In many ways it is modelling how things (objects) like humans, vehicles, animals, etc. act in
the real world.
For example you are an object of type human, you have data (your name, address, height,
skin colour etc.) and you have behaviours, like walk, talk, sit, jump, etc.
• What kind of data and behaviours might a tank object have if you were programming
a game?
So all the related data and methods are packaged together – when you think about it this
makes a lot of sense.
This is in contrast to the functional programming practice that only loosely connects data
and behaviour.
The move towards oop started in the 1980s, with almost all languages developed since 1990
having object-oriented features. Some popular languages have been re developed with
object-oriented features, e.g. object oriented Cobol – my first programming language!.
It is widely accepted that object-oriented programming is the most important and powerful
way of creating software and from this point forward all your programs will be fully object –
oriented. (up to now, our programs are a bit of a hybrid, our code has been written in a
functional style but we have been making use of classes and objects which are part of c#, for
example we have used the StreamReader class when file handling)
43
Classes
You can think of a class as a template or blueprint of something. That something might be
A student
A car
A bank account
A bicycle
An employee
A weapon
In the case of say, an Employee, it will have certain features (attributes) that all Employees
have:
o Name
o Gender
o HourlyRate
o Employee Number
Employee data will also have certain tasks (behaviours) associated with it e.g.
o Calculate Pay
o Calculate Tax
o Calculate Bonus
______________
44
Components of a class
We capture all of these attributes and functions in a class.
Deciding in what modifier to use is very dependent of the requirement of the class – how
you want it to be used, though generally classes tend to be public, attributes private and
methods public.
45
Objects
An object is an instance of a class, you could think of it as a variable. For example
// open connection
FileStream fs = new FileStream("products.txt", FileMode.Open,
FileAccess.Read);
This is creating an object of the FileStream class, we could create as many of these as are
needed:
// open connection
FileStream fs2 = new FileStream("products.txt", FileMode.Open,
FileAccess.Read);
Example of a Class :
Let’s look at an example of a class, with a single attribute, _name , two constructors. It has
one method PrintName()
class Employee
{
private string _name; // the name field
//default constructor
public Employee()
{
//parameterised constructor
public Employee(string n)
{
_name = n;
}
//method
public void PrintName()
{
Console.WriteLine("$Name is {_name}");
46
Working with Objects
An employee of a company is an instance an Employee, it has a name of Mary
class Program
{
// program to test our class
static void Main(string[] args)
{
Employee myEmployee; // declares an object of type Employee
myEmployee = new Employee(); // create an object of type employee
myEmployee.Name = "Mary"; // set the name of this employee to “Mary”
myEmployee.PrintName(); // call to the PrintName method
}
}
47
What the heck is going on?
Employee myEmployee;
myEmployee
null
A class provides the instructions to C# as to what is to be made, and what it can do. The new
keyword causes C# to use the class information to actually make an instance. We have seen
this keyword new before. We use it to create arrays. This is because an array is actually
implemented as an object, and so we use new to create it.
The thing that new creates is an object, an instance of a class.
Employee
myEmployee
myEmployee._name = “Mary”;
myEmployee Employee
_name : Mary
48
Constructors
A constructor is a special kind of method that is automatically called when an object is
created, this occurs when the new keyword is used. They normally perform initialisation or
setup operations such as storing initial values in attribute fields.
They are called constructors because they help construct an object
They have no return type (no need to use void) and must have the same name as the class.
Normally you will have a default constructor, this has no parameters and at least one other
constructor with 1 or more parameters.
You could think of a constructor as the piece of code that gives birth to the object. The
default constructor gives birth to an object where we know nothing about its attributes yet.
(we may set them later on)
Employee myEmployee = new Employee();
Whereas with a parameterised constructor, we know some of the attributes values at the
time of birth,
myEmployee2 Employee
_name : Pat
We can have any number of constructors with different parameter lists, we call this
overloading. The constructor that we use will be dynamically selected at run time based on
the parameter list we use.
49
Properties – Accessors and Mutators
These are special methods that are used to the return (get) attributes and also change (set)
attributes of an object.
They combine aspects of both attributes and methods. To the user of an object, a property
appears to be an attribute, accessing the property requires the same syntax as you would
use if using an attribute.
To the implementer of a class, a property has one or two code blocks, representing get
accessor and/or a set accessor.
• The code block for the get accessor is executed when the property is read.
• The code block for the set accessor is executed when the property is assigned a new
value.
• A property without a set accessor is considered read-only.
• A property without a get accessor is considered write-only.
• A property that has both accessors is read-write.
• Unlike attributes, properties are not classified as variables. Therefore, you cannot
pass a property in method calls.
Properties are declared in the class block by specifying the access level of the field, followed
by the type of the property, followed by the name of the property, and followed by a code
block that declares a get accessor and/or a set accessor. For example:
50
The Get accessor
class Employee
{
private string _name; // the name field
public string Name // the Name property
{
get
{
return this._name;
}
}
}
class Program
{
// program to test our propery
static void Main(string[] args)
{
Employee myEmployee; // declares an object of type Employee
myEmployee = new Employee(“Mary”); // create an object of type employee
with the name Mary
Console.WriteLine($"Name is {Name}"); // the get accessor is invoked
}
}
51
Here is an example where the get accessor includes a code check to make sure the name is
not pointing at null, if it is it return the text “na”.
class Employee
{
private string name;
public string Name
{
get
{
if (name != null) // if set to something
return this.name;
else
return "NA";
}
}
}
class Program
{
// program to test our propery
static void Main(string[] args)
{
Employee myEmployee; // declares an object of type Employee
myEmployee = new Employee(); // create an object of type employee
Console.WriteLine($"Name is {Name}"); // the get accessor is invoked
}
}
52
The Set accessor
The set accessor resembles a method whose return type is void. It uses an implicit
parameter called value whose type is the type of the property. In the following example, a
set accessor is added to the Name property.
class Employee
{
private string _name; // the name field
public string Name // the Name property
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
}
class Program
{
// program to test our class
static void Main(string[] args)
{
Employee myEmployee; // declares an object of type Employee
myEmployee = new Employee(); // create an object of type employee
myEmployee.Name = "Mary"; // set the name of this employee to “Mary”
Console.WriteLine($"Name is {Name}"); // the get accessor is invoked
}
}
53
Note that the set accessor could include code to check the value is appropriate before being
set
Example : Using the set accessor to check an employees name before setting, in this case
let’s assume we don’t want any employee with the name Frank (sorry Frank!)
class Employee
{
private string _name; // the name field
public string Name // the Name property
{
get
{
return this._name;
}
set
{
if (value != "Frank")
_name = value;
else
this._name = “na”;
}
}
}
class Program
{
// program to test our class
static void Main(string[] args)
{
Employee myEmployee; // declares an object of type Employee
myEmployee = new Employee(); // create an object of type employee
myEmployee.Name = "Frank"; // set the name of this employee to “Frank”
Console.WriteLine($"Name is {Name}"); // the get accessor is invoked
}
}
54
Auto-implemented property
public Employee()
{
lastEmployeeNumber++;
employeeNumber = lastEmployeeNumber;
}
55
The Object class
In C#, every class is actually a sub class of a very important class, called the Object class. The
Object class has a number of methods that are made available to all other classes.
It is good practice to write one of these methods for each of our own classes, and let ours
override (replace) the base method. Typically it will return a string with all/some of our
objects attributes.
For example, our employee class might include the following replacement ToString()
method.
Not the use of the word override, this tells our method to override the ToString()
method of the base class.
56
Example : Here is a complete example of a program that uses a class
Attributes : name, gender, hourly rate and employee number
Methods : CalcPay and ToString
/*
# Author VK
# This class represents a blueprint of an employee with four attributes and two
# methods
*
*/
class Employee
{
// attributes
private string _gender;
private string _name;
private int _employeeNumber;
// Name property used to get and set the name attribute of an object
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
// Gender property used to get and set the gender attribute of an object
public string Gender
{
get
{
return _gender;
}
set
{
_gender = value;
}
}
57
// HourlyRate property used to get and set the hourly rate attribute of an object
// here i am using an auto-implemented property
// auto-implemented properties make property-declaration more concise when no
// additionallogic is required in the property accessors. When you declare a
// property as shown in the following example, the compiler creates a private,
// anonymous backing field that can only be accessed through the property's get and
// set accessors.
public double HourlyRate { get; set; }
// EmployeeNumber property used to get and set the employee number attribute of an
object
public int EmployeeNumber
{
get
{
return this._employeeNumber;
}
set
{
_thhis._employeeNumber = value;
}
// Default construct
public Employee()
{
lastEmployeeNumber++; // increment the static variable by 1
EmployeeNumber = lastEmployeeNumber; // assign to the employee number
attribute
}
//parameterised constructor
public Employee(string n, string b, double p)
{
Name = n;
Gender = b;
HourlyRate = p;
lastEmployeeNumber++; // increment the static variable by 1
EmployeeNumber = lastEmployeeNumber; // assign to the employee number
attribute
}
// Method tp print the attributes of an object
public override string ToString()
{
return "Name: " + Name + " Gender : " + Gender + " Rate : " + HourlyRate +
" Employee # : " + EmployeeNumber;
}
}
}
58
// program to make use of our Employee class
class Program
{
static void Main(string[] args)
{
// code to test our classes
Console.WriteLine($"Pay = {employee.CalcPay()}");
}
}
59
Inheritance
With classes and objects we have seen that we can very neatly package the attributes and
functionality of real world objects.
This is great because it allows to manage complex solution (divide and conquer) plus we can
reuse our classes in loads of applications.
For example, if we were developing a new game we can reuse a previously written weapon
class or in a new payroll system we can reuse our Employee class.
There might be situations where we want to reuse a class, but slightly modify its attributes
and/or functionality. Oh-no, does this mean we can’t reuse our class? The great news is, yes,
we can make use of our existing class. Inheritance to the rescue!
When creating a class, instead of writing completely new attributes and functions, the
programmer can designate that the new class (the child or subclass or derived class) should
inherit the members of an existing class (the parent or superclass or base class).
Consider the case of our Employee class, if we were now to consider Part time employees,
all these will have the same characteristics as an Employee but in addition they will have a
number of hours worked attribute and a modified CalPay() method, where their pay is
calculated based on the number of hours they have worked. (rather than 40 for all
employees)
(We can view our Employee class as a generalisation – think what characteristics do all
employees have (regardless of being full or part time)?
60
Base and Derived Classes
A class can be derived from more than one class , which means that it can inherit data and
functions from multiple base classes or interfaces.
In our example the base class is the Employee and its derived class is the PartTimeEmployee
class
61
Initializing Base Class
The derived class inherits the base class member variables and member methods. Therefore
the super class object should be created before the subclass is created.
{
private int _hoursWorked; // this is the new attribute for part time
employeess
public int HoursWorked {
get
{
return _hoursWorked;
}
set
{
_hoursWorked = value;
}
}
_hoursWorked = hrs;
}
public override string ToString() // note that this over rides(replaces) all
super level toString methods
{
62
Program to test our use of inheritance
63
Chapter 8: Miscellaneous
One of the great things about classes is that we can re-use ones that Microsoft has created
for us in the .net library. One useful class for games and simulation is the Random class.
The Random class constructors have two overloaded forms. It takes either no value or it
takes a seed value, i.e. a number used to calculate a starting value for the pseudo-random
number sequence.
The Random class has three public methods- Next, NextBytes, and NextDouble.
• The Next method returns a random number, The Next method has three overloaded
forms and allows you to set the minimum and maximum range of the random
number.
• NextBytes returns an array of bytes filled with random numbers, and
• NextDouble returns a random number between 0.0 and 1.0.
Some Examples:
The following code returns a random number between min and max:
64
Using a seed value
Providing an identical seed value to different Random objects causes each instance to
produce identical sequences of random numbers.
If your application requires different random number sequences, invoke this constructor
repeatedly with different seed values. One way to produce a unique seed value is to make it
time-dependent. For example, derive the seed value from the system clock.
Lists are like arrays but much easier to use, for example list elements can be accessed using
square brackets like arrays. Lists are not restricted in size, so we can keep on adding things
without worrying.
To use lists we just need to include the using directive at the top of our programme.
using System.Collections.Generic;
We can then declare a list of objects of a class we’ve already written e.g. employees:
List<Employee> employees = new List<Employee>();
We can then add employees to our list once we have them created as before e.g..
Employee employee = new Employee(“Sarah”);
Employees.Add(employee);
65
To think about.
We need a program to compute till receipts as follows:
TOTAL 9.10
Hint : A Sale is made up of a sale number, a List of ItemLines, and a payment method. Here
we can have two classes – an ItemLine class ( with attributes item (string), quantity(int) unit
price(decimal) and a method to CalculatePrice) and a Sale class (with the attributes sale
number (int), items (a generic list of ItemLine) and methods to AddItem and
CalculateTotal).
66
Chapter 9 - Software Design Fundamentals
When we move beyond simple problems, our code can get very messy. Fortunately all programming
languages give us ways to break our problem down into smaller pieces. Learning how to do this is a
fundamental skill for software developers.
The basic idea is just like Lego - we build software systems out of smaller components, often
called modules.
“Module’ is a general term that can be used to describe any relatively independent software
component. This year we’ll mainly focus on two types of module:
• Methods and
• Classes, which group methods round the data they need.
These give us a way to divide our software into smaller pieces that are easier to reuse and
test.
If we name our modules clearly and carefully, following standards, this will also help us
write clean code that is easy to change and maintain.
Methods
When we write methods we need to be clear about
(i) what goes in
(ii) what comes out
(iii) what value(s) might be changed as the method is executed.
67
Naming methods and parameters clearly and consistently can make our code readable and
clear.
For example, in a Bank Account Class we might have a method to lodge some money, for
example:
Note that the job done is to add the amount to the bank balance, which will be changed as a
result.
68
Recap: Using Classes and Methods as Building Blocks to Solve Problems
Classes group methods round data and can be used to model real world entities or objects (
e.g. bank accounts, employees) or things that can be generally useful in programming e.g.
user interface components (Windows, Buttons), random numbers, lists, or even things that
might help create a game (sprites). We can think of these as building blocks that we can
test, adapt and reuse.
• Be clear about the role of each class. Name it by what it represents. Make sure it has
the properties and methods it needs.
• Be clear about the distinct role of each method: the job it does, what data it needs to
do that job (arguments, parameters), and what is returned (if needed). Give the
method a name that closely describes what job it does.
69
70
71