Programming Fundamentals
Programming Fundamentals
Dan Gilleland
Buy on Leanpub

Table of Contents

Who is this book for?

To-Do:

  • Talk about the intended audience (first-term programming students)
  • What are LOGs
  • Instructor’s Guide (a future book)

The ABCs of Programming with Objects

An “Objects-First” Introduction to Programming

Learning how to program is a journey into thinking about things and how to manipulate them. For a long time, most instructors and teachers who’ve taken up the challenge of teaching programming have done so with a focus on the manipulations and less concern with the things the program represents. This procedural mindset has been the way many of us (myself included) learned programming in the first place. The problem with this mindset, however, is that “real” programs haven’t been written that way for decades now.

Object-Oriented Programming (OOP) has been around for a long time, but it can be hard to adjust one’s approach from a procedural mindset to become comfortable with OOP. This book aims at offering a way to teach programming starting with OOP, rather than tacking it on at the end. Through simple examples, and a focus on the things first, this book will guide the student (and the teacher) through numerous examples that introduce all the concepts needed to get started in programming with Objects.

The essence of this OOP-First approach are seen in what I call the “ABCs of Classes and Objects”. From these first three topics I move to the “traditional” concerns of programming, all the while placing them within their most natural context: Objects.

Topic A

This topic is the first of a three-part introduction to object-oriented programming. The focus of this first part is to introduce classes and methods. This topic does not go beyond the use of static methods in a class.

Introduction

The purpose of this topic is to introduce the class as the central piece of modern computer programs. A computer program is “a set of instructions for manipulating information.” Notice the two key elements of a computer program: Instructions and Information. A class is a kind of template that groups together data (information) and instructions for manipulating that data.

Manipulating information is done through something called “methods”. A method is basically a set of instructions that has an overall name (method name). Methods cannot exist on their own; methods must exist in a “context”, and the context for all methods is the class. Methods are where programmers tell a computer “what to do.”

Every computer program has one important method that is the entry point or starting point for running the program: main. The main method must be publicly available in order for the operating system to be able to run the program.

Topic B

The focus of this second part is to show how classes act as templates for creating objects. This topic limits itself to showing a) how to create (instantiate) objects using classes and b) how classes can be used to describe what an object “looks like”.

Introduction

The purpose of this topic is to show how classes don’t just “contain” methods: Classes act as templates for defining complex types of information (objects). In fact, a class can almost be thought of as a “mini-program”, because a class brings together the two key elements of every program: Instructions and Information. With classes, we can create objects that do what we want them to.

The class is the basic building block for creating objects. As a template, a class describes
a) What an object “looks like” (that is, what information is inside the object), and
b) How an object “works” (that is, what instructions an object can perform on data).

This topic focuses on the first part – describing what an object “looks like” – by introducing fields and exploring the idea of object state.

Topic C

The focus of this third part is to show the concepts of encapsulation and information hiding as well as good object design by creating private fields and introducing public getters/setters and constructors.

Introduction

The purpose of this topic is to highlight how a major responsibility of every class is to “protect” the data within the class. This is done by designing classes that only use private fields and that “expose” access to the values of those fields through getter and setter methods. Getters and setters provide a way for the programmer to control access to fields in an object and to ensure that the fields are “used correctly”.

(Note: Later topics will address how to write code that tests the values coming through the setters’ parameters to ensure that only “acceptable” values are allowed into an object’s fields.)

This topic also covers the important role of constructors in ensuring that objects have a “stable state” at the moment that they are created. In other words, constructors are responsible to ensure that all of the fields in an object are filled with “meaningful” values. A constructor also forces other code to supply required information when creating (instantiating) an object based on that class. Constructors are the “first line of defense” for ensuring that objects are created properly.

Thinking In OOP

What is a Computer Program

Introduction

What is a computer program? A computer program is basically a set of instructions for manipulating information. To be of any value, the information used by a computer program must have a way to get into the program (input) and get out of the program (output). That may sound too simplistic, but ultimately it is entirely accurate; even the most sophisticated computer program can do nothing more than process information (albeit, in a very fast and efficient way), and no matter how cool the program looks, if there is no way to put information into it and get information out of it then it’s not of much use to anyone.

The most familiar kind of input and output (or I/O) in a computer program comes from the user. Textual information is entered (input) from the user via the keyboard and displayed (output) to the user via the monitor. Other means of user I/O can include computer mice, microphones, speakers, printers, fax machines, Braille readers, touch screens, stylus, etc.

Besides handling user I/O, computer programs can also do file or database I/O. Computer files and databases allow information to be persistent. Information is said to be persistent when it can be stored outside of the computer program and later retrieved for further processing. The combination of a) user I/O, b) fast and accurate processing, and c) persistent information storage is what makes computer programs so useful.

Variables, Values and Data Types

”… manipulating information.”

At the heart of all computer programs is the idea of information or data. This is especially true in Object-Oriented Programming languages. With information being such a critical component of computer programs, it’s important to understand what we mean by information.

It’s All About Information

Since computer programs are all about handling information, it is important to understand something about the different kinds of information programs deal with. Essentially, most information falls into one of the following categories:

  • Numeric information (e.g.: a person’s age or the price of a vehicle)
  • Textual information (e.g.: the title of a book)
  • Conceptual information (e.g.: truth - whether a statement is considered true or false)

These different kinds of information can be said to be primitive. They represent the most basic kind of data that today’s computer programs have to deal with. These three kinds of information can be further subdivided into fundamental data types:

Category of Information Basic Data Types
Numeric Integer - whole numbers
Real - numbers with fractional components
Currency - numbers representing monetary values
Textual Character - a single letter or symbol
String - a set of characters (with or without spaces)
Conceptual Boolean - true/false, yes/no, on/off

Any meaningful handling of information requires the understanding of three related (but distinct) concepts: variables, values, and data types.

In order for a computer program to manipulate information, it needs a way to hold or refer to information. This is the concept of a variable. A variable is a name or identifier used to refer to a single piece of information. It acts like a container that allows a program to refer to a piece of information indirectly, without being dependent on the exact content of that information. One analogy is that a variable is like a cup: a cup can be used to hold different kinds of liquids (water, juice, or even motor oil). The cup is independent of the liquid (the cup can even be empty), but it provides an effective way of working with a liquid (for example, measuring the amount of water used in a recipe).

Besides the idea of a variable that can hold information, there is the concept of a value. Unlike a variable (which is only used to refer to a piece of information), a value is the specific information contained in a variable. Returning to the previous analogy of a cup, a value is like the specific liquid inside the cup (variable). What does a particular cup hold? Is it water or motor oil? The cup is not what’s really important; what’s important is what is in the cup (especially if you are making a recipe!).

The final concept is one that has already been alluded to: the idea of a data type. A data type refers to the kind of information that a variable can hold. For example, the kind of material that a cup is designed to hold is a liquid. The description “liquid” is a description of the type of content that the cup can hold. A plate, on the other hand, is designed to hold a different kind of material - something that is solid (such as a steak or chicken cordon bleu). More specifically, the “data type” that a plate is intended to hold is “food” and steak would qualify as a type of food while motor oil would not. Notice that the concept of data type (e.g.: “food”) can be applied to both the variable (plate) and the value (steak).

This brings up an important consideration: The data type of a variable should be appropriate for the kind of information the variable is intended to hold. There is a close relationship between variables, values and data types, even though those three ideas refer to different things. Cups are used to hold liquids; plates are used to hold food; and a balloon is used to hold a gas. It would be entirely inappropriate (if not impossible) to use a balloon to hold a piece of cake! Using these analogies, the concepts of variable, value and data type can be clearly distinguished:

Variable Value Data Type
Cup Orange Juice Liquid
Plate Black Forest Cake Food
Balloon Helium Gas

Returning to the way these concepts are used in a computer program, the following table gives some examples of variables and values for the data types fundamental to most high-level programming languages.

Variable Value Data Type
Age 25 Integer
PI 3.14159 Real
Cost $4.95 Currency
Gender ‘M’ Character
Title “Computer Basics 101” String
Success True Boolean

Rules About Variables, Values and Data Types

It has been stated that while variables, values and data types are distinct concepts, they are closely related. This close association between these concepts allows us to work with and manipulate information. Before we can begin working with these concepts in a simple program, however, we need to establish some basic rules about how to work with variables, values and data types.

The first rule has already been alluded to in the previous section: The data type of a value must match the data type of the variable that stores the value. This rule is closely related to a second rule: A variable and its data type must be declared before the variable can be used. Whenever a variable name is first identified in a computer program, the data type of the variable must be declared. Stating, or declaring, what the data type of a variable is will allow a computer program to know two things:

  • How much computer memory must be set aside for the variable’s value.
  • How to interpret a value stored in a variable.

A variable cannot be used until it is declared, and once a variable’s data type has been identified it can only hold values that match that data type. For example, if a variable called Status has been declared as a character, then it can only hold a character value (such as ‘T’ or ‘5’). Any attempt to store a value of a different type (such as “Temporary”) in Status would produce an error in the computer program.

A third rule that is related to the second is that once a variable’s data type has been declared, its data type cannot be changed.1 This is because a variable’s data type tells the computer how to interpret the variable’s value (e.g.: is it a character or a number?), and any attempt to change the data type would result in a misinterpretation of the previously stored value.

Another rule is that each primitive variable in a computer program can only hold a single value at any given moment in time. The reason for this rule is so that the computer knows what value to supply when a variable is used in the program. In fact, when a primitive variable’s data type is declared, the computer sets aside enough memory to store only one value - no more! If a new value is stored in the variable, then any previously stored value is lost. This also gives an advantage to the programmer - it is easier to plan for and test a computer program if you can predict what value will be stored in the variable. Since a variable can only hold one value at a time, it is not unusual for a computer program to use many variables.

Notice that this last rule applies to variables with primitive data types. Often, computer programs allow the creation of more complex data types, such as classes and arrays. The rule of a variable storing only one value changes slightly for these complex types. In the case of classes, one variable whose type is based on a class can only store one object (even though the object might be complex and hold many values). Likewise, a variable that refers to an array can only refer to one array (even though arrays can hold many values). These complex data types will be discussed in a later lesson.

Lastly, in order for a computer program to distinguish one variable from another, each variable (in a given scope) must have a distinct name. If two variables were given identical names, then the computer would not be able to tell which variable to use in a given calculation. By giving each variable a different name, it is easier for both the computer and the programmer to keep track of which ones to use.

Notice, however, the qualification to this rule: in a given scope. In general, scope refers to the context in which a variable is used. If two variables are used in two different contexts, then it is permissible to use the same variable name because the computer uses the different contexts to tell them apart (similar to how two people can have the same first name but be distinguished from each other if they have different last names). An obvious (and trivial) example of this is if a variable called Age is used in two different computer programs, then the computer can tell which variable to use because it knows which program it is currently running. Usually, the term scope is used to refer to distinctly different contexts within the same computer program. The idea of scope will be discussed in more detail later. To begin with, most of the programs will be fairly simple and will only have one scope, so it is fair to simplify this rule as each variable must have a distinct name.

In summary, the basic rules for variables, values and data types are:

  • Any value stored in a variable must be of the same data type as the variable.
  • Variables must be declared before they can be used.
  • A variable’s data type can only be declared once.
  • Each primitive variable can only hold one value at a given time.
  • Each variable must have a distinct name.

Programming Languages and Coding Instructions

”… a set of instructions …”

What Programmers Write

Programmers write code in plain-text files known as source files. The language that a programmer use to write code is called a programming language. Just as with human languages, there are many different programming languages. Some examples of modern programming languages are C# (the language used in this book), Java, Visual Basic .Net, SQL, and JavaScript. In addition, many other programming languages have been developed over the years such as Python, Lisp, Fortran, Cobol, Haskell, C, C++, and many more.

Each programming language defines their own words (called keywords), punctuation and grammar rules (or syntax). And like human languages, programming languages typically promote certain “world-views” or perspectives on how code should be written. Some languages emphasize the steps involved in manipulating information (a Procedural perspective). Others put the emphasis on the information itself (as in most Object-Oriented programming languages).

In all cases, programming languages allow us to write instructions that manipulate *data. Through variables, a computer program has the ability to manipulate the values stored in those variables. This manipulation of stored information is accomplished by giving the computer specific instructions on what manipulations to perform.

What Computers “See”

Programming languages allow programmers to give instructions to a computer in a form that is more familiar to and easier to use by the programmer. Today’s programming languages are known as high-level languages because they incorporate simple words with familiar meanings in English, such as if, else, while, do, and return. Low-level languages, such as Assembler, use more cryptic commands and are much closer to machine language, thereby making them harder for programmers to work with.

The exact form that the instructions will take depends on the programming language that is used. These instructions are then examined by a special program (a compiler, an assembler, or an interpreter) and translated into machine language. Machine language consists of a series of ones (1) and zeros (0) which act as on and off switches in the computer’s memory. These on and off switches change other information that is stored in memory, resulting in the manipulation of information.

The on and off switches in computer memory represent the flow of electricity through the computer. Millions and billions of these switches (also known as “gates” - no relation to Bill) are arranged on tiny computer chips in highly sophisticated patterns to allow for the organized flow of electricity. It is this organized flow of ones and zeros that allow us to use these machines for fast and efficient information processing.

Doing the Math

High-level programming languages (such as C++, C#, and Visual Basic) make it relatively easy to manipulate the values of variables. Assignment statements tell the computer to store specific values into specific variables. Assignment statements are often used with expressions, which are combinations of variables, values, and/or operators (such as Arithmetic operators). It is through expressions and assignment statements that the bulk of a computer’s work is done.

Expressions allow new values to be computed based on existing values. For example, if a variable called Cost has the value $5.95 and another variable called Markup has a value of 2.0, then a mathematical expression such as Cost * Markup can be used to create a new value - $11.90 (the Cost multiplied by the Markup value). Using this expression in an assignment statement, this resulting value of the expression can then be stored in another variable:

Price = Cost * Markup

All numeric information can be used with the common arithmetic operators of addition, subtraction, multiplication, and division. When combined to create complex expressions, the commonly accepted rules of mathematics are used to determine which operations should be used first (multiplication and division before addition and subtraction). The order of operations can be modified by using parentheses, as in regular mathematics.

Some arithmetic operations, such as calculating the remainder of a division operation, are only applicable to certain types of numeric information. Some languages supply a special symbol to represent these operations while other languages require the use of special library functions to perform the math. Complex arithmetic operations, such as calculating the sine of an angle, are typically done using library functions. Library functions are simply specialized routines or sets of instructions that can be called upon to do the required calculations.

The following chart summarizes key arithmetic operations and their corresponding symbols as used in the more common high-level programming languages. The chart also shows some of the more complex operations and the names of the library functions used to calculate them (for specific details on using functions, see the documentation for the corresponding language).

Comparison of Arithmetic Operators in different Programming Languages;class:table
Arithmetic Operation Symbols / Function Calls        
  C++ C# JavaScript Visual Basic SQL
Addition + + + + +
Subtraction - - - - -
Multiplication * * * * *
Division / / / / /
Remainder of Division % % % Mod MOD(Division Expression)
Square Root sqrt( ) Math.Sqrt( ) Math.sqrt( ) Sqr( ) SQR( )
Exponential Notation (Power) pow( ) Math.Pow( ) Math.pow( ) ^ POWER( )
Sine sin( ) Math.Sin( ) Math.sin( ) Sin( ) SIN( )
Cosine cos( ) Math.Cos( ) Math.cos( ) Cos( ) COS( )
Tangent tan( ) Math.Tan( ) Math.tan( ) Tan( ) TAN( )
Parenthesis (affects order of operation) ( ) ( ) ( ) ( ) ( )

The only “arithmetic” operation that is typically applied to string data types is addition. The addition of two strings is usually interpreted as the concatenation (joining together) of the two string values into a single string value.

Besides performing assignment statements and expressions, programming languages have instructions that allow the program to control which instructions to perform and which ones to skip over. These control statements allow for performing mutually exclusive instructions (this or that) and for performing certain instructions repeatedly. High level languages also incorporate mechanisms to identify sets of instructions as particular groups or functions as well as ways to call these program-defined functions whenever they are needed.

Summary

Information comes in various forms and programmers can create both simple and complex sets of instructions to manipulate that information. Successful computer programs combine the best techniques for user I/O, information processing, and persistent storage in order to meet the needs of individuals and businesses. Grasping the basic concepts of computer programs - variables, values, data types, I/O, assignments and expressions, and control statements - is fundamental to the efficient and effective development of computer software.

The C# Language

C# (pronounced ‘See-sharp’) is a programming language developed by Microsoft and rooted in the earlier languages of C and C++. It is an Object-Oriented programming language that has evolved quite a bit over time, with each released version adding new features and capabilities to the language. At present, C# is in version 6.0 and version 7.0 is under development. Like every programming language, however, it must allow us to hold information and provide sets of instructions to manipulate that information.

Data (information) is held inside of variables. The following keywords represent the commonly used built-in data types for the general categories of primitive information.

Category C# Data Type
Whole numbers int long short byte
Real numbers double single float
Text char string
Conceptual boolean

Instructions are always placed inside of methods. In fact, a method can be defined as a named set of instructions. Methods can never exist all on their own; they have to be placed inside of some kind of context (or scope), and they are typically placed inside of classes. Classes, themselves, are one of the main means by which we can declare complex data types (which, in turn, can be used to declare objects designed to hold and process sets of data).

Where are variables placed in our program? Variables can appear inside of classes (where they are sometimes called member variables) and inside of methods (where they are called local variables). As we will learn later, the location of the variable defines its scope, and that scope will determine when and where the variable can be used.

If you are beginning to imagine a lego-like structure to the C# programming language, then you are on the right track! We can code classes that hold variables and methods. The classes themselves are new data types which can be used for for creating complex variables (objects). This characteristic of providing keywords for primitive data types along with a means to combine them into more complex data types is called type extensibility. You can think of it in this way: primitive data types are like chemical elements in the periodic table, while complex data types (which we design ourselves) are like molecules made by combining elements. While this analogy has its limits in describing the nature of C#, it does provide a good starting point in understanding how the language is designed.

The Main Method

Speaking of starting points, it’s important to note that every computer program needs a place to start. When we run a computer program, we are telling the operating system (OS) to start running the instructions in the program. That’s why every program needs a starting place - a place (method) where the computer can begin executing the program’s instructions. For C# (like many other languages), that entry point is traditionally called the Main() method.

Let’s look at an example. The following code is a complete program that performs a simple task - displaying the text “Hello World” in a console window.

1 public class MyFirstProgram
2 {
3     public static void Main(string[] args)
4     {
5         System.Console.WriteLine("Hello World");
6     }
7 }

The name of the class is MyFirstProgram and it contains only one method - Main - which is the starting point of the program. That method contains a single instruction telling the computer to display the text “Hello World” to the user.

Notice that besides the name of the class and the Main method, there are various keywords (in blue) and punctuation (such as curly braces { }, parentheses ( ), square brackets [ ], semicolons ; and “dot operators” .). All of these pieces have to be arranged according to the specific rules of the programming language. We call these rules the grammar and the arrangement of our code using the rules the syntax. You can learn more about some of the subtle distinctions between these two terms by searching online, but for now you can think of these words as being almost the same thing.

Syntax is the study of sentences and their structure, and the constructions within sentences. Syntax tells us what goes where in a sentence. Grammar is the general term referring to the set of rules in a given language including syntax , morphology, while syntax studies sentence structures. Apr 3, 2013 - by Googlebot

Order is important

The order in which we place our instructions within a method is important. All of the instructions are processed sequentially - one after the other. Look at this simple example:

1 public class PriceCalculation
2 {
3     public static void Main(string[] args)
4     {
5         double price = 12.95, total;
6         total = price * 10;
7         System.Console.WriteLine("The total price is " + total);
8     }
9 }

In the main method are three lines of code (lines 5-7) which run sequentially. If I change the order of these instructions, then the program won’t run correctly. In fact, changing the order might even violate part of the C# grammer, creating what’s called a syntax error, and the computer won’t be able to run the program at all!

Understanding the Grammar of a programming language is fundamental to knowing how that language works. Without that knowledge, our attempts to write code will quickly be filled with frustration. The next chapter examines the grammar of C#.

Summary

We’ve covered a lot of ground so far, and all of it is fundamental to writing computer programs in C#. To recap, you should now know that

  • Instructions are always placed inside methods (in fact, a method can be defined as a “set of instructions”).
  • Methods always appear inside of classes or similar structures.
  • C# provides keywords for primitive data types. We use these keywords to declare variables which hold values.
  • C# is an extensible language - allowing one to define new complex data types with their own information (variables) and instructions (methods) for processing that information.

A Simplified C# Grammar

A language grammar is a set of small rules that can be combined to produce a syntax.

The many small rules in the C# programming language is its grammar. These rules specify the accepted way to write C# code. Individually, each rule in itself is not enough to produce complete working code. Instead, the rules are like building blocks, offering various ways to assemble or construct your code.

Take, for example, some of the grammar around variable declarations and program statements. A simplified grammar for declaring a variable in C# would look like this:

* dataType variableName*

We would have to supply both a data type and a variable name to declare a variable. Thus, if we wanted to store a whole number to represent a count, we could use the int keyword and write the following:

int count

By itself, this variable declaration is not enough to produce a complete instruction in C#. We have to combine the variable declaration grammar with the grammar for a program statement in order to make a single instruction telling the computer to create the variable. In general, a program statement must be a statement that ends with a semicolon (;). In other words, the program statement grammar requires the semicolon as “punctuation”, much in the same way that English sentences must end in a period. Thus, our completed syntax for creating a variable would be

int count;

The formal grammar for C# is actually quite large and complex. In fact, the grammars for most programming languages are so complex that they require another “language” to describe the grammar. An early and fairly standard language or means to express grammars is the Bakus-Naur Form, or BNF.

For our purposes, we will present a much more simplified grammar. The following sections express the bulk of the C# grammar used in this introduction to programming fundamentals in C#.

Common Grammar Elements

Most of the grammar rules in C# are quite short, defining the order of keywords, identifiers and symbols. In the following grammars, the use of square brackets ([]) indicate an optional part of the syntax for the grammar rule; those square brackets are not actual symbols in the final syntax of the grammar. With each of the rules is a very brief explanation. Later chapters will go into more depth and provide examples of how to use these grammars.


Program Statements and Statement blocks

Individual instructions are known as Program Statements. The instructions can be short and simple, or they can be long an complex. In either case, the program statement must end in a semicolon (;). These individual instructions run sequentially, one after the other, so the order of individual instructions is important.

Besides individual instructions, we can group individual statements into Statement Blocks. A statement block is a set of zero or more program statements that are enclosed in a set of curly braces ({ }). Statement blocks are frequently used with Flow Control Statements (such as the if and for statements).


Variable Declarations

Before a variable can be used, it must be declared. Declaring a variable tells the compiler to

  • set aside room in memory to store information,
  • treat that data as a specific data type, and
  • refer to that information by the variable name

The grammar for declaring variables is as follows.

1 dataType variableName [= expression] [, ...]
A Variable Declaration defines a new variable where
dataType is any built-in or programmer-defined data type.
variableName is
an optional initial value may be assigned, as denoted by [= expression], where expression is any valid C# expression whose final data type matches the variable’s data type. When a variable is declared and initialized at the same time, it is called a Variable Initialization.
additional variable names (with or without initial values) can be declared using a comma-separated list. All variables are of the same data type as the first variable in the list.

Assignment Operation

1 variableName assignmentOperator expression
Assignment Operations are operations where a value is assigned or stored in a variable.
variableName is the name of the variable that will receive/store the value.
assignmentOperator is one of the following:
= Equals
+= Plus-Equals
-= Minus-Equals
*= Multiply-Equals
/= Divide-Equals
%= Modulus-Equals
expression is any valid C# expression whose final data type matches the variable’s data type.
An assignment operation is made into an assignment statement by adding a semicolon to the end of the operation. For example,
total = price * quantity;

Expressions

An Expression is any combination of literal values, variable names, operators (such as the arithmetic operators), and/or method calls (where the method returns a value). When an expression is processed by the computer, a single value is produced. This value can then be used in whatever operation the expressions occurs. For example, the value might be passed into a method as part of a method call, or it might be placed in a variable as part of an assignment statement.


Namespace Declaration and Using Statements

1 namespace Name
2 {
3     // Classes, enumerations, or other programmer-defined data types
4 }
A Namespace Declaration groups programmer-defined data types where
The Name of the namespace can be one or more dot-separated names. For example, the following are all valid names for namespaces.
System
System.Collections
MyGame
MyGame.GameRules

Namespaces are used to group classes and other programmer-defined data types into a single named group. The reason for grouping programmer-defined data types into namespaces is to prevent what are called “naming collisions”. A naming collision is where two or more classes or other programmer-defined data types are given the same name. In other words, you cannot have two classes named Circle in the same namespace. However, if you place those two classes in different namespaces, then that is acceptable because the compiler will then be able to distinguish between the two classes based on the namespace they belong to.

Whenever a class or other data type is placed in a namespace, that namespace becomes part of the fully-qualified name of the data type. For example, if a class named Circle is placed in a namespace called Geometry.Shapes, then the fully qualified name of the class is Geometry.Shapes.Circle.

Namespaces allow us to isolate our classes and other data types into groups. All of the classes/data types in a given namespace can automatically reference each other. To reference or use data types in other namespaces, we must either use their fully-qualified names or include them through the Using Statement.

1 using NamespaceName;

The using statement allows access to all the data types in referenced namespace. Using statements are typically placed at the beginning of a file. The NamespaceName is simply the complete name of the namespace that contains the classes or data types that we want to access.


Classes and Class Members

As an object-oriented language, classes play a very prominent part of the code we write in C#. It is within classes, for example, that we place variables (also called fields) and methods (which are “named sets of instructions”). One of the first things that classes give us developers is a context or scope for the code that we write. Classes are also building blocks, acting as blueprints for new and complex data types that we as programmers can create as we develop richer and more complex computer programs. Classes permeate all the code that we write in C# and are so fundamental that you can’t even write a “Hello World” program without them.


Class Definition

1 [accessModifier] class ClassName
2 {
3   // FieldDeclarations
4   // PropertyDeclarations
5   // Constructors
6   // MethodDeclarations
7 }
A Class Definition describes a new data type where
[accessModifier] is either public{format: csharp} or internal{format:csharp}. If no access modifier is provided, then the default modifier is internal{format:csharp}.
ClassName is the programmer-supplied name for the class (in TitleCase format)
FieldDeclarations, PropertyDeclarations, Constructors and MethodDeclarations are all optional and can appear in any order.
See the related grammars below to see how they are defined.

Field Declarations

1 [accessModifier] [static] dataType _FieldName [= constantExpression];
A Field Declaration identifies a static or instance member variable of the class where
[accessModifier] is either public{format: csharp}, private{format: csharp}, protected{format: csharp}, or internal{format:csharp}. If no access modifier is provided, then the default modifier is private{format:csharp}.
[static]{format:csharp} is an optional keyword. If present, the field is shared among all instances of the class. If absent (which is the common case) then the field is an instance member and one is created every time an object based on the class is created.
dataType is any built-in data type or the name of a programmer-defined data type.
_FieldName is a the name you give to the member variable. By convention, private fields are given an underscore as a prefix to the name.
constantExpression is an optional expression that generates data whose value can be determined at compile time. Being a constant expression does not mean that the field is a constant, only that the initial value stored in the field is a constant and can be known at compile time before the program runs.

Property Declarations

Properties are a kind of cross between methods and fields. On one hand, they are used in the same way that fields are. When you want to assign (or set) a value to a property, you place the property on the left side of the assignment operator. When you want to use (or get) the properties value, you simply reference the property name just as you would a field name.

Internally, however, the get and set operations are like the bodies of a method, where you can place instructions to retrieve or change the data in the class or object.

Explicitly Implemented Property

Explicitly implemented properties are properties where the programmer supplies the getter and setter implementations. The bodies of the getter and setter may reference a field (known as a backing store) that holds the actual information. In these cases, the property is working to provide a controlled access to the underlying field’s data.

In other situations, a property may merely have a getter where the body of the getter derives or calculates a value to return from some other source, such as a calculation.

 1 [accessModifier] [static] dataType PropertyName
 2 {
 3     get
 4     {
 5         // Body of getter
 6     }
 7     set
 8     {
 9         // Body of setter
10     }
11 }
A Property Declaration identifies a static or instance member of the class where
[accessModifier] is either public{format: csharp}, private{format: csharp}, protected{format: csharp}, or internal{format:csharp}. If no access modifier is provided, then the default modifier is private{format:csharp}.
[static]{format:csharp} is an optional keyword. If present, the Property is shared among all instances of the class. If absent (which is the common case) then the Property is an instance member.
dataType is any built-in data type or the name of a programmer-defined data type.
PropertyName is a the name you give to the member property.
Body of getter is a set of instructions that must ultimately return a value of the same data type as the property.
Body of the setter is a set of instructions that can process incoming data that is in the value{format:csharp} keyword. A typical implementation will store that data into the property’s backing store.

Autoimplemented Property

Autoimplemented properties are properties where the compiler takes care of the getter and setter implementations and also supplies a hidden field as the backing store for the property. The default get implementation is to retrieve the value from the backing store while the default set implementation is to place a value into the backing store.

1 [accessModifier] [static] dataType PropertyName { get; set; }
A Property Declaration identifies a static or instance member of the class where
[accessModifier] is either public{format: csharp}, private{format: csharp}, protected{format: csharp}, or internal{format:csharp}. If no access modifier is provided, then the default modifier is private{format:csharp}.
[static]{format:csharp} is an optional keyword. If present, the Property is shared among all instances of the class. If absent (which is the common case) then the Property is an instance member.
dataType is any built-in data type or the name of a programmer-defined data type.
PropertyName is a the name you give to the member property.

Method Declarations

1 [accessModifier] [static] returnType MethodName(ParameterList)
2 {
3     // body of method
4 }
A Method Declaration defines a named set of instructions.
[accessModifier] is either public{format: csharp}, private{format: csharp}, protected{format: csharp}, or internal{format:csharp}. If no access modifier is provided, then the default modifier is private{format:csharp}.
[static]{format:csharp} is an optional keyword. If present, the method is shared among all instances of the class. If absent (which is the common case) then the method is an instance member.
returnType is any built-in data type or the name of a programmer-defined data type. The return type signifies the kind of information that the method will return. If the method does not return any information, then the keyword void is used as the return type.
MethodName is a the name you give to the method.
ParameterList is a comma-separated list of individual variable declarations.

Constructors

1 [accessModifier] ClassName(ParameterList)
2 {
3     // body of constructor
4 }
A Constructor is a set of instructions used when instantiating (creating) an object.
[accessModifier] is either public{format: csharp}, private{format: csharp}, protected{format: csharp}, or internal{format:csharp}. If no access modifier is provided, then the default modifier is private{format:csharp}.
ClassName - All constructors use the name of the class to which they belong as the name of the constructor.
ParameterList is a comma-separated list of individual variable declarations.
Classes never return any information - they are simply blocks of instructions used to set up the initial state of the object.

Flow-Control Statements

  • If-Else
  • Case
  • For and Foreach
  • While and Do-While

Interlude 1 - Console Input/Output

TODO:

  • Output
  • Input
  • Converting user input

The ABCs of Classes and Objects

A Tutorial and Walkthrough of coding Classes and Objects

The purpose of this tutorial is to give the student an opportunity to write code and to explore the fundamentals of Classes and Objects. Specifically, this tutorial demonstrates fields, properties, constructors, and methods in class declarations along with object instantiation and the use of the member access operator.

About Classes and Objects

A computer program is a set of instructions for manipulating information.

Information is central to the whole purpose of computer programs, and is the “thing” that has value in the eyes of the end-user. Information is often complex, being made up of many smaller pieces of related information. For example, the information could be the details of a bank account, the marks earned by a student, or information about a company or an employee. A key aspect of all of these is that the details of the information (First and Last name, for example) are bundled together and treated as a single unit - a composition of related information. In programming, those bundled sets of detailed information are known as objects.

Objects embody more than just information, however. A person can do things with objects. For example, if you imagine a Bank Account as an object, it can be made up of a bunch of information, such as Account Number, Balance and Overdraft Limit. Now imagine the things you can do with a bank account: you can Deposit or Withdraw money. These actions are tightly related to bank accounts, largely because they directly affect the information in the bank account. These actions are carried out as a set of instructions - known as methods - which are carried out in a prescribed way through a set of one or more program statements.

Two objects can have the same set of characteristics, but different information. For example, consider two Bank Account objects where one account has a balance of $4,500.00 and another has a balance of $125.00. The actual information is different, but the characteristics (what Bank Accounts “look like”) remain the same. The things you can do with the two bank accounts also remain the same: you can Deposit and Withdraw money. In programs, the characteristics of an object are defined in something called a Class. A class defines

  • What an object “looks like” (information)
  • How an object “behaves” (instructions to manipulate information)

For a computer program to be able to work with objects, it must first know the class definition of that object. Coding a class definition is like telling the computer about a new data type that you are defining. The name of the class is the name of the new data type. Once the data type is defined, then it can be used to create objects. A class definition (or “class” for short) acts as a blueprint for creating objects; from the blueprint, the computer is told what the object “looks like” and how it “behaves”. Every object is said to be an “instance” of a class, in the same way that a physical car would be an instance of the car’s blueprint. The term instantiation basically means “to instantiate”, and it refers to the act of creating objects in code. An object is said to be “based on” a class when that class is the data type from which an object has been instantiated (just as a physical car would be “based on” the car’s blueprint).

So, objects and classes are closely related, but not exactly the same. The relationship between objects and classes is pretty much the same as the relationship between ordinary values and data types.

Coding the Class Definition

A class definition can contain four parts: Fields, Properties, Constructors, and Methods. Fields and properties work together to describe what an object based on the class “looks like” (the object’s information). Constructors and Methods describe how the object “behaves” (what instructions an object performs to manipulate information).

  • Fields
    • Fields are variables that are shared by/accessible to all the other members of a class (properties, constructors, and methods).
    • Fields are almost always declared as private (meaning that they are not directly accessible from outside the class).
    • Although not commonly done, a field can be assigned an initial default value when it is declared.
  • Properties
    • Properties are used like ordinary fields or variables, but work internally as methods.
    • Properties can have a Get method and/or a Set method.
      • The Get method is used when attempting to retrieve a value from the property.
      • The Set method is used when attempting to store a value in the property.
    • Properties often (but not always) have a corresponding field that is used to hold or store the property’s value in the “background”; the field associated with a property is often referred to as the “backing store”.
    • Properties that do not have a corresponding backing store will only have a Get method that calculates a value based on other values; there is no Set method because there is no single field in which to store a value for the property.
    • Properties are usually declared as public (meaning that they can be accessed directly from outside the class).
  • Constructors
    • Constructors are called automatically whenever an object is created. Objects are created by the new keyword, whose general syntax is as follows:
      new ClassName(ArgList)
    • ArgList (or Argument List) is a comma-separated list of values that are sent to the constructor. The decision of which constructor can be called depends on the arguments (values) sent in when the new keyword is used; the compiler looks for a constructor with a parameter list that matches the argument list.
    • Constructors have one purpose: to make sure that the fields in the object have meaningful values. This usually means that a constructor will need some parameters to get those values from the code that creates the object.
    • Usually, constructors are made public.
    • A class can define more than one constructor. If no constructor is defined for a class, then a “default constructor” is used, which simply sets all the fields to their default values.
  • Methods
    • A method is a set of instructions that are typically focused on manipulating or working with the fields and properties of an object.
    • Methods are identified by a name (called the Method Name) and a parameter list; together the method name and parameter list make up what is called the Method Signature.
    • If a method has a return type of void, then it is known as a Subroutine; subroutines do not return any information to the code that called it.
    • If a method has any return type except void, then it is called a Function; functions can only return one item, and must do so using a return statement.

A Tutorial - OOP First in Three Parts

Practice makes better!

This three-part tutorial establishes the foundations of the key grammars around classes and objects. The first two work on a BankAccount and Bank class while the last part demonstrates the same concepts around the idea of rental cars and rental companies.

Part 1

This tutorial will walk you through the steps to create a class and an object based on the following design. This first program will demonstrate a BankAccount class and the transfer of money from one bank account to another.

  1. Open up Visual Studio and create a new C# Console Application project. In that project, create a folder called “Tutorial”.
  1. Right-click on the Tutorial folder, and create a class called “BankAccount”. Edit the BankAccount class so that it has the following code.
 1 namespace ObjectABCs.Tutorial
 2 {
 3     public class BankAccount
 4     {
 5         #region Fields (always private)
 6         private int _AccountNumber;
 7         private double _Balance;
 8         #endregion
 9 
10         #region Properties
11         public int AccountNumber
12         {
13             get { return _AccountNumber; }
14             private set { _AccountNumber = value; }
15         }
16 
17         public double Balance
18         {
19             get { return _Balance; }
20             set { _Balance = value; }
21         }
22         #endregion
23 
24         public BankAccount(int accountNumber, double balance)
25         {
26             AccountNumber = accountNumber;
27             Balance = balance;
28         }
29 
30         public void Deposit(double amount)
31         {
32             Balance = Balance + amount;
33         }
34 
35         public void Withdraw(double amount)
36         {
37             Balance = Balance - amount;
38         }
39     }
40 }
  1. Create another class inside the Tutorial folder, and name it “Bank”. Edit the class so that it has the following code.
 1 namespace ObjectABCs.Tutorial
 2 {
 3     public class Bank
 4     {
 5         public static void Transfer(BankAccount fromAccount, BankAccount toAccou\
 6 nt, double amount)
 7         {
 8             fromAccount.Withdraw(amount);
 9             toAccount.Deposit(amount);
10         }
11     }
12 }
  1. Create a driver class named “DemoDriver” and place it in the Tutorial folder. Edit the driver so that it has the following code.
 1 using System;
 2 
 3 namespace ObjectABCs.Tutorial
 4 {
 5     public class DemoDriver
 6     {
 7         public static void Start()
 8         {
 9             BankAccount myAccount = new BankAccount(123546, 250.00);
10             BankAccount storeAccount = new BankAccount(987654, 5473.28);
11 
12             DisplayAccount(myAccount, "My Account");
13             DisplayAccount(storeAccount, "Store Account");
14 
15             Console.WriteLine("I am purchasing an item for $12.95");
16             Bank.Transfer(myAccount, storeAccount, 12.95);
17             DisplayAccount(myAccount, "My Account");
18             DisplayAccount(storeAccount, "Store Account");
19             Console.WriteLine("Purchase complete");
20         } // end of Start() method
21 
22         private static void DisplayAccount(BankAccount account, string message)
23         {
24             Console.WriteLine(message);
25             Console.WriteLine("-- Account Info --");
26             Console.WriteLine("Acct. #: " + account.AccountNumber);
27             Console.WriteLine("Balance: $ " + account.Balance);
28             Console.WriteLine("-- ------------ --");
29             Console.WriteLine();
30         } // end of DisplayAccount() method
31     }
32 }
  1. Open the Program.cs file and edit the Main() method to call the demo driver class.
 1 using ObjectABCs.Tutorial;
 2 
 3 namespace ObjectABCs
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             DemoDriver.Start();
10         }
11     }
12 }

When you run the program, you should see the result as shown in the following screen-shot.

Part 2

A big aspect of developing computer programs is the work of modifying existing code that you or others have written. In this part of the tutorial, we’ll revisit the BankAccount and DemoDriver classes to add and take advantage of a new method on the BankAccount class: ToString().

  1. Open the BankAccount class and modify it by adding the following ToString() method in the body of the class.
1     public override string ToString()
2     {
3         string accountInfo = "Balance (for account # "
4                             + AccountNumber.ToString()
5                             + "): "
6                             + string.Format("{0:C}", Balance);
7 
8         return accountInfo;
9     }
  1. Open the DemoDriver class and modify the DisplayAccount() method to look like the following code.
1     private static void DisplayAccount(BankAccount account, string message)
2     {
3         Console.WriteLine(message);
4         Console.WriteLine("-- Account Info --");
5         Console.WriteLine(account);
6         Console.WriteLine("-- ------------ --");
7         Console.WriteLine();
8     } // end of DisplayAccount() method

Part 3

Many times, properties act to provide transparent access to fields. (All of the examples so far have used Properties in this simplest way.) In C# version 3.0, a new syntax was introduced called auto-implemented properties which reduces the amount of code required to get the same effect as these transparent properties.

Auto-implemented properties do not have a field as a “backing store” and do not have bodies for the get and set methods. For example, the following code demonstrates an auto-implemented property.

1   public string ClientName { get; private set; }

This property has the exact same effect as the following, longer approach of using a property with a field in the background.

1   private string _ClientName;
2   public string ClientName
3   {
4       get { return _ClientName; }
5       private set { _ClientName = value; }
6   }

In this part of the tutorial, you will create classes that use auto-implemented properties, as well as regular properties.

  1. Open up Visual Studio and create a new C# Console Application project. In that project, create a folder called “Tutorial”.
  1. Create a new class in the Tutorial folder called RentalCar. Edit the class so that it matches the following code.
 1 using System; // needed for DateTime
 2 namespace ObjectABCs.Tutorial
 3 {
 4     public class RentalCar
 5     {
 6         public string VIN { get; private set; }
 7         public string ClientName { get; private set; }
 8         public DateTime DateTaken { get; private set; }
 9         public int DaysRental { get; set; }
10         public DateTime DateDue
11         {
12             get
13             {
14                 return DateTaken.AddDays(DaysRental);
15             }
16         }
17 
18         public RentalCar(string clientName, DateTime dateTaken, int days)
19         {
20             ClientName = clientName;
21             DateTaken = dateTaken;
22             DaysRental = days;
23             // figure out the remaining values
24             VIN = GetPretendVIN();
25         }
26 
27         private static string _PretendVIN = "1ABC234DE567";
28         private static int _Counter = 10;
29         private static string GetPretendVIN()
30         {
31             string tempVIN = _PretendVIN + _Counter.ToString();
32             _Counter = _Counter + 1;
33             return tempVIN;
34         }
35 
36         public override string ToString()
37         {
38             return VIN;
39         }
40     }
41 }
  1. Create another class named RentalCompany. Edit the code to match the following.
 1 using System; // needed for DateTime
 2 namespace ObjectABCs.Tutorial
 3 {
 4     public class RentalCompany
 5     {
 6         public int CarCount { get; private set; }
 7 
 8         public RentalCompany(int carCount)
 9         {
10             CarCount = carCount;
11         }
12 
13         public RentalCar BookRental(string name, int days)
14         {
15             RentalCar car;
16             car = new RentalCar(name, DateTime.Today, days);
17             CarCount = CarCount - 1;
18             return car;
19         }
20 
21         public override string ToString()
22         {
23             return CarCount.ToString() + " cars available to rent.";
24         }
25     }
26 }
  1. Create a final class named DemoRentals. This will be the driver to use RentalCompany and RentalCar objects. Edit DemoRentals to match the following.
 1 using System;
 2 
 3 namespace ObjectABCs.Tutorial
 4 {
 5     public class DemoRentals
 6     {
 7         public static void Start()
 8         {
 9             string name;
10             int daysToRent;
11 
12             name = PromptName();
13             daysToRent = PromptRentalTime();
14 
15             RentalCar rental;
16             RentalCompany budget = new RentalCompany(5);
17 
18             rental = budget.BookRental(name, daysToRent);
19 
20             DisplayRentalInfo(rental);
21         }
22 
23         private static string PromptName()
24         {
25             Console.Write("Enter name of person renting vehicle: ");
26             string name = Console.ReadLine();
27             return name;
28         }
29 
30         private static int PromptRentalTime()
31         {
32             Console.Write("Enter number of days to rent: ");
33             string daysAsText = Console.ReadLine();
34             int days = Convert.ToInt32(daysAsText);
35             return days;
36         }
37 
38         private static void DisplayRentalInfo(RentalCar rental)
39         {
40             Console.WriteLine("Rental Info");
41             Console.WriteLine("-----------");
42             Console.WriteLine(rental);
43             Console.WriteLine("Customer: " + rental.ClientName);
44             Console.WriteLine("Due Date: " + rental.DateDue.ToShortDateString());
45             Console.WriteLine();
46         }
47     }
48 }
  1. Lastly, modify the Main method in Program.cs to call the DemoRentals.Start() method.
 1 using ObjectABCs.Tutorial;
 2 
 3 namespace ObjectABCs
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             DemoRentals.Start();
10         }
11     }
12 }
  1. Run the program. You should get results similar to the following screenshot.

OOP As A Foundation

Topic A - Starting Classes

Overview

This topic introduces some of the basic syntax and grammar surrounding Object-Oriented Programming in C#. The following C# keywords are introduced.

  • public
  • class
  • static
  • string
  • void
  • return
  • namespace

This topic will also introduce the following grammars, syntax and language constructs:

  • Simple class declaration syntax (no members)
  • Simple class declaration syntax (with static methods)
  • Method overloading
  • Method declaration syntax (class methods, with the static keyword)
  • Parameter declaration (variable declaration) syntax
  • Class (static) method call syntax (with and without arguments)
  • main function (entry point of program)
  • Console output
  • Simple string concatenation
  • C# as a case-sensitive language
  • Single-line, multi-line and XML comments

LOGs

At the end of this topic, you should be able to …

OOP Basics

  • Define the term “class” as used in OOP
  • Explain the purpose of classes in computer programs
  • Describe the primary keywords used in declaring a class
  • Define the term “method” and give an example
  • Create simple classes with methods only
  • Explain what is meant by “overloading”
  • Describe the syntax of a method declaration (aka, method implementation)
  • Explain how classes with identical names can be distinguished from each other

General Programming Concepts and Terms

  • Define the term “keyword” as it applies to programming languages
  • Define the term “identifier” as it applies to programming languages
  • Define the term “program statement” and identify how the computer recognizes a program statement
  • Define the term “syntax” as it applies to programming languages
  • Identify the entry point for every computer program
  • Perform simple output to the console using System.Console
  • Identify the basic structure of a simple C# program
  • Explain what is meant by a “driver”
  • Explain what is meant by a “case-sensitive” programming language
  • Explain what is meant by a “strongly-typed” programming language
  • Explain what “string concatenation” is and how it works
  • Define and distinguish the terms “argument” and “parameter”
  • Use single-line, multi-line and XML comments as a means of documenting code
  • List the four pieces of information to include in comments at the top of every source file

Intro to IDEs

  • Define the term “IDE” as it relates to software development tools
  • Define the terms “project” and “solution”
  • Identify the various parts of the IDE (Integrated Development Environment) used in this course
  • Create a new project in the IDE for this course
  • Create new source files in the IDE for this course
  • Add existing files to a project

Code Samples

The following examples are used to illustrate this topic.

  1. Nothingness - This class represents the absolute minimum code required to code a class. Even though it’s not a very “useful” class, it does provide and introduction to the ideas of classes, keywords and identifiers.
  2. HelloWorld - This adaptation of the classic “Hello World” program illustrates static methods. This example includes and introduces the concept of a “driver”.
  3. Comments - This class is not really “functional”, but is intended to illustrate the basic types of comments allowed in the programming language.

Nothingness

This class represents the absolute minimum code required to code a class. Even though it’s not a very “useful” class, it does provide and introduction to the ideas of classes, keywords and identifiers.

1 namespace Topic.A.Examples
2 {
3     public class Nothingness
4     {
5 
6     }
7 }

HelloWorld

This adaptation of the classic “Hello World” program illustrates static methods. This example includes and introduces the concept of a “driver”.

 1 namespace Topic.A.Examples
 2 {
 3     public class Salutation // Define a class called "Salutation"
 4     {
 5         public static string Greeting()
 6         {
 7             return "Hello World!";
 8         } // end of Greeting()
 9 
10         public static string Greeting(string name)
11         {
12             return "Hello " + name;
13         } // end of Greeting(string)
14 
15         public static string Farewell()
16         {
17             return "So long!";
18         } // end of Farewell()
19     } // end of Salutation class
20 }
 1 namespace Topic.A.Examples
 2 {
 3     public class HelloWorld_Driver
 4     {
 5         public static void Main(string[] args)
 6         {
 7             System.Console.WriteLine(Salutation.Greeting());
 8             System.Console.WriteLine(Salutation.Greeting("Bob"));
 9             System.Console.WriteLine(); // print a blank line
10             System.Console.WriteLine(Salutation.Farewell());
11         }
12     }
13 }

Comments

This class is not really “functional”, but is intended to illustrate the basic types of comments allowed in the programming language.

 1 /*
 2  * File:    Comments.cs
 3  * Author:  Dan Gilleland
 4  * Date:    2010
 5  * Purpose: To illustrate multi-line, single-line, and XML comments.
 6  *          This is a multi-line comment.
 7  */
 8 namespace Topic.A.Examples
 9 {
10     /// <summary>
11     /// Comments illustrates multi-line, single-line, and XML comments.
12     /// </summary>
13     /// <remarks>
14     /// This class is a stand-alone class used to illustrate comments.
15     /// This particular XML comment is "attached" to the class as
16     /// a whole, while other XML comments are for fields or methods
17     /// in the class (a few methods and fields have been included for
18     /// illustration purposes).
19     /// [Author: Dan Gilleland]
20     /// </remarks>
21     public class Comments
22     {
23         /// <summary>
24         /// This is a method of <see cref="Comments"/>
25         /// </summary>
26         /// <returns>This method returns a string.</returns>
27         public static string SimpleMethod()
28         {
29             return "Hello World!"; // "Hello World!" is a literal string value
30         } // end of SimpleMethod()
31 
32         /// <summary>
33         /// This is a one-sentence description of the method.
34         /// </summary>
35         /// <param name="name">This is where I describe the purpose of this para\
36 meter</param>
37         /// <returns>Here I describe what information is returned from this meth\
38 od.</returns>
39         /// <remarks>
40         /// This method has a single parameter.
41         /// </remarks>
42         public static int MethodWithParameter(string name)
43         {
44             return name.Length; // This is a single-line comment (must be end of\
45  physical line)
46         } // end of MethodWithParameter(string)
47     } // end of Comments class
48 }

Practice Exercises

  • OuterSpace – This class is the simplest possible class (and, coincidentally, one of the most useless).
  • AnsweringMachine – The AnsweringMachine class provides a method to give an answer to an incoming phone call.
    Driver – This class is the driver for the AnsweringMachine class.
  • Salutation – This is the Salutation class that was previously demonstrated.
    HelloWorld_Driver – This class is the driver for the Salutation class.

OuterSpace

This class is the simplest possible class (and, coincidentally, one of the most useless).

Problem Statement:

Create a class called OuterSpace. This class has no members at all (it is empty, like outer space). Add a multi-line comment at the beginning that should include your full name as the author of the class. Also make an XML comment for the class as a whole.

AnsweringMachine

The AnsweringMachine class provides a method to give an answer to an incoming phone call.

Problem Statement:

Create the AnsweringMachine class so that it can provide a default answer for an incoming phone call as well as a customizable answer. The methods should be named answer and they should return a String. There should be two methods in total, and both of them should be declared as static. The actual content of the default message can be whatever you choose, while the customizable method will receive a single String argument that has the name of the person receiving the message. Also create a driver that demonstrates the AnsweringMachine in a Console environment.

Use the following details to guide your solution.

Method Detail

  • public static string Answer()
    Provides a standard default message for the answering machine.

    Returns:
    A String that instructs the caller to leave a message.

  • public static string Answer(string name)
    Provides a customizable message for the answering machine.

    To use this method, supply a person’s name, and this name will be incorporated into the message that is returned. For example,
    System.Console.WriteLine(AnsweringMachine.Answer("Bob");

    Parameters:
    name - A String that is the name of the person being called.
    Returns:
    A String that instructs the caller to leave a message for the person with the supplied name.

Salutation and HelloWorld_Driver

In each of the single-line comments above a line of code, enter a phrase or sentence in English that describes what is done in that line of code.

Salutation

 1 // Instructions: Enter comments in each blank to describe the following code
 2 // _____________________________________________________
 3 namespace Topic.A.Exercises
 4 {
 5 
 6     // _____________________________________________________________________
 7     public class Salutation
 8     {
 9         // _________________________________________________________________
10         public static string Greeting()
11         {
12             // _____________________________________________________________
13             return "Hello World!";
14         } // end of Greeting()
15 
16         // _________________________________________________________________
17         public static string Greeting(string name)
18         {
19             // _____________________________________________________________
20             return "Hello " + name;
21         } // end of Greeting(string)
22 
23         // _________________________________________________________________
24         public static string Farewell()
25         {
26             // _____________________________________________________________
27             return "So long!";
28         } // end of Farewell()
29     } // end of Salutation class
30 }

HelloWorld_Driver

 1 // Instructions: Enter comments in each blank to describe the following code
 2 // _____________________________________________________
 3 namespace Topic.A.Exercises
 4 {
 5     // _____________________________________________________
 6     public class HelloWorld_Driver
 7     {
 8         // __________________________________________________________________
 9         public static void main(string[] args)
10         {
11             // ______________________________________________________________
12             System.Console.WriteLine(Salutation.Greeting());
13             // ______________________________________________________________
14             System.Console.WriteLine(Salutation.Greeting("Bob"));
15             // ______________________________________________________________
16             System.Console.WriteLine(); // print a blank line
17             // ______________________________________________________________
18             System.Console.WriteLine(Salutation.Farewell());
19         }
20     }
21 }

Topic B – Starting Classes

Overview

This topic introduces some of the basic syntax and grammar surrounding Object-Oriented Programming in Java. The following keywords are introduced. (Note that additional keywords from previous topics may also be present.)

  • new
  • char
  • int
  • double

This topic will also introduce the following grammars, syntax and language constructs. (Note that additional concepts from previous topics may also be present.)

  • Method declaration syntax (instance methods)
  • Object instantiation
  • Instance method call syntax (with and without arguments)
  • Class Field declaration syntax (member variables)
  • Assignment statement syntax
  • Accessing public fields in objects (storing & retrieving values)

Note that this package introduces the distinction between static and non-static methods. Static methods, also known as “class methods”, are identified by the keyword static and must be qualified by the class name; for example, in the following method call Salutation is the name of the class and Greeting is a static method of that class.
Salutation.Greeting()

Non-static methods, also known as “instance methods”, are identified by the absence of the static keyword and must be called by using an instance of the class (that is, an object). An example of calling an instance method would be
app.Greeting()
where the app is an instance of the Salutation class.

LOGs

At the end of this topic, you should be able to …

OOP Basics

  • Define the term “object” as used in OOP
  • Describe the syntax of static and non-static method declarations
  • Compare and contrast the syntax for method declarations (implementations) vs. method calls (for both static and non-static methods)
  • Define the term “field” as used in OOP and give an example
  • Compare and contrast instance and class members, for both methods and fields
  • Identify the “member access operator” and explain it’s purpose
  • Create (instantiate) objects
  • Distinguish between classes and objects in OOP
  • Explain what is meant by the phrase “type extensibility” and how classes represent “complex” data types in OOP

General Programming Concepts and Terms

  • List the three categories of simple information
  • Define the term “intrinsic data type”
  • Explain what an assignment statement is and how it works
  • Compare and contrast the three categories of simple information with the complex types of information which classes represent
  • Explain the advantages of using classes and objects instead of only using intrinsic data types

Code Samples

The following examples are used to illustrate this topic.

  1. Salutation - This adaptation of the classic “Hello World” program illustrates instance methods. This example includes and introduces the concept of a “driver” and the idea of creating (instantiating) an object based on a class.
  2. Person - This simple class illustrates and introduces the idea of fields (member variables) of a class. This example includes and introduces the idea of a driver. The driver also illustrates how a single class can be used to instantiate multiple, distinct objects.
  3. Account - This simple class also illustrates fields. This example includes a driver.
  4. Comments - This class continues the illustration of the kinds of comments allowed in the programming language. This class builds on the previous example by showing comments for fields as well as methods.
  5. Student - This class introduces a slightly more complex class by offering more fields. This example includes two drivers. By using two drivers, this illustrates that separate “programs” can share/use the same class definition.
  6. The first driver is a simple “test driver” to ensure that the class is “working”. This introduces the student to the idea that it is necessary to “test” or prove that the code we are creating is valid.
  7. The second driver illustrates how the a single class can act as the basis for creating many distinct objects.
  8. Employee + Company - These are other classes similar to the Person and Student classes. These classes, however, “share” a driver, illustrating the fact that any given “program” typically uses more than one class. In addition, this driver introduces the ToString() and Parse() methods of the DateTime class.

Salutation & Driver

This adaptation of the classic “Hello World” program illustrates instance methods. This example includes and introduces the concept of a “driver” and the idea of creating (instantiating) an object based on a class.

 1 /*
 2  * Purpose: To illustrate 
 3  *          - Keywords: public, class, return
 4  *          - Grammar: method declaration, parameter declaration, single line co\
 5 mments
 6  *          - Other:
 7  *              - string data type
 8  *              - method overloading
 9  *              - Instance members
10  */
11 namespace Topic.B.Examples
12 {
13     public class Salutation
14     {
15         public string Greeting()
16         {
17             return "Hello World!";
18         }
19 
20         public string Greeting(string name)
21         {
22             return "Hello " + name;
23         }
24     }
25 }
 1 /*
 2  * Purpose: To illustrate 
 3  *          - Keywords: public, class, static, void, new
 4  *          - Grammar: variable (object) declaration, object instantiation, meth\
 5 od declaration, method call, multi-line comments
 6  *          - Other:
 7  *              - main - the entry level of every program
 8  *              - console output (println)
 9  *              - Instance vs. Class methods
10  *              - instance method call
11  *              - instance method call with argument
12  *              - (optional) array declaration - string[]
13  */
14 namespace Topic.B.Examples
15 {
16 
17     public class HelloWorld_Driver
18     {
19         public static void Main(string[] args)
20         {
21             Salutation app = new Salutation();
22 
23             System.Console.WriteLine(app.Greeting());
24             System.Console.WriteLine(app.Greeting("Bob"));
25         }
26     }
27 }

Person

This simple class illustrates and introduces the idea of fields (member variables) of a class. This example includes and introduces the idea of a driver. The driver also illustrates how a single class can be used to instantiate multiple, distinct objects.

  • Data Attributes of the Person class:
  • FirstName : String
  • LastName : String
  • Age : Integer
 1 namespace Topic.B.Examples
 2 {
 3     public class Person
 4     {
 5         /// <summary>This is the first name of the person</summary>
 6         public string FirstName;
 7         /// <summary>This is the last name of the person</summary>
 8         public string LastName;
 9         /// <summary>This is the person's age</summary>
10         public int Age;
11     }
12 }
 1 namespace Topic.B.Examples
 2 {
 3     public class DemoPerson
 4     {
 5         public static void Main(string[] args)
 6         {
 7             Person someGuy;
 8             someGuy = new Person();
 9             someGuy.FirstName = "Harry";
10             someGuy.LastName = "Burns";
11             someGuy.Age = 25;
12 
13             Person someGirl;
14             someGirl = new Person();
15             someGirl.FirstName = "Sally";
16             someGirl.LastName = "Albright";
17             someGirl.Age = 25;
18 
19             string fullName;
20 
21             fullName = someGuy.FirstName + " " + someGuy.LastName;
22             System.Console.WriteLine("Hi. My name is " + fullName);
23 
24             fullName = someGirl.FirstName + " " + someGirl.LastName;
25             System.Console.WriteLine("Hi" + someGuy.FirstName +
26                                ". My name is " + fullName);
27         }
28     }
29 }

Account

This simple class also illustrates fields. This example includes a driver.
* Data Attributes of the Account class:
  * AccountNumber : Integer
  * Balance : Real
  * OverdraftLimit : Double

1 namespace Topic.B.Examples
2 {
3     public class Account
4     {
5         public int AccountNumber;
6         public double Balance;
7         public double OverdraftLimit;
8     }
9 }
 1 namespace Topic.B.Examples
 2 {
 3     public class DemoAccountDriver
 4     {
 5         public static void Main(string[] args)
 6         {
 7             Account myAccount; // declares a reference variable to an Account ob\
 8 ject
 9             myAccount = new Account(); // creates the Account object.
10 
11             myAccount.Balance = 500000.00;
12             myAccount.OverdraftLimit = 1000000.00;
13             myAccount.AccountNumber = 123456;
14         }
15     }
16 }

Comments

This class continues the illustration of the kinds of comments allowed in the programming language. This class builds on the previous example by showing comments for fields as well as methods.

 1 /*
 2  * File:    Comments.cs
 3  * Author:  Dan Gilleland
 4  * Date:    2010
 5  * Purpose: To illustrate multi-line, single-line, and XML comments.
 6  *          This is a multi-line comment.
 7  */
 8 namespace Topic.B.Examples
 9 {
10     /// <summary>
11     /// Comments illustrates multi-line, single-line, and XML comments.
12     /// </summary>
13     /// <remarks>
14     /// This class is a stand-alone class used to illustrate comments.
15     /// This particular XML comment is "attached" to the class as
16     /// a whole, while other XML comments are for fields or methods
17     /// in the class (a few methods and fields have been included for
18     /// illustration purposes).
19     /// </remarks>
20     public class Comments
21     {
22         /// <summary>
23         /// Here is a simple integer variable that is pre-set to the value 5.
24         /// </summary>
25         /// <remarks>
26         /// This is an instance member (non-static) of the class.
27         /// </remarks>
28         private int _five = 5;
29 
30         /// <summary>
31         /// Here is a whole number that is pre-set to the value 0.
32         /// </summary>
33         /// <remarks>
34         /// This field is a static member of the class.
35         /// </remarks>
36         private static int _instanceCounter = 0;
37 
38         /// <summary>
39         /// Here is a real number that is pre-set to the value 3.14159.
40         /// </summary>
41         /// <remarks>
42         /// This field is a constant member of the class.
43         /// </remarks>
44         private const  double _PI = 3.14159;
45 
46         /* ****************** Methods ******************** */
47         /// <summary>
48         /// This is a method of <see cref="Comments"/>
49         /// </summary>
50         /// <returns>This method returns a string.</returns>
51         public static string SimpleMethod()
52         {
53             return "Hello World!";
54         } // end of SimpleMethod()
55 
56         /// <summary>
57         /// This is a one-sentence description of the method.
58         /// </summary>
59         /// <param name="name">This is where I describe the purpose of this para\
60 meter</param>
61         /// <returns>Here I describe what information is returned from this meth\
62 od.</returns>
63         /// <remarks>
64         /// This method has a single parameter.
65         /// </remarks>
66         public static int MethodWithParameter(string name)
67         {
68             return name.Length;
69         } // end of MethodWithParameter(string)
70     } // end of Comments class
71 }

Student

The Student class introduces a slightly more complex example by offering more fields.

  • Data Attributes of the Student class:
  • Name : String
  • Gender : Character
  • StudentId : Integer
  • Program : String
  • GradePointAverage : Double
  • FullTime : Boolean

This example also includes two drivers. By using two drivers, this illustrates that separate “programs” can share/use the same class definition.
The first driver is a simple “test driver” to ensure that the class is “working”. This introduces the student to the idea that it is necessary to “test” or prove that the code we are creating is valid.

The second driver illustrates how the a single class can act as the basis for creating many distinct objects.

 1 /**
 2  * Purpose: To illustrate 
 3  *          Highlights:
 4  *          - Keywords: char, int, double
 5  *          - Grammar: variable declaration (fields)
 6  *          - Other:
 7  *              - Instance members
 8  */
 9 namespace Topic.B.Examples
10 {
11     public class Student
12     {
13         public string Name;                 // The full name of the student
14         public char Gender;                 // Gender can be 'M' or 'F'
15         public int StudentId;               // The school-provided student ID
16         public string Program;              // The course program; e.g.: "CST"
17         public double GradePointAverage;    // GPA is from 1.0 to 9.0
18         public bool FullTime;               // If the student is enrolled full-t\
19 ime
20     }
21 }
 1 /**
 2  * Purpose: To illustrate 
 3  *          Highlights:
 4  *          - Keywords: public, class, static, void, new
 5  *          - Grammar: 
 6  */
 7 namespace Topic.B.Examples
 8 {
 9     public class DemoStudentDriver
10     {
11         public static void Main(string[] args)
12         {
13             Student bob, mary, joe, susan, frank;
14             bob = new Student();
15             mary = new Student();
16             joe = new Student();
17             susan = new Student();
18             frank = new Student();
19 
20             bob.Name = "Bob McNalley";
21             bob.Gender = 'M';
22             bob.Program = "CST";
23             bob.StudentId = 200765789;
24             bob.GradePointAverage = 6.76;
25 
26             mary.Name = "Mary McTavishski";
27             mary.Gender = 'F';
28             mary.Program = "CST";
29             mary.StudentId = 200765790;
30             mary.GradePointAverage = 5.76;
31 
32             joe.Name = "Joe Jetson";
33             joe.Gender = 'M';
34             joe.Program = "CST";
35             joe.StudentId = 200765792;
36             joe.GradePointAverage = 4.66;
37 
38             susan.Name = "Susan Orlando";
39             susan.Gender = 'F';
40             susan.Program = "CST";
41             susan.StudentId = 200765795;
42             susan.GradePointAverage = 8.54;
43 
44             frank.Name = "Frank Smith";
45             frank.Gender = 'M';
46             frank.Program = "CST";
47             frank.StudentId = 200765797;
48             frank.GradePointAverage = 8.52;
49 
50             displayStudentInformation(bob);
51         }
52 
53         public static void displayStudentInformation(Student someStudent)
54         {
55             System.Console.WriteLine(someStudent.Name);
56             System.Console.WriteLine(someStudent.Gender);
57             System.Console.WriteLine(someStudent.Program);
58             System.Console.WriteLine(someStudent.StudentId);
59             System.Console.WriteLine(someStudent.GradePointAverage);
60         }
61     }
62 }

Employee & Company

The Employee and Company classes are similar to the Person and Student classes.

  • Data Attributes of the Employee class:
  • FirstName : String
  • LastName : String
  • SocialInsuranceNumber : Integer
  • YearlySalary : Real
  • EmploymentStartDate : Date
  • Gender : Character
 1 using System;
 2 namespace Topic.B.Examples
 3 {
 4     public class Employee
 5     {
 6         public string FirstName;
 7         public string LastName;
 8         public int SocialInsuranceNumber;
 9         public double YearlySalary;
10         public DateTime EmploymentStartDate;
11         public char Gender;
12     }
13 }
  • Data Attributes of the Company class:
  • Name : String
  • City : String
  • IsIncorporated : Boolean
  • BusinessStartDate : Date
  • NumberOfEmployees : Integer
  • GrossIncomeToDate : Real
 1 using System;
 2 namespace Topic.B.Examples
 3 {
 4     public class Company
 5     {
 6         public string Name;
 7         public string City;
 8         public bool IsIncorporated;
 9         public DateTime BusinessStartDate;
10         public int NumberOfEmployess;
11         public double GrossIncomeToDate;
12     }
13 }

In the following driver, the Employee and Company classes are both being used, illustrating the fact that any given “program” typically uses more than one class. In addition, this driver introduces the overloaded ToString() method in the DateTime class to improve the output of displaying dates and the Parse() method to convert a string representation of a date to an actual DateTime instance.

 1 using System;
 2 namespace Topic.B.Examples
 3 {
 4     public class DemoCompanyAndEmployee
 5     {
 6         public static void Main(string[] args)
 7         {
 8             Company Acme = new Company();
 9             Employee Salesman = new Employee();
10             Employee Shipper = new Employee();
11 
12             // Set the company's information
13             Acme.Name = "Acme International";
14             Acme.City = "Edmonton";
15             Acme.BusinessStartDate = new DateTime(); // new Date() defaults to t\
16 he current date
17             Acme.IsIncorporated = false;
18             Acme.NumberOfEmployess = 2;
19             Acme.GrossIncomeToDate = 2152368.52; // $ 2 million, plus change
20 
21             // Set the salesman's information
22             Salesman.FirstName = "Wiley";
23             Salesman.LastName = "Coyote";
24             Salesman.Gender = 'M';
25             Salesman.SocialInsuranceNumber = 123456789;
26             Salesman.EmploymentStartDate = DateTime.Today;
27             Salesman.YearlySalary = 45250.00;
28 
29             // Set the shipper's information
30             Shipper.FirstName = "Road";
31             Shipper.LastName = "Runner";
32             Shipper.Gender = 'F';
33             Shipper.SocialInsuranceNumber = 7777777;
34             Shipper.EmploymentStartDate = DateTime.Parse("June 1, 2008");
35             Shipper.YearlySalary = 54520.00;
36 
37 
38             // Show the information
39             System.Console.WriteLine("The information for the company:");
40             System.Console.WriteLine(Acme.Name);
41             System.Console.WriteLine(Acme.City);
42             System.Console.WriteLine(Acme.BusinessStartDate);
43             System.Console.WriteLine(Acme.IsIncorporated);
44             System.Console.WriteLine(Acme.NumberOfEmployess);
45             System.Console.WriteLine(Acme.GrossIncomeToDate);
46 
47             System.Console.WriteLine("The employee information: Salesman");
48             System.Console.WriteLine(Salesman.FirstName);
49             System.Console.WriteLine(Salesman.LastName);
50             System.Console.WriteLine(Salesman.Gender);
51             System.Console.WriteLine(Salesman.SocialInsuranceNumber);
52             System.Console.WriteLine(Salesman.EmploymentStartDate);
53             System.Console.WriteLine(Salesman.YearlySalary);
54 
55             System.Console.WriteLine("The employee information: Shipper");
56             System.Console.WriteLine(Shipper.FirstName);
57             System.Console.WriteLine(Shipper.LastName);
58             System.Console.WriteLine(Shipper.Gender);
59             System.Console.WriteLine(Shipper.SocialInsuranceNumber);
60             System.Console.WriteLine(Shipper.EmploymentStartDate.ToString("MMMM \
61 d, yyyy"));
62             System.Console.WriteLine(Shipper.YearlySalary);
63         }
64     }
65 }

Practice Exercises

  • AnsweringMachine - Create the AnsweringMachine class so that it can provide a default answer for an incoming phone call as well as a customizable answer.
  • Account - Extend the Account class from the example to include more information. Specifically, include an AccountType:String, BankName:String, BranchNumber:Integer, and InstitutionNumber:Integer.
  • CanadianAddress - Create the CanadianAddress class so that it can represent the majority of possible addresses that some place may have in Canada.
  • Course - Create the Course class so that it represents a post-secondary course.
  • ExamResult - Create the ExamResult class so that it represents the results of an exam written by a student.
  • LabResult - Create the labResult class so that it represents the results of a lab submitted by a student.

AnsweringMachine

The AnsweringMachine class provides a method to give an answer to an incoming phone call.

Problem Statement:

Create the AnsweringMachine class so that it can provide a default answer for an incoming phone call as well as a customizable answer. The methods should be named answer and they should return a String. There should be two methods in total, and both of them should be declared as instance members (non-static). The actual content of the default message can be whatever you choose, while the customizable method will receive a single String argument that has the name of the person receiving the message.

Also create a driver that demonstrates the AnsweringMachine in a Console environment

Create a driver for the AnsweringMachine class that creates an instance of the class and displays the results of calling the answer methods.

Account

Extend the Account class from the example to include more information.

Problem Statement:

Extend the Account class from the example to include more information. Specifically, include an AccountType:String, BankName:String, BranchNumber:Integer, and InstitutionNumber:Integer.

Also modify the driver to make use of the added information.

Notes

The branch number and the institution number together make up the Transit Number for a bank. “The bank transit number is 8 digits long. This is divided into a 5 digit branch number and 3 digit institution code, for example 10000-200.” (See http://en.wikipedia.org/wikiSort_code)

For more information on bank accounts and transit numbers in Canada, see http://en.wikipedia.org/wiki/Routing_transit_number#Canadian_transit_number.

CanadianAddress

This class represents an address for some place in Canada.

Problem Statement:

Create the CanadianAddress class so that it can represent the majority of possible addresses that some place may have in Canada. Design the class to have only public fields, as specified in this document.

  • Data Attributes of the CanadianAddress class:
    • Street : String
    • Unit : String
    • City : String
    • Province : String
    • PostalCode : String
    • RuralRoute : String
    • BoxNumber : String

Also create a driver for testing this class; you may use any name for the driver as long as it is not already mentioned in this package. In the driver, create instances of the CanadianAddress class that represent your current address as well as the address of your school (use hard-coded data).

Course

This class represents a post-secondary course with a theory (exam) and a lab portion.

Problem Statement:

Create the Course class so that it represents a post-secondary course. Design the class to have only public fields, as specified in this document.

  • Data Attributes of the Course class:
    • CourseName : String
    • CourseNumber : String
    • ExamCount : Integer
    • LabCount : Integer
    • ClassHours : Integer

Also create a driver for testing this class; you may use any name for your driver as long as it is not already mentioned in this package. In the driver, instantiate all of the first term classes you are taking and populate those objects with data (use hard-coded data).

ExamResult

This class represents the results of an exam for a student.

Problem Statement:

Create the ExamResult class so that it represents the results of an exam written by a student. Design the class to have only public fields, as specified in this document.

  • Data Attributes of the ExamResult class:
    • Name : String
    • TotalMarks : Integer
    • MarksEarned : Real
    • ExamWeight : Integer
    • StudentId : Integer

Also create a driver for testing this class; you may use any name for the driver as long as it is not already mentioned in this package. In the driver, instantiate all of the exams you have taken to date in this course and populate those objects with data (use hard-coded data).

LabResult

This class represents the results of an lab for a student.

Problem Statement:

Create the labResult class so that it represents the results of a lab submitted by a student. Design the class to have only public fields, as specified in this document.

  • Data Attributes of the LabResult class:
    • LabNumber : Integer
    • TotalMarks : Integer
    • MarksEarned : Real
    • LabWeight : Integer
    • StudentId : Integer

Also create a driver for testing this class; you may use any name for the driver as long as it is not already mentioned in this package. In the driver, instantiate all of the labs you have submitted to date in this course and populate those objects with data (use hard-coded data).

Topic C – Starting Classes

Overview

This topic introduces some of the basic syntax and grammar surrounding Object-Oriented Programming in C#. The following keywords are introduced. (Note that additional keywords from previous topics may also be present.)

• private
• this
• bool
• true
• false
• DateTime

This topic will also introduce the following grammars, syntax and language constructs. (Note that additional concepts from previous topics may also be present.)

• Private fields (encapsulation)
• Public properties (encapsulation)
• Constructor syntax
• Object instantiation with parameterized constructors
• Overriding the Object’s ToString() method

Daily LOGs

The following daily LOGs are covered in this package.

OOP Basics

• Define the term “encapsulation” as used in OOP
• Explain why encapsulation is a good design principle
• Define the term “access specifier” and identify where it occurs in the code for a class
• List the two access specifiers that are used in this course
• Describe the difference between “private” and “public” members of a class
• Describe the concepts of “properties” as used in OOP
• Define the term “backing store” as it applies to properties and fields
• Describe and explain the purpose and function of a constructor for a class
• Describe the syntax of a class constructor
• Identify when a class constructor is “called”
• Define the term “class scope” as used in OOP
• Define the term “local scope” as used in OOP
• Define the term “state” as applied to objects used in OOP
• Define the term “override” as used in OOP
• Explain the purpose and function of the ToString() method and why we sometimes want to change its default behaviour when we create classes
• Create simple class diagrams to represent classes

General Programming Concepts and Terms

• List three levels of scope

Code Samples

The following examples are used to illustrate this topic.

  1. Person - This simple class illustrates and introduces the idea of encapsulation (private fields with public properties). This example does not have a constructor. This example includes a driver. The driver is also used to illustrate how, with only fields & getter/setter methods, an object can be in an “unknown” (and invalid) state as soon as it is created; this idea is introduced to show the need for a constructor, and opens the discussion of the idea of a “default constructor”.
  2. Account - This simple class also illustrates encapsulation, but with some of the fields being read-only. This necessitates the presence of a constructor. This example includes a driver which shows that a class is in a “known state” as soon as it is created.
  3. Student - This class reinforces the idea of encapsulation and constructors. It also introduces the idea of overloading the default toString() method that every class inherits from the Object class. This example includes a driver with multiple objects, showing how the use of constructors makes it easier to create many objects in a few lines of code.
  4. Employee + Company - These are other classes similar to the Person and Student classes, but the Employee class uses Auto-Implemented properties (new since C# 3.0). Lastly, these classes “share” a driver, illustrating the fact that any given “program” typically uses more than one class.

The following class diagrams detail the design of these examples.

Person

This simple class illustrates and introduces the idea of encapsulation (private fields with public properties). This example does not have a constructor. This example includes a driver. The driver is also used to illustrate how, with only fields & getter/setter methods, an object can be in an “unknown” (and invalid) state as soon as it is created; this idea is introduced to show the need for a constructor, and opens the discussion of the idea of a “default constructor”.

Person Class Diagram

Account

This simple class also illustrates encapsulation, but with some of the fields being read-only. This necessitates the presence of a constructor. This example includes a driver which shows that a class is in a “known state” as soon as it is created.

Account Class Diagram

Student

This class reinforces the idea of encapsulation and constructors. It also introduces the idea of overloading the default ToString() method that every class inherits from the Object class. This example includes a driver with multiple objects, showing how the use of constructors makes it easier to create many objects in a few lines of code.

Student Class Diagram

Company and Employee

These are other classes similar to the Person and Student classes, but the Employee class uses Auto-Implemented properties (new since C# 3.0). Lastly, these classes “share” a driver, illustrating the fact that any given “program” typically uses more than one class.

Company Class Diagram
Employee Class Diagram

Practice Exercises

  • Person - Extend the Person class to include a constructor.
  • Account – Extend the Account class from the example to include more information. Specifically, include an AccountType:String, BankName:String, BranchNumber:Integer, and InstitutionNumber:Integer.
  • CanadianAddress - This class represents an address for some place in Canada.
  • Course - This class represents a post-secondary course with a theory (exam) and a lab portion.
  • ExamResult - This class represents the results of an exam for a student.
  • LabResult - This class represents the results of an lab for a student.

Person

This simple class illustrates and introduces the idea of encapsulation (private fields with public properties). This example uses a constructor for ensuring the state of an object when it is instantiated (created).

Extend the Person class from the example to include a constructor that takes in a first and last name as well as an age in the parameter list.

Person Class Diagram

Account

Extend the Account class from the example to include more information.

Problem Statement:

Extend the Account class from the example to include more information. Specifically, include an AccountType:String, BankName:String, BranchNumber:Integer, and InstitutionNumber:Integer. Base your solution on the following class diagram.

Account Class Diagram

Also modify the driver to make use of the added information.

Notes

The branch number and the institution number together make up the Transit Number for a bank. “The bank transit number is 8 digits long. This is divided into a 5 digit branch number and 3 digit institution code, for example 10000-200.” (See http://en.wikipedia.org/wikiSort_code)
For more information on bank accounts and transit numbers in Canada, see http://en.wikipedia.org/wiki/Routing_transit_number#Canadian_transit_number.

CanadianAddress

This class represents an address for some place in Canada.

Problem Statement:

Create the CanadianAddress class so that it can represent the majority of possible addresses that some place may have in Canada. Design the class to use auto-implemented properties as specified in this class diagram. No constructor is required for this class.

CanadianAddress Class Diagram

Also create a driver for testing this class; you may use any name for the driver as long as it is not already mentioned in this namespace. In the driver, create two instances of the CanadianAddress class that represent your current address as well as the address of your school (use hard-coded data).

Course

This class represents a post-secondary course with a theory (exam) and a lab portion.

Problem Statement:

Create the Course class so that it represents a post-secondary course. Design the class to have auto-implemented properties and a constructor as specified in this class diagram. Note that the auto-implemented properties should have their “set” implementations marked as private.

Course Class Diagram

Also create a driver for testing this class; you may use any name for your driver as long as it is not already mentioned in this namespace. In the driver, instantiate all of the first term classes you are taking and populate those objects with data (use hard-coded data).

LabResult

This class represents the results of a lab for a student.

Problem Statement:

Create the LabResult class so that it represents the results of a lab submitted by a student. Design the class to have the fields, properties, and constructor as specified in this document. Also create a ToString() method that describes the information in any given instance of this class.

Use an auto-implemented property for the MarksEarned; use fields as the “backing store” for all other properties.

Note that the following properties should not have “set” implementations: TotalMarks, LabNumber, LabWeight, and StudentId.

LabResult Class Diagram

Here are some XML comments to describe the ToString( ) method.

 1 /// <summary>
 2 /// This method overrides the default ToString() method to display 
 3 /// more meaningful information about this object.
 4 /// </summary>
 5 /// <returns>A string displaying the StudentId, MarksEarned, and 
 6 /// TotalMarks.</returns>
 7 /// <remarks>
 8 /// A call to this method (such as <c>Lab4.ToString()</c>) 
 9 /// would produce the following result:
10 /// <code>The student (200702694) received 24.5/35 for this lab.</code>
11 /// </remarks>

Also create a driver for testing this class; you may use any name for the driver as long as it is not already mentioned in this namespace. In the driver, instantiate all of the labs you have submitted to date in any course and populate those objects with data (use hard-coded data); if you haven’t had any labs as of yet, then make up some data.


### ExamResult

This class represents the results of an exam for a student.

Problem Statement:

Create the ExamResult class so that it represents the results of an exam written by a student. Design the class to have the properties and constructors as specified in this document. (Note that there are two constructors for this class.) Also create a ToString( ) method that describes the information in any given instance of this class.

Use auto-implemented properties for the entire class. Note that only the following properties should have private “set” implementations: TotalMarks, ExamName, ExamWeight, and StudentId.

ExamResult Class Diagram

Also create a driver for testing this class; you may use any name for the driver as long as it is not already mentioned in this namespace. In the driver, instantiate all of the exams you have taken to date in this course and populate those objects with data (use hard-coded data); if you need to, you may create fake data for the driver.

Topic D – Testing and Debugging

Overview

This topic introduces the concepts of testing and verifying that code is running correctly. Two approaches will be presented and compared: Ad-hoc test drivers and Unit Tests.

Test drivers that rely on user input/output are the traditional means of verifying that code runs properly. The biggest benefit of test drivers is that they provide quick “ad-hoc” tests and are simple to produce on any IDE. However, test drivers have some major downfalls.

Current programming techniques make use of Unit Tests. A unit test is a simple, isolated test of some part of a class. Unit tests provide a way to clearly show the success or failure of a particular section of code. Unit tests are a key part of Test Driven Development (TDD).

Regardless of whether the developer uses test drivers or unit tests, it is important to remember that the developer is still responsible to make sure that the tests (and thus, the test results) are valid. Improper use of test drivers and unit tests can lead to
* “false positives” - indicating that something works when it really doesn’t, and
* “false negatives” - indicating that something is broken when it really isn’t

Note: For this course, students will be provided with unit tests and will not be expected to have to write their own unit tests. The unit tests supplied to students will use nUnit 2.5.7 which is already installed in the lab. To use these libraries at home, simply install nUnit 2.5.7 on your home computer.

LOGs

The following daily LOGs are covered in this package.

General Programming Concepts and Terms

  • Explain the role of testing as it applies to software development
  • Define and compare the terms “compile-time error” and “run-time error”
  • Define the term “test driver”
  • Create simple ad-hoc test drivers to test for run-time errors
  • Define the term “TDD”
  • Compare and contrast Test Drivers and Unit Tests
  • Define the terms “false positive” and “false negative”
  • List three downfalls of using Test Drivers
  • Identify four benefits of using Unit Tests
  • Add unit testing libraries and unit testing packages to existing programs
  • Use unit tests to validate the requirements of a class’ design and behaviour
  • Diagnose and correct software problems by using unit tests

Code Samples

The following examples are used to illustrate this topic.

  1. Person - This simple class was used to introduce the idea of encapsulation (private fields with public getters and setters). This example uses a constructor for ensuring the state of an object when it is instantiated (created). In this topic, it is used to demonstrate unit testing.
  2. Account - This simple class also illustrates encapsulation, but with some of the fields being read-only. This class uses a constructor (which is also necessary for getting state into fields which do not have corresponding setter methods).
  3. Student - This class reinforces the idea of encapsulation and constructors. It also demonstrates the idea of overloading the default ToString() method that every class inherits from the Object class.
  4. Employee – The Employee class represents basic information about an employee of a company.
  5. Company - These are other classes similar to the Person and Student classes. These classes, however, “share” a driver, illustrating the fact that any given “program” typically uses more than one class.

Test Drivers (Console I/O)
TBA
Unit Tests (nUnit)
The unit tests for these classes are included in the solution folder under the “Demos + Practice” folder. Simply double-click the NUnit Test Project (.nunit) and the tests will open in the NUnit GUI.

Person

This simple class was used to introduce the idea of encapsulation (private fields with public getters and setters). This example uses a constructor for ensuring the state of an object when it is instantiated (created). In this topic, it is used to demonstrate unit testing. The following diagram represents the last design for the Person class, as completed in the exercises portion of the previous topic.

Previous Person Class Diagram

The supplied unit tests check all of this previously documented behaviour, but they also check to see if the Person class has overridden the ToString() method. Because this requirement is new, and has not yet been implemented, the unit tests show this as a “failed test.” The following diagram is the design that the unit tests are evaluating.

Person Class Diagram

Should…
* Instantiate (build) from constructor
* Get/Set First Name
* Get/Set Last Name
* Get/Set Age
* [NOT-YET-IMPLEMENTED] Override ToString() to get the person’s full name (as first name then last name)
  The test for this method will report as “failed” because it has not yet been implemented.

Account

This simple class also illustrates encapsulation, but with some of the fields being read-only. This class uses a constructor (which is also necessary for getting state into fields which do not have corresponding setter methods).

Account Class Diagram

Should…
* Get Bank Name
* Get Branch Number
* Get Institution Number
* Get Account Number
* Get Account Type
* Get/Set Balance
* Get/Set Overdraft Limit

Student

This class reinforces the idea of encapsulation and constructors. It also demonstrates the idea of overloading the default ToString() method that every class inherits from the Object class.

Student Class Diagram

Should…
* Get/Set Name
* Get/Set Gender
* Get/Set Student Id
* Get/Set GPA
* Get/Set Program
* Get/Set Full-Time
* Override ToString() to get the student’s ID and name

Employee

Employee Class Diagram

Should…
* Get/Set First Name
* Get/Set Last Name
* Get/Set Gender
* Get/Set Employment Date
* Get/Set Salary
* Get Social Insurance Number

Company

Company Class Diagram

Should…
* Get/Set Name
* Get/Set City
* Get/Set Incorporated
* Get/Set Number of Employees
* Get/Set Gross Income to Date
* Get Business Start Date

Practice Exercises

  1. Person - This simple class was used to introduce the idea of encapsulation (private fields with public properties). This example uses a constructor for ensuring the state of an object when it is instantiated (created). It also demonstrates the overriding of the ToString() method inherited from the Object method.
  2. CanadianAddress - This class represents an address for some place in Canada.
    Update this class to now include a constructor and to override the ToString() method.
  3. Course - This class represents a post-secondary course with a theory (exam) and a lab portion.
  4. ExamResult - This class represents the results of an exam for a student.
  5. LabResult - This class represents the results of a lab for a student.

For this exercise, take the code solutions you created in the previous topic and compare your results with the jUnit tests for these classes; check with your instructor to see where you can download the unit tests.

Person

This simple class was used to introduce the idea of encapsulation (private fields with public properties). This example uses a constructor for ensuring the state of an object when it is instantiated (created). It also demonstrates the overriding of the ToString() method inherited from the Object method.

Person Class Diagram

Should…
* Instantiate (build) from constructor
* Get/Set First Name
* Get/Set Last Name
* Get/Set Age
* Override ToString() to get the person’s full name (as first name then last name)

CanadianAddress

CanadianAddress Class Diagram

Should…
* Instantiate (build) from Constructor
* Get/Set: Street, Unit, City, Province, Postal Code, Rural Route, Box Number
* Override ToString() to just show Street, City, Province, and Postal Code

Course

Course Class Diagram

Should…
* Instantiate from Constructor
* Get: Course Name, Course Number, Exam Count, Lab Count, Class Hours

ExamResult

ExamResult Class Diagram

Should…
* Instantiate from Constructor
* Get/Set: Marks Earned
* Get: Name, Student Id, Total Marks, Exam Weight
* Override ToString() to show
  “The student (studentId) received earnedMarks/totalMarks for this examName exam.”

LabResult

LabResult Class Diagram

Should…
* Instantiate from Constructor
* Get/Set: Marks Earned
* Get: Lab Number, Student Id, Total Marks, Lab Weight
* Override ToString() to show
  “The student (studentId) received earnedMarks/totalMarks for this lab.”

Expressions, Math, Exceptions, If-Else, and Case

Topic E – Expressions and Math

Overview

This topic introduces concepts surrounding the use of arithmetic expressions and common Math library routines.

This topic will introduce the following grammars, syntax and language constructs. (Note that additional concepts from previous topics may also be present.)

  • Arithmetic expressions
  • Assignment statements
  • Automatic type conversion and casting
  • Integer division
  • String concatenation
  • Math library routines and constants (such as Random, Square Root, and π)

This topic will also take a deeper look at the distinctive aspects of variables, values and data types as well as demonstrate the use of overloaded constructors. This is also the first foray into creating classes that actually “do something” – these classes not only maintain state but also provide methods to generate other information besides that which is stored in a class’ fields.

LOGs

OOP Basics

  • Explain how method overloading is applied to constructors

General Programming Concepts and Terms

  • Name at least three kinds of program statements commonly seen in all high-level programming languages
  • Distinguish between Variables, Values and Data Types
  • List the five basic rules governing variables, values and data types
  • List the intrinsic (built-in) data types in C#
  • Explain what is meant by the phrase “type extensibility”
  • Define the terms Reference Type and Value Type as they apply to data types in C#
  • Define the term Identifier
  • Create and initialize variables in C#
  • Explain what is meant by the terms “scope” and “lifetime” as they apply to variables
  • Describe what is meant by the term “expression”
  • Explain the difference between program statements and expressions as well as how the two relate to each other
  • List the three general sets of operators in C#
  • Describe the two basic rules of using arithmetic operators that every compiler must follow.
  • Use the arithmetic operators to create arithmetic expressions
  • Explain what is meant by “integer division” and how that can be useful in solving particular problems regarding numbers.
  • Explain the purpose of the modulus (%) operator.
  • List and describe how to use the various assignment operators in C#
  • Explain the difference between binary and unary operators
  • Demonstrate understanding of operator precedence and how to override the default precedence of the arithmetic operators
  • Summarize and distinguish the rules for automatic type conversion involving arithmetic operators and the assignment operator
  • Determine the final data type for expressions involving mixed data types and type conversion
  • Describe “type casting” and explain how to use it appropriately.
  • Compare and contrast the prefix and postfix behaviour of the unary arithmetic operators
  • Identify and explain how to use the common Math library routines (for Power, Square Root, Absolute, random numbers, pi, trigonometry, and the various types of rounding)
  • Use Math rounding methods with arithmetic expressions to round real numbers to a specific precision
  • Create random whole number values within a specific range
  • Use type casting appropriately in C#
  • Create constants in C#
  • Explain how arithmetic operations affect character values in C#
  • List the most common math functions of the Math class
  • Demonstrate how to use the various Math functions in simple programs
  • List and describe the commonly used fields and methods of the String class
  • Demonstrate how to use “String Arithmetic” (concatenation)
  • List the equivalent “wrapper” classes for each of the primitive types.

Code Samples

The following examples are used to illustrate this topic.

  1. Calculator – This class introduces simple arithmetic operations, demonstrating simple addition and multiplication.
  2. Person - This adaptation of the person class changes the previous design by replacing the age field with a “read-only” field for the person’s birth date. The approximate age of the person is then calculated based on the current date and the birth date.
  3. Account - This class illustrates simple addition and calculation by allowing deposits and withdrawals. Note that changes to the balance can now only be made through deposits and withdrawals; the balance is now “read-only”.
  4. ElapsedTime – This class demonstrates overloaded constructors and introduces the concepts of operator precedence and integer division.
  5. ResolveExpressions – This class is used in conjuncture with several sample expressions that illustrate operator precedence and automatic type conversion.
  6. Circle - This class represents a simple circle of a specified diameter. The radius, area and circumference are calculated.
  7. Square - This class represents a simple square with a specified length for its side. The area and perimeter are calculated.
  8. Fraction - This class represents a fraction as a numerator and denominator. It provides the double equivalent of the fraction’s value as well as a string representation that uses the numerator and denominator. It demonstrates type casting and the integer division issue.
  9. Angle - This class represents an angle and provides the value in the following units: degrees, radians and grads. It also gives a simple example of unicode characters (for degrees).
  10. StockItem - This class represents an item that is part of an inventory. The item has an item name, a cost and a profit margin (which can be positive or negative). By using the profit margin, it can derive the price of the item. This example illustrates rounding.
  11. Die - This class represents a single six-sided die. This example is used to illustrate random number generation and casting.
  12. ParkingCounter - This class represents a simple counter to monitor whether a parking lot is full or not; it tracks vehicles entering and leaving the parking lot and allows the counter to be reset when the lot is full or empty. This class illustrates increment and decrement operators and/or the assignment increment or assignment decrement operators.
  13. QuadradicEquation - This class is used to solve for the two possible values of a quadratic formula where quadradic equals zero. This sample illustrates order of operations and parentheses.

Calculator

This class introduces simple arithmetic operations, demonstrating simple addition and multiplication.

Problem Statement

Write the code that will act as a calculator for doing math. This first version must be a working prototype; as a prototype, it does not have to support all of the features of the final product.

The solution must meet the following requirements:

  • Should add two whole numbers.
  • Should multiply two whole numbers.

Use the following class diagram when creating your solution. Since this class does not have properties or fields, make the methods static.

Calculator Class Diagram
 1 public class Calculator
 2 {
 3     public static int Add(int firstNumber, int secondNumber)
 4     {
 5         return firstNumber + secondNumber;
 6     }
 7 
 8     public static int Multiply(int firstNumber, int secondNumber)
 9     {
10         return firstNumber * secondNumber;
11     }
12 }

Person

This adaptation of the person class changes the previous design by replacing the age field with a “read-only” field for the person’s birth date. The approximate age of the person is then calculated based on the current date and the birth date.

Problem Statement

Write the code that will represent a person with a first and last name and a date of birth.
The solution must meet the following requirements (new requirements are in bold):
* Should get and set the first and last name
* Should get the birth date
* Should get the person’s approximate age (which is the age that the person will turn to in the current year)
* Should get the person’s initials
* Should override ToString() to get the person’s full name (as first name then last name)

Use the following class diagram when creating your solution.

Person Class Diagram
 1 public class Person
 2 {
 3     public string FirstName { get; set; }
 4 
 5     public string LastName { get; set; }
 6 
 7     public DateTime BirthDate { get; private set; }
 8 
 9     public int Age
10     {
11         get
12         {
13             int currentAge = 0;
14             currentAge = DateTime.Today.Year - BirthDate.Year;
15             return currentAge;
16         }
17     }
18     public Person(string firstName, string lastName, DateTime birthDate)
19     {
20         FirstName = firstName;
21         LastName = lastName;
22         BirthDate = birthDate;
23     }
24 
25 
26     public override string ToString()
27     {
28         return FirstName + " " + LastName;
29     }
30 
31     public string Initials
32     {
33         get
34         {
35             return FirstName[0] + "." + LastName[0] + ".";
36         }
37     }
38 }

Account

This class illustrates simple addition and calculation by allowing deposits and withdrawals. Note that changes to the balance can now only be made through deposits and withdrawals; the balance is now “read-only”.

Problem Statement

Write the code that will represent a simple bank account.

The solution must meet the following requirements (new requirements are in bold):

  • Should get the bank name, branch number, institution number, account number, balance, overdraft limit, and account type
  • Should allow the overdraft limit to be set
  • Should support deposits and withdrawals

Use the following class diagram when creating your solution.

Account Class Diagram
1   public void Withdraw(double amount)
2   {
3       Balance -= amount;
4   }
5 
6   public void Deposit(double amount)
7   {
8       Balance += amount;
9   }

ElapsedTime

This class demonstrates overloaded constructors and introduces the concepts of operator precedence and integer division.

Problem Statement

Write the code that will represent a period of elapsed time for a competitor in a marathon. It should be able to represent its information in two forms:

  • Hours, minutes and seconds, and
  • Total seconds.

The solution must meet the following requirements:

  • Should calculate the hours, minutes and seconds given the total seconds
  • Should calculate the total seconds given the hours, minutes and seconds

Use the following class diagram when creating your solution.

ElapsedTime Class Diagram
 1 public class ElapsedTime
 2 {
 3     public ElapsedTime(int hours, int minutes, int seconds)
 4     {
 5         TotalSeconds = hours * 60 * 60;
 6         TotalSeconds += minutes * 60;
 7         TotalSeconds += seconds;
 8 
 9         Hours = hours;
10         Minutes = minutes;
11         Seconds = seconds;
12     }
13 
14     public ElapsedTime(int totalSeconds)
15     {
16         Hours = totalSeconds / (60 * 60);
17         Minutes = (totalSeconds - Hours * 60 * 60) / 60;
18         Seconds = totalSeconds - Hours * 60 * 60 - Minutes * 60;
19 
20         TotalSeconds = totalSeconds;
21     }
22 
23     public int Hours { get; private set; }
24 
25     public int Minutes { get; private set; }
26 
27     public int Seconds { get; private set; }
28 
29     public int TotalSeconds { get; private set; }
30 }

ResolveExpressions

This class is used in conjuncture with several sample expressions that illustrate operator precedence and automatic type conversion.

Problem Statement

Write the code that will provide the final value for the expressions in the following exercise (as a solution for a student’s exercise).

Expressions Exercise

On a piece of paper, evaluate the following expressions to show the final value and the data type of the final value. Show the order in which the operations are evaluated.

  1. 10.0 + 15 / 2 + 4.3
  2. 8 / 5 + 1.25
  3. 10.0 + 15.0 / 2 + 4.3
  4. 3.0 * 4 / 6 + 6
  5. 3.0 * (4 % 6) + 6
  6. 3 * 4.0 / 6 + 6
  7. 20.0 - 2 / 6 + 3
  8. 10 + 17 % 3 + 4
  9. (10 + 17) % 3 +4.0
  10. 10 + 17 / 4.0 + 4

The solution for question 2 is provided as an example. Use the accompanying class diagram when creating your coded solution as proof of your final answers.

 1 namespace Topic.E.Examples
 2 {
 3     public class ResolveExpressions
 4     {
 5         public static double Sample1
 6         { get { return 10.0 + 15 / 2 + 4.3; } }
 7 
 8         public static double Sample3
 9         { get { return 10.0 + 15.0 / 2 + 4.3; } }
10 
11         public static double Sample4
12         { get { return 3.0 * 4 / 6 + 6; } }
13 
14         public static double Sample5
15         { get { return 3.0 * (4 % 6) + 6; } }
16 
17         public static double Sample6
18         { get { return 3 * 4.0 / 6 + 6; } }
19 
20         public static double Sample7
21         { get { return 20.0 - 2 / 6 + 3; } }
22 
23         public static int Sample8
24         { get { return 10 + 17 % 3 + 4; } }
25 
26         public static double Sample9
27         { get { return (10 + 17) % 3 + 4.0; } }
28 
29         public static double Sample10
30         { get { return 10 + 17 / 4.0 + 4; } }
31     }
32 }

Circle

This class represents a simple circle of a specified diameter. The radius, area and circumference are calculated.

Problem Statement

Write the code for the Circle class. The solution must meet the following requirements:

  • Should get and set the diameter
  • Should calculate the area, radius, and circumference

Use the following class diagram when creating your solution.

Circle Class Diagram
 1 using System;
 2 namespace Topic.E.Examples
 3 {
 4     public class Circle
 5     {
 6         public Circle(double diameter)
 7         {
 8             this.Diameter = diameter;
 9         }
10 
11         public double Diameter { get; set; }
12 
13         public double Radius
14         { get { return Diameter / 2; } }
15 
16         public double Circumference
17         { get { return Math.PI * Diameter; } }
18 
19         public double Area
20         { get { return Math.PI * Radius * Radius; } }
21     }
22 }

Square

This class represents a simple square with a specified length for its side. The area and perimeter are calculated.

Problem Statement

Write the code for the Square class. The solution must meet the following requirements:

  • Should get and set the length of the side of the square
  • Should calculate the area and perimeter

Use the following class diagram when creating your solution.

Square Class Diagram
 1 namespace Topic.E.Examples
 2 {
 3     public class Square
 4     {
 5         public Square(double side)
 6         {
 7             this.Side = side;
 8         }
 9 
10         public double Side { get; set; }
11 
12         public double Area
13         {
14             get { return Side * Side; }
15         }
16 
17         public double Perimeter
18         {
19             get { return Side * 4; }
20         }
21     }
22 }

Fraction

This class represents a fraction as a numerator and denominator. It provides the double equivalent of the fraction’s value as well as a string representation that uses the numerator and denominator. It demonstrates type casting and the integer division issue.

Problem Statement

Write the code for the Fraction class. The solution must meet the following requirements:

  • Should get the string representation of the fraction, as “numerator/denominator
  • Should get the numeric value of the fraction (as a real number)
  • Should get the reciprocal of the fraction

Use the following class diagram when creating your solution.

Fraction Class Diagram
 1 public class Fraction
 2 {
 3     public int Numerator { get; private set; }
 4 
 5     public int Denominator { get; private set; }
 6 
 7     public Fraction(int numerator, int denominator)
 8     {
 9         Numerator = numerator;
10         Denominator = denominator;
11     }
12 
13     public Fraction Reciprocal
14     {
15         get { return new Fraction(Denominator, Numerator); }
16     }
17 
18     public override string ToString()
19     {
20         string stringValue = "";
21         stringValue += Numerator + "/" + Denominator;
22         return stringValue;
23     }
24 
25     public double ToDouble()
26     {
27         // The casting of numerator to a double helps
28         // ensure that we don't lose any fractional
29         // portion due to integer division.
30         double value = (double)(Numerator) / Denominator;
31         return value;
32     }
33 }

Angle

This class represents an angle and provides the value in the following units: degrees, radians and grads. It also gives a simple example of unicode characters (for degrees).

Problem Statement

Write the code for the Angle class. The solution must meet the following requirements:

  • Should get and set the angle’s value (in degrees)
  • Should calculate the equivalent angle in Radians and Grads, using the following formulas:
  • Radians = Degrees * (π / 180)
  • Grads = Radians * (200 / π)
  • Should override the ToString() method to return the angle in degrees, in the following format:
  • degrees°
  • The Unicode character for the degrees symbol (°) is ‘\u00B0’

Use the following class diagram when creating your solution.

Angle Class Diagram
 1 using System;
 2 namespace Topic.E.Examples
 3 {
 4     public class Angle
 5     {
 6         public Angle(double degrees)
 7         {
 8             this.Degrees = degrees;
 9         }
10 
11         public double Degrees { get; set; }
12 
13         public double Radians
14         {
15             get
16             {
17                 double radians = Degrees * (Math.PI / 180);
18                 return radians;
19             }
20         }
21 
22         public double Grads
23         {
24             get
25             {
26                 double grads = Radians * (200 / Math.PI);
27                 return grads;
28             }
29         }
30 
31         // http://unicode.org/notes/tn28/UTN28-PlainTextMath.pdf
32         // Page 40 of the above reference for the degree symbol
33         public override string ToString()
34         {
35             return Degrees.ToString() + '\u00B0';
36         }
37     }
38 }

StockItem

This class represents an item that is part of an inventory. The item has an item name, a cost and a profit margin (which can be positive or negative). By using the profit margin, it can derive the price of the item. This example illustrates rounding.

Problem Statement

Write the code for the StockItem class. The solution must meet the following requirements:

  • Should get and set the name, cost and profit margin of the stock item
  • Should represent the profit margin as a percent; a value of 45 means 45%
  • Should calculate the price of the item, to the nearest cent
  • Use the rounding where values under a half-cent are rounded down and values greater than or equal to a half-cent are rounded up

Use the following class diagram when creating your solution.

StockItem Class Diagram
 1 using System;
 2 namespace Topic.E.Examples
 3 {
 4     public class StockItem
 5     {
 6         public double Cost { get; set; }
 7 
 8         public double ProfitMargin { get; set; }
 9 
10         public StockItem(string itemName, double cost, double profitMargin)
11         {
12             this.ItemName = itemName;
13             this.Cost = cost;
14             this.ProfitMargin = profitMargin;
15         }
16 
17         public string ItemName { get; set; }
18 
19         public double Price
20         {
21             get
22             {
23                 // Round to the nearest cent
24                 double price = Cost;
25                 price += Cost * (ProfitMargin / 100);
26                 return Math.Round(price * 100) / 100.0;
27             }
28         }
29     }
30 }

Die

This class represents a single six-sided die. This example is used to illustrate random number generation and casting.

Problem Statement

Write the code for the Die class. The solution must meet the following requirements:

  • Should generate a random value from 1 to 6, when initially created and when re-rolled
  • Should get the face value of the die

Use the following class diagram when creating your solution. Note that this uses the Random class as a private static field.

Die Class Diagram
 1 using System;
 2 namespace Topic.E.Examples
 3 {
 4     public class Die
 5     {
 6         private static Random rnd = new Random();
 7 
 8         public Die()
 9         {
10             Roll();
11         }
12 
13         public int FaceValue { get; private set; }
14 
15         public void Roll()
16         {
17             FaceValue = rnd.Next(6000) % 6 + 1;
18         }
19     }
20 }

ParkingCounter

This class represents a simple counter to monitor whether a parking lot is full or not; it tracks vehicles entering and leaving the parking lot and allows the counter to be reset when the lot is full or empty. This class illustrates increment and decrement operators and/or the assignment increment or assignment decrement operators.

Problem Statement

Write the code that will monitor vehicles entering and leaving a parking lot. The solution must meet the following requirements:

  • Should track vehicles entering
  • Should track vehicles leaving
  • Should get total parking spots
  • Should get open (empty) spots
  • Should reset lot as full (that is, fill the parking lot)
  • Should reset lot as empty (that is, clear all the parking spots of vehicles)

Use the following class diagram when creating your solution.

ParkingCounter Class Diagram
 1 namespace Topic.E.Examples
 2 {
 3     public class ParkingCounter
 4     {
 5         public int ParkingSpots { get; private set; }
 6 
 7         public int OpenSpots { get; private set; }
 8 
 9         public ParkingCounter(int parkingSpots)
10         {
11             this.ParkingSpots = parkingSpots;
12             this.OpenSpots = parkingSpots;
13         }
14 
15         public ParkingCounter(int parkingSpots, int numberOfCars)
16         {
17             this.ParkingSpots = parkingSpots;
18             this.OpenSpots = this.ParkingSpots - numberOfCars;
19         }
20 
21         public void Leave()
22         {
23             OpenSpots++;
24         }
25 
26         public void Enter()
27         {
28             OpenSpots--;
29         }
30 
31         public void ResetLotAsEmpty()
32         {
33             OpenSpots = ParkingSpots;
34         }
35 
36         public void ResetLotAsFull()
37         {
38             OpenSpots = 0;
39         }
40     }
41 }

QuadradicEquation

This class is used to solve for the two possible values of a quadratic formula where quadratic equals zero. It is based off of the following formula.

This sample illustrates order of operations and parentheses.

Problem Statement

Write the code that will represent a quadratic equation that has a higher and lower root. It is to use the Quadratic formula, which states:

For ax^2 + bx + c = 0$, the value of x is given by

More information on the quadratic formula can be found at http://www.purplemath.com/modules/quadform.htm.

The solution must meet the following requirements:

  • Should get the lower root, using the quadratic formula
    x=(-b-√(b^2-4ac))/2a$
  • Should get the higher root, using the quadratic formula
    x=(-b+√(b^2-4ac))/2a$
  • Should overload the ToString() method to represent the quadratic formula showing the values for a, b and c in the following format:
    a____x2 + ____b____x + ____c = 0
    For example, given the values of 1, 3 and -4 for a, b and c respectively, the method should produce
    1x2 + 3x + -4 = 0

Use the accompanying class diagram when creating your solution.

QuadraticEquation Class Diagram
 1 using System;
 2 namespace Topic.E.Examples
 3 {
 4     public class QuadraticEquation
 5     {
 6         private int a;
 7         private int b;
 8         private int c;
 9 
10         public QuadraticEquation(int a, int b, int c)
11         {
12             this.a = a;
13             this.b = b;
14             this.c = c;
15         }
16 
17         public double LowerRoot
18         {
19             get
20             {
21                 double value;
22                 value = (-b - Math.Sqrt(b * b - 4 * a * c)) / (2 * a);
23                 return value;
24             }
25         }
26 
27         public double HigherRoot
28         {
29             get
30             {
31                 double value;
32                 value = (-b + Math.Sqrt(b * b - 4 * a * c)) / (2 * a);
33                 return value;
34             }
35         }
36 
37 
38         public override string ToString()
39         {
40             return a.ToString() + "x^2 + " + b + "x + " + c + " = 0";
41         }
42     }
43 }

Practice Exercises

  • Calculator – This exercise expands on the original Calculator class to perform subtraction and division with integers.
  • Fraction – This exercise expands on the original Fraction class to include methods that allow for adding, subtracting, multiplying, and dividing fractions.
  • Square – This exercise expands on the original Square class to include a method that determines the diagonal of a square.
  • Coordinate – Not Yet Implemented The Coordinate class represents a geographical co-ordinate for either longitude or latitude. A Coordinate’s value can be expressed either as a real number or as degrees, minutes and seconds. It makes use of integer division and overloaded constructors.
  • PaintEstimator – The PaintEstimator class is used to estimate the number of paint cans needed for painting a simple room (with or without a window). It makes use of a constant and the Math library; it also uses overloaded constructors.
  • BulkItem – The BulkItem class represents products that are available in bulk and shows the cost of individual items. It makes use of rounding (to two decimal places).
  • Die - This exercise expands on the original Die class to allow for creating a die of any number of sides, with a default of six sides. This means that there is an overloaded constructor.
  • RoundingCalculator – This exercise demonstrates rounding using separate methods for each level of rounding precision.
  • GenericRoundingCalculator – This exercise demonstrates rounding to the nearest whole number of fractional number using a couple of “generic” methods.
  • PeopleCounter – This simple class is used to count the number of people who have entered a store in a single day. It takes a simplistic approach, counting each person entering and leaving, estimating the number of people for the day by dividing the total count by two.
  • ScoreCard – Not Yet Implemented This class represents a scorecard for tracking bowling scores frame by frame. It produces a final tally for the game, as well as the current score and the current frame.
  • Cylinder – The Cylinder class represents a cylindrical object whose height and radius is known. The class provides methods to calculate the volume and surface area.
  • Cone – The Cone class represents a conical object whose height and base radius is known. The class provides methods to determine the volume and surface area with this information.
  • GravityCalculator – The GravityCalculator provides static methods for determining an object’s weight for the various planets in our solar system, given the equivalent weight as found on Earth.
  • CurrencyCalculator – The CurrencyCalculator allows the conversion of US dollars to four other currencies, given the current exchange rate of those currencies.

For these exercises, compare your results with the unit tests for these classes.

Calculator

This exercise expands on the original Calculator class to perform subtraction and division with integers.

Problem Statement

Write the code that will act as a calculator for doing math. This version is a follow-up on the previous prototype; now it should support subtraction and division.

The solution must meet the following requirements:

  • Should add two whole numbers.
  • Should multiply two whole numbers.
  • Should subtract two whole numbers.
  • Should divide two whole numbers.

Use the following class diagram when creating your solution.

Calculator Class Diagram

Fraction

This exercise expands on the original Fraction class to include methods that allow for adding, subtracting, multiplying, and dividing fractions.

Problem Statement

Write the code needed to expand the capabilities of the Fraction class. The class must now support the ability to add, subtract, multiply, and divide fractions as well as allow the individual numerator and denominator values to be seen. The solution must meet the following requirements:

  • Should get the string representation of the fraction, as “numerator/denominator”
  • Should get the numeric value of the fraction (as a real number)
  • Should get the reciprocal of the fraction
  • Should get the numerator and denominator
  • Should add another fraction to its existing value
  • Should subtract another fraction from its existing value
  • Should multiply its existing value by another fraction
  • Should divide its existing value by another fraction

As an assist, the following code can be used for the multiplication method.

1   public void multiplyBy(Fraction otherFraction)
2   {
3       this.numerator = this.numerator * otherFraction.numerator;
4       this.denominator = this.denominator * otherFraction.denominator;
5   }

Use the following class diagram when creating your solution.

Fraction Class Diagram

Square

This exercise expands on the original Square class to include a method that determines the diagonal of a square.

Problem Statement

Write the code needed to add the ability for a Square to determine the length of its diagonal. The solution must meet the following requirements:

  • Should get and set the length of the side of the square.
  • Should calculate the area, perimeter, and diagonal of the square.

Use the following class diagram when creating your solution.

Square Class Diagram

Coordinate

Not Yet Implemented The Coordinate class represents a geographical co-ordinate for either longitude or latitude. A Coordinate’s value can be expressed either as a real number or as degrees, minutes and seconds. It makes use of integer division and overloaded constructors.

Problem Statement

Write the code needed to represent a geographical co-ordinate for longitude and latitude. The solution must meet the following requirements:

  • Should get the type of coordinate (such as “longitude” or “latitude”)
  • Given the hours, minutes and seconds, it
    • should calculate coordinate value as a real number
    • should get hours, minutes, and seconds
  • Given the coordinate value as a real number, it
    • should calculate the hours, minutes and seconds
    • should get the coordinate value as a real number

Use the following class diagram when creating your solution.

Coordinate Class Diagram

PaintEstimator

The PaintEstimator class is used to estimate the number of paint cans needed for painting a simple room (with or without a window). It makes use of a constant and the Math library; it also uses overloaded constructors.

Problem Statement

Write the code needed to help a painter to estimate the number of paint cans to paint simple rooms (with or without a window). The solution must meet the following requirements:

  • Uses a constant value of 8.0 for the paint coverage. (8 square metres per can)
  • Should get room height, width, and length
  • Should get and set the window’s width and height
  • Should calculate the number of paint cans for the room and the window
  • Should calculate the surface area to be painted
  • The room’s height, length and width should have a private set property.

Use the following class diagram when creating your solution.

PaintEstimator Class Diagram

BulkItem

The BulkItem class represents products that are available in bulk and shows the cost of individual items. It makes use of rounding (to two decimal places).

Problem Statement

Write the code for the BulkItem class. The solution must meet the following requirements:

  • Should get and set the cost and quantity of the bulk item
  • Should calculate the cost for each item in the bulk item
  • Should properly round values for currency (either the US or Canadian dollar)
  • The Quantity property’s set should be private.

Use the following class diagram when creating your solution.

Die

This exercise expands on the original Die class to allow for creating a die of any number of sides, with a default of six sides. This means that there is an overloaded constructor.

Problem Statement

Modify the Die class from the examples to support multi-sided die other than just the standard six sides. The solution must meet the following requirements (new requirements are in bold):

  • The Sides and FaceValue properties’ set should be private.
  • Should generate a six-sided die by default
  • Should get the number of sides of the die
  • Should randomly generate each side (if rolled enough); for example, if the die has ten sides, it should eventually roll a 1, 2, 3, 4, 5 6, 7, 8, 9, and 10

Use the following class diagram when creating your solution.

Die Class Diagram

RoundingCalculator

This exercise demonstrates rounding using separate methods for each level of rounding precision.

Problem Statement

Write the code needed to provide rounding of various degrees of accuracy. The solution must meet the following requirements:

  • All of the methods should be static.
  • Should correctly round up to the nearest thousand
  • Should correctly round down to the nearest thousand
  • Should correctly round up to the nearest hundred
  • Should correctly round down to the nearest hundred
  • Should correctly round up to the nearest ten
  • Should correctly round down to the nearest ten
  • Should correctly round up to the nearest one
  • Should correctly round down to the nearest one
  • Should correctly round up to the nearest tenth
  • Should correctly round down to the nearest tenth
  • Should correctly round up to the nearest hundredth
  • Should correctly round down to the nearest hundredth

Use the following class diagram when creating your solution.

RoundingCalculator Class Diagram

GenericRoundingCalculator

This exercise demonstrates rounding to the nearest whole number of fractional number using a couple of “generic” methods.

Problem Statement

Write the code needed to perform rounding to either whole numbers or fractions at a specified level of precision. The solution must meet the following requirements:

  • All of the methods should be static.
  • Should correctly round up or down to the nearest whole number, such as
    • the nearest thousand
    • the nearest hundred
    • the nearest ten
    • the nearest one
  • Should correctly round up or down to the nearest fractional value, such as
    • the nearest tenth
    • the nearest hundredth

Use the following class diagram when creating your solution.

GenericRoundingCalculator Class Diagram

PeopleCounter

This simple class is used to count the number of people who have entered a store in a single day. It takes a simplistic approach, counting each person entering and leaving, estimating the number of people for the day by dividing the total count by two.

Problem Statement

Write the code needed to track people entering and leaving a store. It must be able to estimate the number of people that have entered the store at the end of the day. The solution must meet the following requirements:

  • The Count property should have a private set.
  • Should default to having a count of zero people when first started up
  • Should increment by one (that is, count a single person)
  • Should increment by a specified quantity (for when a group of people enter)
  • Should adequately estimate the number of people who entered the store, assuming that each person who enters also leaves the store
    • Each estimate should be rounded down; for example, if 15 people are counted, then the estimate should be for only 7 (not 7.5 or 8)

Use the following class diagram when creating your solution.

PeopleCounter Class Diagram

ScoreCard

Not Yet Implemented This class represents a scorecard for tracking bowling scores frame by frame. It produces a final tally for the game, as well as the current score and the current frame.

Problem Statement

Write the code needed to.

The solution must meet the following requirements:

  • Should

Use the following class diagram when creating your solution.


### Cylinder

The Cylinder class represents a cylindrical object whose height and radius is known. The class provides methods to calculate the volume and surface area.

Problem Statement

Write the code for the Cylinder class that meets the following requirements:

  • The Radius and Height properties should have a private set.
  • Should get the radius and the height
  • Should calculate the volume and the surface area
    • Volume of a Cylinder = pi * r^2 * h$
    • Surface Area of a Cylinder = 2 * pi * r^2 + 2 * pi * r * h$

Use the following class diagram when creating your solution.

Cylinder Class Diagram

Cone

The Cone class represents a conical object whose height and base radius is known. The class provides methods to determine the volume and surface area with this information.

Problem Statement

Write the code for the Cone class that meets the following requirements:

  • The Radius and Height properties should have a private set.
  • Should get the radius and the height
  • Should calculate the volume and the surface area
    • Volume of a Cone = 1/3 * pi * r^2 * h$
    • Surface Area of a Cone = pi * r^2 + pi * r * sqrt(r^2 + h^2)$

Note that the portion sqrt(r^2 + h^2)$ is known as the slant height.

Use the following class diagram when creating your solution.

Cone Class Diagram

GravityCalculator

The GravityCalculator provides static methods for determining an object’s weight for the various planets in our solar system, given the equivalent weight as found on Earth.

Problem Statement

Write the code needed to convert Earth weights to their equivalent for the other planets in our solar system. The solution must meet the following requirements:

  • All the methods should be static.
  • Should convert a weight in Earth kilograms to their equivalent weight on
    • Mercury
    • Venus
    • Mars
    • Jupiter
    • Saturn
    • Uranus
    • Neptune
  • For information on equivalent weights among the planets, see these URLS.
    • NinePlanets.org
    • http://www.serve.com/chunter/index/info/aweigh.html

Use the following class diagram when creating your solution.

GravityCalculator Class Diagram

CurrencyCalculator

The CurrencyCalculator allows the conversion of US dollars to four other currencies, given the current exchange rate of those currencies.

Problem Statement

A currency exchange store at the international airport needs a program to convert from US dollars to four other currencies: Canadian dollar, Euro, Japanese Yen, and the Great Britain Pound. The store uses a set exchange rate for each currency as established at the start of the day. Write the code for a class called CurrencyCalculator to meet this need. The solution must meet the following requirements:

  • Should correctly convert US dollars to the
    • British Pound (GBP)
    • Canadian Dollar (CAD)
    • Euro (EUR)
    • Japanese Yen (JPY)
  • Should use the correct level of precision when making the exchange; each currency uses a different number of significant digits:
    • CAD, GBP and EUR use two digits
    • JPY uses three digits

To illustrate the possible exchange rates, please refer to the following images.

Currency exchange rates sourced from http://www.x-rates.com

Use the following class diagram when creating your solution.

CurrencyCalculator Class Diagram

As a starter, you can use the following code to begin creating your class.

 1 public class CurrencyCalculator
 2 {
 3     // The following are multipliers to convert the
 4     // US dollar to different currencies.
 5     /* The multiplier to convert US dollars to Canadian dollars. */
 6     private double _ToCanadian;  // CAD - Canadian Dollar
 7     /* The multiplier to convert US dollars to the Euro. */
 8     private double _ToEuro;      // EUR - Euro
 9     /* The multiplier to convert US dollars to the Japanese Yen. */
10     private double _ToYen;       // JPY - Japanese Yen
11     /* The multiplier to convert US dollars to the British Pound. */
12     private double _ToPound;     // GBP - Great Britain Pound
13     
14     /* The number of significant digits for the Canadian dollar.
15      * The unit for portions of a dollar is the Cent. */
16     private static int _CadDigits = 2; // Cents
17     /* The number of significant digits for the Euro.
18      * The unit for portions of a dollar is the Cent. */
19     private static int _EuroDigits = 2; // Cents
20     /* The number of significant digits for the Japanese Yen.
21      * The unit for 1/100<sup>th</sup> portions of the Yen is the Sen,
22      * while each 1/1000<sup>th</sup> is known as a Rin. */
23     private static int _YenDigits = 3; // 1/100 is sen, 1/1000 is rin
24     /* The number of significant digits for the British Pound.
25      * The unit for portions of a Pound is the Pence (or P). */
26     private static int _PoundDigits = 2; // Pence (or p)
27     
28     /*
29      * This constructor initializes a CurrencyCalculator object
30      * by taking the supplied parameter values and storing
31      * them in the fields of this instance of the class.
32      */
33     public CurrencyCalculator(double toCanadian, double toEuro, double toYen,
34             double toPound)
35     {
36         // Your code goes here...
37     }
38 
39     /* ************** Methods **************** */
40     // Your code goes here...
41 }

Topic F – If-Else Structures

Overview

This topic introduces the if-else control flow statement and demonstrates both simple and complex conditional expressions. This topic will also introduce how to nest program statements.

LOGs

General Programming Concepts and Terms

  • Describe and draw a diagram of the If-Then-Else logical structure
  • Identify the programming statement that corresponds to the If-Then-Else logical structure
  • Translate If-Then-Else structures into code
  • Describe what is meant by a “conditional expression”
  • List the operator precedence for mixing logical, arithmetic, and relational operations
  • List the relational operators
  • List the logical operators
  • Use relational, logical, and arithmetic operators to construct conditional expressions
  • Demonstrate an understanding of operator precedence in conditional expressions
  • Use statement blocks to allow nesting program statements into control structures
  • Define the term “boundary condition” as it relates to if-else statements and testing
  • Identify the correct way to compare or check the contents of strings in conditional expressions
  • List and describe the commonly used properties and methods of the String class that would be used in if-else statements

Code Samples

The following examples are used to illustrate this topic.

  1. StockItem - This class represents an item that is part of an inventory. The item has an item name, a cost and a profit margin (which can be positive or negative). By using the profit margin, it can derive the price of the item. The class can also report if the item is priced at or below cost.
  2. Account - This class illustrates simple if structure in handling withdrawals; withdrawals are only made when the amount does not exceed the balance and the overdraft. It also identifies if the account is overdrawn.
  3. Person - This adaptation of the person class checks the age of the person to see if the person’s life stage is infant, toddler, preschooler, school age, or adult.
  4. Fraction - This class now ensures that any negative denominators have their negative sign “moved” to the numerator. It also recognizes whether a fraction is proper (numerator less than denominator) or not and provides a method to express the fraction as a mixed number string.
  5. Angle - This version of the Angle class includes an attribute to identify the type of the angle as either acute, right, obtuse, straight, reflex, full rotation, or undefined.
  6. ParkingCounter - This class represents a simple counter to monitor whether a parking lot is full or not; it tracks vehicles entering and leaving the parking lot and allows the counter to be reset when the lot is full or empty. This class illustrates increment and decrement operators and/or the assignment increment or assignment decrement operators.
  7. MemoryAddress - This class represents a single memory address in both its base 10 and hexadecimal value.
  8. Color - This class represents a color as three base-10 RGB values and as a single hexadecimal value.

StockItem

This class represents an item that is part of an inventory. The item has an item name, a cost and a profit margin (which can be positive or negative). By using the profit margin, it can derive the price of the item. The class can also report if the item is priced at or below cost.

Problem Statement

Write the code for the StockItem class. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the name, cost and profit margin of the stock item
  • Should represent the profit margin as a percent; a value of 45 means 45%
  • Should calculate the price of the item, to the nearest cent
    • Use the rounding where values under a half-cent are rounded down and values greater than or equal to a half-cent are rounded up
  • Should recognize when the stock item is priced at cost (that is, the profit margin is zero)
  • Should recognize when the stock item is priced below cost (that is, the profit margin is negative)

Use the following class diagram when creating your solution.

StockItem Class Diagram
 1   public bool IsPricedAtCost
 2   {
 3       get
 4       {
 5           bool atCost = false;
 6           if (ProfitMargin == 0)
 7               atCost = true;
 8           return atCost;
 9       }
10   }
11 
12   public bool IsPricedBelowCost
13   {
14       get
15       {
16           bool belowCost;
17           if (ProfitMargin < 0)
18               belowCost = true;
19           else
20               belowCost = false;
21           return belowCost;
22       }
23   }

Account

This class illustrates simple if structure in handling withdrawals; withdrawals are only made when the amount does not exceed the balance and the overdraft. It also identifies if the account is overdrawn.

Problem Statement

Write the code that will represent a simple bank account. The solution must meet the following requirements (new requirements are in bold):

  • Should get the bank name, branch number, institution number, account number, balance, overdraft limit, and account type and allow the overdraft limit to be set
  • Should support deposits
  • Should only support withdrawals if the amount does not exceed the sum of the balance and the overdraft limit
  • Should identify if the account is overdrawn

Use the following class diagram when creating your solution.

Account Class Diagram
 1   public double Withdraw(double amount)
 2   {
 3       if (amount <= Balance + OverdraftLimit)
 4           Balance = Balance - amount;
 5       else
 6           amount = 0;
 7       return amount;
 8   }
 9 
10   public bool IsOverdrawn
11   {
12       get
13       {
14           bool overdrawn;
15           if (Balance < 0)
16               overdrawn = true;
17           else
18               overdrawn = false;
19           return overdrawn;
20       }
21   }

Person

This adaptation of the person class checks the age of the person to see if the person’s life stage is infant, toddler, preschooler, school age, or adult.

Problem Statement

Write the code that will represent a person with a first and last name and a date of birth. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the first and last name
  • Should get the birth date
  • Should get the person’s approximate age (which is the age that the person will turn to in the current year)
  • Should override ToString() to get the person’s full name (as first name then last name)
  • Should get the life stage, based on the following table
Age Range (Years) Life Stage
0 Infant
< 3 Toddler
< 5 Preschooler
< 18 School age
>= 18 Adult

Use the following class diagram when creating your solution.

 1   public string LifeStage
 2   {
 3     get{
 4       string stage;
 5       if (Age == 0)
 6           stage = "infant";
 7       else if (Age < 3)
 8           stage = "toddler";
 9       else if (Age < 5)
10           stage = "preschooler";
11       else if (Age < 18)
12           stage = "school age";
13       else
14           stage = "adult";
15       return stage;
16     }
17   }

Fraction

This class now ensures that any negative denominators have their negative sign “moved” to the numerator. It also recognizes whether a fraction is proper (numerator less than denominator) or not and provides a method to express the fraction as a mixed number string.

Problem Statement

Write the code for the Fraction class. The solution must meet the following requirements (new requirements are in bold):

  • Should get the string representation of the fraction, as “numerator/denominator”
  • Should get the numeric value of the fraction (as a real number)
  • Should get the reciprocal of the fraction
  • Should get the numerator and denominator
  • Should add another fraction to its existing value
  • Should subtract another fraction from its existing value
  • Should multiply its existing value by another fraction
  • Should divide its existing value by another fraction
  • Should affix the sign for negative fractions onto the numerator only
  • Should identify if the fraction is a proper fraction
  • Should express the fraction as a mixed number string

Use the following class diagram when creating your solution.

 1     public Fraction(int numerator, int denominator)
 2     {
 3         Numerator = numerator;
 4         Denominator = denominator;
 5         FixSign();
 6     }
 7 
 8     private void FixSign()
 9     {
10         if (Denominator < 0)
11         {
12             Denominator *= -1;
13             Numerator *= -1;
14         }
15     }
16 
17     public bool IsProper
18     {
19         get
20         {
21             bool proper;
22             if (Numerator < Denominator)
23                 proper = true;
24             else
25                 proper = false;
26             return proper;
27         }
28     }
29 
30     public override string ToString()
31     {
32         string stringValue = "";
33         if(IsProper)
34             stringValue += (Numerator / Denominator) + " and " 
35                          + (Numerator % Denominator) + "/" + Denominator;
36         else
37             stringValue += Numerator + "/" + Denominator;
38         return stringValue;
39     }

Angle

This version of the Angle class includes an attribute to identify the type of the angle as either acute, right, obtuse, straight, reflex, full rotation, or undefined.

Problem Statement

Write the code for the Angle class. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the angle’s value (in degrees)
  • Should calculate the equivalent angle in Radians and Grads, using the following formulas:
    • Radians = Degrees * (π / 180)
    • Grads = Radians * (200 / π)
  • Should override the toString() method to return the angle in degrees, in the following format:
    • degrees°
    • The Unicode character for the degrees symbol (°) is ‘\u00B0’
  • Should get the type of angle, based on the following table
Angle Range Angle Type
< = 0 or > 360 Undefined
> 0 and < 90 Acute
= 90 Right
> 90 and < 180 Obtuse
= 180 Straight
> 180 and < 360 Reflex
= 360 Full Rotation

Use the following class diagram when creating your solution.

 1   public string AngleType
 2   {
 3       get
 4       {
 5           string angleType;
 6           if (Degrees <= 0)
 7               angleType = "undefined";
 8           else if (Degrees < 90)
 9               angleType = "acute";
10           else if (Degrees == 90)
11               angleType = "right";
12           else if (Degrees < 180)
13               angleType = "obtuse";
14           else if (Degrees == 180)
15               angleType = "straight";
16           else if (Degrees < 360)
17               angleType = "reflex";
18           else if (Degrees == 360)
19               angleType = "full rotation";
20           else
21               angleType = "undefined";
22           return angleType;
23       }
24   }

ParkingCounter

This class represents a simple counter to monitor whether a parking lot is full or not; it tracks vehicles entering and leaving the parking lot and allows the counter to be reset when the lot is full or empty. This class illustrates increment and decrement operators and/or the assignment increment or assignment decrement operators.

Problem Statement

Write the code that will monitor vehicles entering and leaving a parking lot. The solution must meet the following requirements (new requirements are in bold):

  • Should track vehicles entering
  • Should track vehicles leaving
  • Should track the peak occupancy of the parking lot
    • The peak occupancy represents the highest number of cars in the parking lot at any one time
  • Should get total parking spots
  • Should get open (empty) spots
  • Should reset lot as full (that is, fill the parking lot)
  • Should reset lot as empty (that is, clear all the parking spots of vehicles)

Use the following class diagram when creating your solution.

 1     public int PeakOccupancy { get; private set; }
 2 
 3     public ParkingCounter(int parkingSpots)
 4     {
 5         this.ParkingSpots = parkingSpots;
 6         this.OpenSpots = parkingSpots;
 7         this.PeakOccupancy = 0;
 8     }
 9 
10     public ParkingCounter(int parkingSpots, int numberOfCars)
11     {
12         this.ParkingSpots = parkingSpots;
13         this.OpenSpots = this.ParkingSpots - numberOfCars;
14         this.PeakOccupancy = numberOfCars;
15     }
16 
17     public void enter()
18     {
19         OpenSpots--;
20         int numberOfCars = ParkingSpots - OpenSpots;
21         if (numberOfCars > PeakOccupancy)
22             PeakOccupancy = numberOfCars;
23     }

MemoryAddress

This class represents a single memory address in both its base 10 and hexadecimal value.

Base ten is the common number system that we use in every day life. Base ten uses the digits 0-9 and the concept of the position of a digit occupying some multiple of ten. Thus, for the number 129 there is a hundreds-position (102), a tens-position (101) and a ones-position (10^0).

 1 129 base 10
 2 ||\
 3 |\ \_ 10^0 * 9 =>   9
 4 | \
 5 \  \_ 10^2 * 2 =>  20
 6  \
 7   \
 8    \_ 10^3 * 1 => 100
 9                  ====
10                   129

Converting a value from one base to another (such as base-10 to base-16) involves thinking about the digit positions of the target base. Base 16 uses the digits 0-9 along with the letters A through F for the range of hex values zero to fifteen. Each digit position in a base-16 number can hold a value of 0 to F. Thus, a digit in the ones position is worth 1 times the digit. A two-digit hex value would have the sixteens-position (161) and a ones-position (160). A three-digit hex value would add onto that a two-hundred-and-fifty-sixth-position (16^2). For example, to convert the number 679 base 10 to a base 16, you would follow these steps.

  • Divide the original number by the two-hundred-and-fifty-sixth-position (162). Then use the remainder in calculating the next position (161). \include{longdiv} \longdiv{679}{256}$
  • Dividing the previous steps remainder (167) by 16 gives the result of 10, which is the hex-digit of A. \include{longdiv} \longdiv{167}{16}$
  • The remainder of that last step is the ones-position
  • Thus, the base-10 value 679 is 2B9 in base-16.
 1 2B9 base 16
 2 ||\
 3 |\ \_ 16^0 * 9  =>    9
 4 | \
 5 \  \_ 16^2 * 11 =>  176
 6  \
 7   \
 8    \_ 16^3 * 2  =>  512
 9                    ====
10                     679 base 10

The following class demonstrates a small memory address (up to four hexadecimal digits) as a short and a string representation of hexadecimal.

 1     public class MemoryAddress
 2     {
 3         public short Base10Value { get; private set; }
 4         public string HexValue
 5         {
 6             get
 7             {
 8                 string hex = "0x";
 9                 // A short number in hexadecimal 
10                 // will be at most 4 digits
11                 //    FFFF
12                 //    ||||
13                 //    |||- 16^0 =>    1
14                 //    ||-- 16^1 =>   16
15                 //    |--- 16^2 =>  256
16                 //    ---- 16^3 => 4096
17                 int value = Base10Value;
18                 int portion = value / 4096;
19                 hex += ToHexDigit(portion);
20                 value -= portion;
21                 portion = value / 256;
22                 hex += ToHexDigit(portion);
23                 value -= portion;
24                 portion = value / 16;
25                 hex += ToHexDigit(portion);
26                 portion = value % 16;
27                 hex += ToHexDigit(portion);
28                 return hex;
29             }
30         }
31 
32         public MemoryAddress(short address)
33         {
34             Base10Value = address;
35         }
36 
37         private static string ToHexDigit(int number)
38         {
39             string result;
40             if (number < 10)
41                 result = number.ToString();
42             else if (number == 10)
43                 result = "A";
44             else if (number == 11)
45                 result = "B";
46             else if (number == 12)
47                 result = "C";
48             else if (number == 13)
49                 result = "D";
50             else if (number == 14)
51                 result = "E";
52             else if (number == 15)
53                 result = "F";
54             else // Should never happen...
55                 result = "";
56 
57             return result;
58         }
59     }

Color

This class represents a color as three base-10 RGB values and as a single hexadecimal value.

Problem Statement

Create a data type to represent a color as both base-10 RBG values and as a hexadecimal value.

 1     public class Color
 2     {
 3         public byte Red { get; private set; }
 4         public byte Blue { get; private set; }
 5         public byte Green { get; private set; }
 6 
 7         public string Hex
 8         {
 9             get
10             {
11                 string converted = "#";
12                 converted += ToHexDigit((byte)(Red / _Base16))
13                            + ToHexDigit((byte)(Red % _Base16));
14                 converted += ToHexDigit((byte)(Blue / _Base16))
15                            + ToHexDigit((byte)(Blue % _Base16));
16                 converted += ToHexDigit((byte)(Green / _Base16))
17                            + ToHexDigit((byte)(Green % _Base16));
18                 return converted;
19             }
20         }
21 
22         private static byte _Base16 = (byte)16;
23         private static string ToHexDigit(byte number)
24         {
25             string result;
26             if (number < 10)
27                 result = number.ToString();
28             else if (number == 10)
29                 result = "A";
30             else if (number == 11)
31                 result = "B";
32             else if (number == 12)
33                 result = "C";
34             else if (number == 13)
35                 result = "D";
36             else if (number == 14)
37                 result = "E";
38             else if (number == 15)
39                 result = "F";
40             else
41                 result = "";
42 
43             return result;   
44         }
45 
46         public Color(byte red, byte blue, byte green)
47         {
48             Red = red;
49             Blue = blue;
50             Green = green;
51         }
52     }

## Practice Excercises

  • Rectangle – “All squares are rectangles, but not all rectangles are squares.” This class represents a simple rectangle with a height and width. From this information, the area, perimeter and diagonal can be obtained; it can also be determined if the rectangle is or is not square.
  • HazardousMaterial – The HazardousMaterial class is a simple representation of the six main classes of hazardous materials (A through F). This class maps a classification code with a general description of the material’s classification:
    • Class A – Compressed Gas
    • Class B – Flammable and Combustible Material
    • Class C – Oxidizing Material
    • Class D – Poisonous and Infectious Material
    • Class E – Corrosive Material
    • Class F – Dangerously Reactive Material
  • CurrencyCalculator – This exercise extends the previous CurrencyCalculator exercise by allowing the conversion from a foreign currency to US dollars.
  • GravityCalculator – This exercise extends the previous GravityCalculator exercise by allowing the conversion to a weight on Earth from a weight on another planet in our solar system.

Rectangle

“All squares are rectangles, but not all rectangles are squares.” This class represents a simple rectangle with a height and width. From this information, the area, perimeter and diagonal can be obtained; it can also be determined if the rectangle is or is not square.

Problem Statement

Write the code for the Rectangle class. The solution must meet the following requirements:

  • Should get and set the height and the width
  • Should calculate the area, the perimeter and the diagonal
  • The formula for the diagonal is √(〖width〗2 + 〖height〗2 )
  • Should determine if the rectangle is a square

Use the following class diagram when creating your solution.

HazardousMaterial

The HazardousMaterial class is a simple representation of the six main classes of hazardous materials (A through F). This class maps a classification code with a general description of the material’s classification:

  • Class A – Compressed Gas
  • Class B – Flammable and Combustible Material
  • Class C – Oxidizing Material
  • Class D – Poisonous and Infectious Material
  • Class E – Corrosive Material
  • Class F – Dangerously Reactive Material

Problem Statement

Write the code for the HazardousMaterial class. The solution must meet the following requirements:

  • Should return the class code as the classification
  • Should get the description for the class, based on the following table
Class Code Description
A Compressed Gas
B Flammable and Combustible Material
C Oxidizing Material
D Poisonous and Infectious Material
E Corrosive Material
F Dangerously Reactive Material
  • Should override the ToString() method to get the full description and class code in the following format:
  • “Class ClassCode - Description”

Use the following class diagram when creating your solution.

CurrencyCalculator

This exercise extends the previous CurrencyCalculator exercise by allowing the conversion from a foreign currency to US dollars.

Problem Statement

A currency exchange store at the international airport needs a program to convert from US dollars to four other currencies: Canadian dollar, Euro, Japanese Yen, and the Great Britain Pound. The store uses a set exchange rate for each currency as established at the start of the day. Write the code for a class called CurrencyCalculator to meet this need. The solution must meet the following requirements (new requirements are in bold):

  • Should correctly convert US dollars to the
    • British Pound (GBP)
    • Canadian Dollar (CAD)
    • Euro (EUR)
    • Japanese Yen (JPY)
  • Should convert an amount to US dollars from any of the supported currencies (GBP, CAD, JPY, and EUR)
  • Should use the correct level of precision when making the exchange; each currency uses a different number of significant digits:
    • CAD, GBP and EUR use two digits
    • JPY uses three digits

To illustrate the possible exchange rates, please refer to the following images.

Use the following class diagram when creating your solution.

GravityCalculator

This exercise extends the previous GravityCalculator exercise by allowing the conversion to a weight on Earth from a weight on another planet in our solar system.

Problem Statement

Write the code needed to convert Earth weights to their equivalent for the other planets in our solar system. The solution must meet the following requirements (new requirements are in bold):

  • Should convert a weight in Earth kilograms to their equivalent weight on
    • Mercury
    • Venus
    • Mars
    • Jupiter
    • Saturn
    • Uranus
    • Neptune
  • Should convert a weight from a specific planet back to the equivalent weight on Earth

Use the following class diagram when creating your solution.

Topic G – Raising Exceptions

Overview

This topic introduces the throw statement and exceptions. The following new keywords are introduced.
* throw
* throws

This topic will demonstrate objects that are capable of validating information supplied to them. This introduces the principle in object oriented design that well designed objects are capable of ensuring the validity of their internal state. When invalid information is supplied, either through the constructor or through other methods, objects can respond by raising exceptions.

LOGs

General Programming Concepts and Terms

  • Describe how object-oriented programs run
  • Describe what is meant by a “call stack”
  • Define the term “Exception”
  • Describe what is meant by the phrase “raising (or throwing) an exception”
  • Describe the role that exceptions play in a computer program
  • Identify the three most commonly used Exception types used in this course

OOP Basics

  • Explain why methods (including constructors) should perform validation of their parameter values
  • Explain the significance of raising an exception in the constructor
  • Use exceptions as part of the validation of parameter values in methods and constructors
  • Explain why property setters are a good place for throwing exceptions
  • Identify when constructors should throw exceptions directly

Code Samples

  1. Fraction – The fraction class avoid the division by zero error by ensuring that the supplied denominator is not zero.
  2. Square – Only accepts positive, non-zero lengths for the side.
  3. Circle – Only accepts positive, non-zero diameters.
  4. Die – Only accepts from 4 to 20 sides for a die.
  5. Person – First and last names cannot be empty and the birth date cannot be in the future. This illustrates putting the validation on the setters and calling the setters from the constructor (to reduce the duplication of code).
  6. Student – Gender must be ‘M’ or ‘F’ (and will be converted to upper-case). The student name and program cannot be empty. The student ID must be 9 digits. The GPA must be between 0.0 and 9.0 (inclusive).
  7. ParkingCounter – Only accepts positive, non-zero counts for available parking spaces and number of cars. Also, the number of cars must not exceed the number of parking spaces. The rules for the number of cars must also apply for cars entering and leaving the parking lot.
  8. StockItem – Represents an inventory item that is kept in stock. The item’s description, cost and profit margin are all part of the class design. Empty descriptions and zero or negative costs, as well as profit margins less than -100, are not allowed.
  9. Account – The following account information is now verified when the class is created:
  10. Bank name and account type cannot be empty
  11. The opening balance must be greater than zero
  12. The overdraft limit cannot be negative
  13. The institution number must be 3 digits
  14. The branch number must be 6 digits
  15. Attempts to withdraw amounts beyond the overdraft limit should throw an “Insufficient Funds” exception

Fraction

The fraction class avoids the division by zero error by ensuring that the supplied denominator is not zero.

Problem Statement

Write the code for the Fraction class. The solution must meet the following requirements (new requirements are in bold):
* Should get the string representation of the fraction, as “numerator/denominator”
* Should get the numeric value of the fraction (as a real number)
* Should get the reciprocal of the fraction
* Should get the numerator and denominator
* Should add another fraction to its existing value
* Should subtract another fraction from its existing value
* Should multiply its existing value by another fraction
* Should divide its existing value by another fraction
* Should affix the sign for negative fractions onto the numerator only
* Should identify if the fraction is a proper fraction
* Should reject zero denominators

Use the following class diagram when creating your solution.

1     public Fraction(int numerator, int denominator)
2     {
3         if (denominator == 0)
4             throw new System.Exception("A fraction cannot have a denominator of \
5 zero (0)");
6         Numerator = numerator;
7         Denominator = denominator;
8         FixSign();
9     }

Square

Only accepts positive, non-zero lengths for the side.

Problem Statement

Write the code needed to add the ability for a Square to determine the length of its diagonal. The solution must meet the following requirements (new requirements are in bold):
* Should get and set the length of the side of the square
* Should calculate the area, perimeter, and diagonal of the square
* Should only accept positive, non-zero lengths for the side

Use the following class diagram when creating your solution.

 1     private double _Side;
 2     public double Side
 3     {
 4         get
 5         {
 6             return _Side;
 7         }
 8         set
 9         {
10             if (value <= 0)
11                 throw new System.Exception("A square must have a positive non-ze\
12 ro length for its side");
13             _Side = value;
14         }
15     }

Circle

Only accepts positive, non-zero diameters.

Problem Statement

Write the code for the Circle class. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the diameter
  • Should calculate the area, radius, and circumference
  • Should only accept positive, non-zero lengths for the diameter

Use the following class diagram when creating your solution.

 1     private double _Diameter;
 2     public double Diameter
 3     {
 4         get
 5         {
 6             return _Diameter;
 7         }
 8         set
 9         {
10             if (value <= 0)
11                 throw new System.Exception("Diameter must be a positive non-zero\
12  value");
13             _Diameter = value;
14         }
15     }

Die

Only accepts from 4 to 20 sides for a die. This class represents a single six-sided die. This example is used to illustrate random number generation and casting.

Problem Statement

Write the code for the Die class. The solution must meet the following requirements (new requirements are in bold):

  • Should generate a random value from 1 to the number of sides on the die, when initially created and when re-rolled
  • Should get the face value of the die
  • Should get the number of sides of the die
  • Should randomly generate each side (if rolled enough); for example, if the die has ten sides, it should eventually roll a 1, 2, 3, 4, 5 6, 7, 8, 9, and 10
  • Should only accept 4 to 20 sides for the die

Use the following class diagram when creating your solution.

1     public Die(int sides)
2     {
3         if (sides < 4 || sides > 20)
4             throw new System.Exception("A die can only have from 4 to 20 sides");
5         this.Sides = sides;
6         Roll();
7     }

Person

First and last names cannot be empty and the birth date cannot be in the future. This illustrates putting the validation on the setters and calling the setters from the constructor (to reduce the duplication of code).

This adaptation of the person class includes a check of the age of the person to see if the person’s life stage is infant, toddler, preschooler, school age, or adult.

Problem Statement

Write the code that will represent a person with a first and last name and a date of birth. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the first and last name
  • Should get the birth date
  • Should get the person’s approximate age (which is the age that the person will turn to in the current year)
  • Should override toString() to get the person’s full name (as first name then last name)
  • Should get the life stage, based on the following table
Age Range (Years) Life Stage
0 Infant
< 3 Toddler
< 5 Preschooler
< 18 School age
>= 18 Adult
  • Should ensure the first and last names are not empty (or null)
  • Should trim leading and trailing spaces from the first and last names
  • Should reject birthdates that are in the future

Use the following class diagram when creating your solution.

 1     private string _FirstName;
 2     public string FirstName
 3     {
 4         get
 5         {
 6             return _FirstName;
 7         }
 8         set
 9         {
10             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
11 ))
12                 throw new Exception("FirstName cannot be empty");
13             _FirstName = value.Trim();
14         }
15     }
16 
17     private string _LastName;
18     public string LastName
19     {
20         get
21         {
22             return _LastName;
23         }
24         set
25         {
26             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
27 ))
28                 throw new Exception("LastName cannot be empty");
29             _LastName = value.Trim();
30         }
31     }
32 
33     public Person(string firstName, string lastName, DateTime birthDate)
34     {
35         if (birthDate.CompareTo(DateTime.Today) > 0)
36             throw new System.Exception("Birthdates in the future are not allowed\
37 ");
38         FirstName = firstName;
39         LastName = lastName;
40         BirthDate = birthDate;
41     }

Student

Gender must be ‘M’ or ‘F’ (and will be converted to upper-case). The student name and program cannot be empty. The student ID must be 9 digits. The GPA must be between 0.0 and 9.0 (inclusive).

Problem Statement

Write the code for the Student class. The class must now ensure that the supplied information is valid. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the student’s name, gender, GPA, program of studies, and whether or not the student is full-time.
  • Should override the toString() method to get the student’s ID and name in this format:
    (ID) Name
  • Should n * longer allow the student ID to be set (it’s only set through the constructor)
  • Should reject empty text (and null values) for the student’s name and program of studies.
  • Should trim the student’s name and the program name
  • Should only accept ‘M’ and ‘F’ as valid genders
  • Should set the gender to upper-case
  • Should reject negative GPAs and GPAs over 9
  • Should require a nine-digit student ID

This class reinforces the idea of encapsulation and constructors. It also demonstrates the idea of overloading the default ToString() method that every class inherits from the Object class.

  1 public class Student
  2 {
  3     #region Fields
  4     private string _Name;
  5     private char _Gender;
  6     private int _StudentId;
  7     private string _Program;
  8     private double _GradePointAverage;
  9     private bool _IsFullTime;
 10     #endregion
 11 
 12     #region Properties
 13     public string Name
 14     {
 15         get { return _Name; }
 16         set
 17         {
 18             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
 19 ))
 20                 throw new System.Exception("Name cannot be empty");
 21             _Name = value.Trim();
 22         }
 23     }
 24 
 25     public char Gender
 26     {
 27         get { return _Gender; }
 28         set
 29         {
 30             value = char.ToUpper(value);
 31             if (value != 'M' && value != 'F')
 32                 throw new Exception("Gender must be M or F");
 33             _Gender = value;
 34         }
 35     }
 36 
 37     public int StudentId
 38     {
 39         get { return _StudentId; }
 40         set
 41         {
 42             if (value < 100000000 || value > 999999999)
 43                 throw new Exception("Student Ids must be 9 digits");
 44             _StudentId = value;
 45         }
 46     }
 47 
 48     public string Program
 49     {
 50         get { return _Program; }
 51         set
 52         {
 53             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
 54 ))
 55                 throw new Exception("Program cannot be empty");
 56             _Program = value.Trim();
 57         }
 58     }
 59 
 60     public double GradePointAverage
 61     {
 62         get { return _GradePointAverage; }
 63         set
 64         {
 65             if (value < 0 || value > 9)
 66                 throw new System.Exception("GPA must be between 0 and 9 inclusiv\
 67 e");
 68             _GradePointAverage = value;
 69         }
 70     }
 71 
 72     public bool IsFullTime
 73     {
 74         get { return _IsFullTime; }
 75         set { _IsFullTime = value; }
 76     }
 77     #endregion
 78 
 79     #region Constructors
 80     public Student(string name, char gender, int studentId, string program, doub\
 81 le gradePointAverage, bool isFullTime)
 82     {
 83         if (studentId < 100000000 || studentId > 999999999)
 84             throw new System.Exception("Student Ids must be 9 digits");
 85         this.Name = name;
 86         this.Gender = gender;
 87         this.StudentId = studentId;
 88         this.Program = program;
 89         this.GradePointAverage = gradePointAverage;
 90         this.IsFullTime = isFullTime;
 91     }
 92     #endregion
 93 
 94     #region Methods
 95     public override string ToString()
 96     {
 97         return "(" + StudentId + ") " + Name;
 98     }
 99     #endregion
100 }

ParkingCounter

Only accepts positive, non-zero counts for available parking spaces and number of cars. Also, the number of cars must not exceed the number of parking spaces. The rules for the number of cars must also apply for cars entering and leaving the parking lot.

Problem Statement

Write the code that will monitor vehicles entering and leaving a parking lot. The solution must meet the following requirements (new requirements are in bold):

  • Should track vehicles entering
  • Should track vehicles leaving
  • Should track the peak occupancy of the parking lot
    • The peak occupancy represents the highest number of cars in the parking lot at any one time
  • Should get total parking spots
  • Should get open (empty) spots
  • Should reset lot as full (that is, fill the parking lot)
  • Should reset lot as empty (that is, clear all the parking spots of vehicles)
  • Should only allow a positive (non-zero) number of parking spots
  • Should not allow a negative number of cars (when using the overloaded constructor), and should not allow more cars than parking spots
  • Should not allow available (open) parking spots to go negative or to exceed the actual number of parking spots
    • Should raise an error when trying to enter a full parking lot
    • Should raise an error if trying to leave a parking lot that is already empty

Use the following class diagram when creating your solution.

 1     public ParkingCounter(int parkingSpots)
 2     {
 3         if (parkingSpots <= 0)
 4             throw new System.Exception("Negative or zero parkingSpots not allowe\
 5 d");
 6         this.ParkingSpots = parkingSpots;
 7         this.OpenSpots = parkingSpots;
 8         this.peak = 0;
 9     }
10 
11     public ParkingCounter(int parkingSpots, int numberOfCars)
12     {
13         if (parkingSpots <= 0)
14             throw new System.Exception("Negative or zero parkingSpots not allowe\
15 d");
16         if (numberOfCars < 0)
17             throw new System.Exception("Negative numberOfCars not allowed");
18         if (numberOfCars > parkingSpots)
19             throw new System.Exception("The number of cars cannot exceed the num\
20 ber of parking spots");
21         this.ParkingSpots = parkingSpots;
22         this.OpenSpots = this.ParkingSpots - numberOfCars;
23         this.peak = numberOfCars;
24     }
25 
26     public void leave()
27     {
28         if (OpenSpots == ParkingSpots)
29             throw new System.Exception("Parking lot is empty");
30         OpenSpots++;
31     }
32 
33     public void enter()
34     {
35         if (OpenSpots == 0)
36             throw new System.Exception("Parking lot is full");
37         OpenSpots--;
38         int numberOfCars = ParkingSpots - OpenSpots;
39         if (numberOfCars > peak)
40             peak = numberOfCars;
41     }

StockItem

The StockItem class represents an inventory item that is kept in stock. The item’s description, cost and profit margin are all part of the class design. Empty descriptions and zero or negative costs, as well as profit margins less than -100, are not allowed.

Problem Statement

Write the code for adding validation to the StockItem class. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the name, cost and profit margin of the stock item
  • Should represent the profit margin as a percent; a value of 45 means 45%
  • Should calculate the price of the item, to the nearest cent
    • Use the rounding where values under a half-cent are rounded down and values greater than or equal to a half-cent are rounded up
  • Should recognize when the stock item is priced at cost (that is, the profit margin is zero)
  • Should recognize when the stock item is priced below cost (that is, the profit margin is negative)
  • Should reject an empty (or null) item name
  • Should trim excess spaces from the ends of the item name
  • Should require cost to be greater than zero
  • Should only allow negative profit margins up to 100% (which is a full mark-down)

Use the following class diagram when creating your solution.

 1     private double _Cost;
 2     public double Cost
 3     {
 4         get
 5         {
 6             return _Cost;
 7         }
 8         set
 9         {
10             if (value <= 0)
11                 throw new Exception("Cost must be positive");
12             _Cost = value;
13         }
14     }
15 
16     private double _ProfitMargin;
17     public double ProfitMargin
18     {
19         get
20         {
21             return _ProfitMargin;
22         }
23         set
24         {
25             if (value < -100)
26                 throw new Exception("A profit margin below 100% (more than the c\
27 ost) is not allowed");
28             _ProfitMargin = value;
29         }
30     }
31 
32     private string _ItemName;
33     public string ItemName
34     {
35         get
36         {
37             return _ItemName;
38         }
39         set
40         {
41             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
42 ))
43                 throw new Exception("ItemName cannot be empty");
44             _ItemName = value.Trim();
45         }
46     }

Account

The following account information is now verified when the class is created:

  1. Bank name and account type cannot be empty
  2. The opening balance must be greater than zero
  3. The overdraft limit cannot be negative
  4. The institution number must be 3 digits
  5. The branch number must be 6 digits
  6. Attempts to withdraw amounts beyond the overdraft limit should throw an “Insufficient Funds” exception

Problem Statement

Write the code that will add validation to the Account class. The solution must meet the following requirements (new requirements are in bold):
* Should get the bank name, branch number, institution number, account number, balance, overdraft limit, and account type and allow the overdraft limit to be set
* Should support deposits
* Should only support withdrawals if the amount does not exceed the sum of the balance and the overdraft limit, otherwise an exception stating “Insufficient Funds” should occur
* Should identify if the account is overdrawn
* Should require bank name and account type (that is, they cannot be empty or null)
* Should trim the bank name and account type
* Should verify that the branch number is six digits and the institution number is three digits
* Should require an opening balance
* Should not allow a negative overdraft limit

Use the following class diagram when creating your solution.

  1     public double Balance
  2     {
  3         get { return _Balance; }
  4         set {
  5             if (value < -OverdraftLimit)
  6                 throw new Exception("Negative balances cannot exceed the Overdra\
  7 ft Limit");
  8             _Balance = value;
  9         }
 10     }
 11 
 12     public double OverdraftLimit
 13     {
 14         get { return _OverdraftLimit; }
 15         set
 16         {
 17             if (value < 0)
 18                 throw new Exception("Negative overdraft limits not allowed");
 19             _OverdraftLimit = value;
 20         }
 21     }
 22 
 23     public int BranchNumber
 24     {
 25         get { return _BranchNumber; }
 26         set {
 27             if (value < 10000 || value > 99999)
 28                 throw new Exception("Branch number must be 5 digits");
 29             _BranchNumber = value;
 30         }
 31     }
 32 
 33     public int InstitutionNumber
 34     {
 35         get { return _InstitutionNumber; }
 36         set
 37         {
 38             if (value < 100 || value > 999)
 39                 throw new Exception("InstitutionNumber must be a three-digit val\
 40 ue");
 41             _InstitutionNumber = value;
 42         }
 43     }
 44 
 45     public string AccountType
 46     {
 47         get { return _AccountType; }
 48         set {
 49             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
 50 ))
 51                 throw new Exception("Account type cannot be empty");
 52             _AccountType = value.Trim();
 53         }
 54     }
 55 
 56     public string BankName
 57     {
 58         get { return _BankName; }
 59         set
 60         {
 61             if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(value.Trim()\
 62 ))
 63                 throw new Exception("BankName is required");
 64             _BankName = value.Trim();
 65         }
 66     }
 67 
 68     public Account(string bankName, int branchNumber, int institutionNumber, int\
 69  accountNumber, double balance, double overdraftLimit, string accountType)
 70     {
 71         if (balance <= 0)
 72             throw new Exception("Opening balance must be greater than zero");
 73         if (balance != Math.Round(balance, 2))
 74             throw new Exception("Opening balances cannot include a fraction of a\
 75  penny");
 76         if (overdraftLimit != Math.Round(overdraftLimit, 2))
 77             throw new Exception("Overdraft limit amounts cannot include a fracti\
 78 on of a penny");
 79         AccountNumber = accountNumber;
 80         Balance = balance;
 81         OverdraftLimit = overdraftLimit;
 82         BankName = bankName;
 83         BranchNumber = branchNumber;
 84         InstitutionNumber = institutionNumber;
 85         AccountType = accountType;
 86     }
 87 
 88     public double Withdraw(double amount)
 89     {
 90         if (amount != Math.Round(amount, 2))
 91             throw new Exception("Withdrawal amounts cannot include fractions of \
 92 a penny");
 93         if (amount > Balance + OverdraftLimit)
 94             throw new Exception("Insufficient Funds");
 95         if (amount <= Balance + OverdraftLimit)
 96             Balance = Math.Round(Balance - amount, 2);
 97         else
 98             amount = 0;
 99         return amount;
100     }
101 
102     public void Deposit(double amount)
103     {
104         if (amount != Math.Round(amount, 2))
105             throw new Exception("Deposit amounts cannot include fractions of a p\
106 enny");
107         Balance = Math.Round(Balance + amount, 2);
108     }

Practice Exercises

  • Account – Add one more point of validation to the Account class: Do not allow depositing or withdrawing non-positive amounts.
  • Rectangle – The height and width of the rectangle must be greater than zero.
  • Cone – The radius and height of the cone must be greater than zero.
  • Course – The course name and number cannot be blank, and the exam and lab counts must be greater than zero. The class hours must also be greater than zero.
  • Cylinder – The radius and height of the cylinder must be greater than zero.
  • HazardousMaterial – The class code for the hazardous material can only be the letters ‘A’ through ‘F’, inclusive.
  • ExamResult - Requires a positive, non-zero value for the total marks and weight. The weight cannot be over 50. The marks earned can be between zero and the total marks, inclusive. The student ID must be 9 digits, and the exam name cannot be an empty string.
  • LabResult – Requires a positive, non-zero value for the lab number, total marks and weight. The weight cannot be over 50. The marks earned can be between zero and the total marks, inclusive. The student ID must be 9 digits.
  • PeopleCounter – Does not allow adding a negative number of people to the counter.
  • BulkItem – The description cannot be blank and the cost and quantity values must be greater than zero.

Account

Problem Statement

Write the code that will add another piece of validation to the Account class. The solution must meet the following requirements (new requirements are in bold):

  • Should get the bank name, branch number, institution number, account number, balance, overdraft limit, and account type and allow the overdraft limit to be set
  • Should support deposits
  • Should only support withdrawals if the amount does not exceed the sum of the balance and the overdraft limit, otherwise an exception stating “Insufficient Funds” should occur
  • Should identify if the account is overdrawn
  • Should require bank name and account type (that is, they cannot be empty or null)
  • Should trim the bank name and account type
  • Should verify that the branch number is six digits and the institution number is three digits
  • Should require an opening balance
  • Should not allow a negative overdraft limit
  • Should only allow positive, non-zero amounts when performing a deposit or withdrawal

Use the following class diagram when creating your solution.

Rectangle

The height and width of the rectangle must be greater than zero.

Problem Statement

Write the code to provide validation for the Rectangle class. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the height and the width
  • Should calculate the area, the perimeter and the diagonal
  • The formula for the diagonal is √(〖width〗2 + 〖height〗2 )
  • Should determine if the rectangle is a square
  • Should require the height and width to be greater than zero

Use the following class diagram when creating your solution.

Cone

The radius and height of the cone must be greater than zero.

Problem Statement

Write the code to provide validation for the Cone class that meets the following requirements (new requirements are in bold):

  • Should get the radius and the height
  • Should calculate the volume and the surface area
  • Should require the radius and height to be greater than zero

Use the following class diagram when creating your solution.

Course

The course name and number cannot be blank, and the exam and lab counts must be greater than zero. The class hours must also be greater than zero.

Problem Statement

Write the code to provide validation for the Course class. The solution must meet the following requirements (new requirements are in bold):

  • Should get the course name and number, the number of exams and labs, and the class hours for the course.
  • Should not allow empty course names or numbers
  • Should trim spaces from the course name and number
  • Should require class hours as well as lab and exam counts to be greater than zero

Cylinder

The radius and height of the cylinder must be greater than zero.

Problem Statement

Write the code to provide validation for the Cylinder class that meets the following requirements (new requirements are in bold):

  • Should get the radius and the height
  • Should calculate the volume and the surface area
  • Should make sure the radius and height are greater than zero

Use the following class diagram when creating your solution.

HazardousMaterial

The class code for the hazardous material can only be the letters ‘A’ through ‘F’, inclusive.

Problem Statement

Write the code to provide validation for the HazardousMaterial class. The solution must meet the following requirements (new requirements are in bold):

  • Should return the class code as the classification
  • Should make sure only class codes ‘A’ through ‘F’ are allowed (in either upper or lower case)
  • Should make sure the classification is stored in upper case
  • Should get the description for the class, based on the following table
Class Code Description
A Compressed Gas
B Flammable and Combustible Material
C Oxidizing Material
D Poisonous and Infectious Material
E Corrosive Material
F Dangerously Reactive Material
  • Should override the toString() method to get the full description and class code in the following format:
    • “Class ClassCode - Description”

Use the following class diagram when creating your solution.

ExamResult

Requires a positive, non-zero value for the total marks and weight. The weight cannot be over 50. The marks earned can be between zero and the total marks, inclusive. The student ID must be 9 digits, and the exam name cannot be an empty string.

Problem Statement

Write the code to provide validation for the ExamResult class. The solution must meet the following requirements (new requirements are in bold):

  • Should get the name, student Id, total marks, and exam weight
  • Should get and set the marks earned
  • Should override the toString() to show “The student (studentId) received earnedMarks/totalMarks for this examName exam.”
  • Should require the total marks and weight to be a positive, non-zero value
  • Should not allow a weight over 50
  • The marks earned must be between zero and the total possible marks, inclusive
  • The student ID must be nine digits
  • The exam name cannot be an empty string (and must be trimmed)

LabResult

Requires a positive, non-zero value for the lab number, total marks and weight. The weight cannot be over 50. The marks earned can be between zero and the total marks, inclusive. The student ID must be 9 digits.

Problem Statement

Write the code to provide validation for the LabResult class. The solution must meet the following requirements (new requirements are in bold):

  • Should get the lab number, student Id, total marks, and lab weight
  • Should get and set the marks earned
  • Should override the toString() to show “The student (studentId) received earnedMarks/totalMarks for this lab.”
  • Should require the total marks and weight to be a positive, non-zero value
  • Should not allow a weight over 50
  • The marks earned must be between zero and the total possible marks, inclusive
  • The student ID must be nine digits
  • The lab number must be a positive number

### PeopleCounter

Does not allow adding a negative number of people to the counter.

Problem Statement

Write the code needed to track people entering and leaving a store. It must be able to estimate the number of people that have entered the store at the end of the day. The solution must meet the following requirements (new requirements are in bold):

  • Should default to having a count of zero people when first started up
  • Should increment by one (that is, count a single person)
  • Should increment by a specified quantity (for when a group of people enter)
  • Should adequately estimate the number of people who entered the store, assuming that each person who enters also leaves the store
    Each estimate should be rounded down; for example, if 15 people are counted, then the estimate should be for only 7 (not 7.5 or 8)
  • Should not allow a zero or negative quantity when adding to the counter

Use the following class diagram when creating your solution.

BulkItem

The description cannot be blank and the cost and quantity values must be greater than zero.

Problem Statement

Write the code for the BulkItem class. The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the cost and quantity of the bulk item
  • Should get and set the description
  • Should ensure the description is not empty (and that it is trimmed)
  • Should ensure the cost and quantity values are greater than zero
  • Should calculate the cost for each item in the bulk item
  • Should properly round values for currency (either the US or Canadian dollar)

Use the following class diagram when creating your solution.

Topic H – Case Structures

Overview

This topic introduces the C# switch statement which is used to code case structures. The following new keywords are introduced.
* switch
* case
* default
* break

LOGs

General Programming Concepts and Terms

  • Describe the syntax of the switch statement
  • Discuss the limitations of the switch statement in C# and the available alternatives for the times that we can’t use a switch statement

Code Samples

  1. LetterGrade - Represents a letter grade as assigned in Quebec universities. Source: http://en.wikipedia.org/wiki/Letter_grade
  2. Rating – Represents a rating on a scale of 1 to 5, where 1 is “very bad”, 2 is “bad”, 3 is “average”, 4 is “good”, and 5 is “very good”.

LetterGrade

Problem Statement

Write the code for the LetterGrade class that represents a letter grade as assigned in Quebec universities (Source: http://en.wikipedia.org/wiki/Letter_grade). The solution must meet the following requirements (note – you do not need to perform validation for this sample):

  • Should get and set the grade (as a single letter)
  • Should ensure the grade is in upper-case
  • Should get the appropriate descriptions for the grade, based on the following table:
Grade Description
A A - 80-100% - Greatly Above Standards
B B - 70-79% - Above Standards
C C - 60-69% - At Government Standards
D D - 50-60% - Lower Standards
F F - 0-49% - Failure

Use the following class diagram when creating your solution.

 1 public class LetterGrade
 2 {
 3     private char _Grade;
 4 
 5     public char Grade
 6     {
 7         get { return _Grade; }
 8         set { this._Grade = char.ToUpper(value); }
 9     }
10 
11     public LetterGrade(char grade)
12     {
13         Grade = grade;
14     }
15 
16 
17     public override string ToString()
18     {
19         string description;
20         switch (_Grade)
21         {
22             case 'A':
23                 description = "A - 80-100% - Greatly Above Standards";
24                 break;
25             case 'B':
26                 description = "B - 70-79% - Above Standards";
27                 break;
28             case 'C':
29                 description = "C - 60-69% - At Government Standards";
30                 break;
31             case 'D':
32                 description = "D - 50-60% - Lower Standards";
33                 break;
34             case 'F':
35                 description = "F - 0-49% - Failure";
36                 break;
37             default:
38                 description = "Invalid Letter Grade";
39                 break;
40         }
41         return description;
42     }
43 }

Rating

Problem Statement

Write the code for the Rating class that represents a rating on a survey where the rating is done using the values 1 through 5, inclusive. The solution must meet the following requirements (note – you do not need to perform validation for this sample):

  • Should get and set the rating value
  • Should get the appropriate string result when using the ToString() method, based on the following table:
Value Description
1 very bad
2 bad
3 average
4 good
5 very good

Use the following class diagram when creating your solution.

 1 public class Rating
 2 {
 3     public int Value { get; set; }
 4 
 5     public Rating(int value)
 6     {
 7         Value = value;
 8     }
 9 
10 
11     public override string ToString()
12     {
13         string rating;
14         switch (Value)
15         {
16             case 5:
17                 rating = "very good";
18                 break;
19             case 4:
20                 rating = "good";
21                 break;
22             case 3:
23                 rating = "average";
24                 break;
25             case 2:
26                 rating = "bad";
27                 break;
28             case 1:
29                 rating = "very bad";
30                 break;
31             default:
32                 rating = "Invalid Rating";
33                 break;
34         }
35         return rating;
36     }
37 }

Practice Exercises

  1. BahamaLetterGrade - Represents a letter grade as assigned in the Bahamas universities. Source: http://en.wikipedia.org/wiki/Letter_grade
  2. Feedback – Represents an opinion rating as feedback, where 1 is “no opinion”, 2 is “strongly disagree”, 3 is “disagree”, 4 is “agree, and 5 is “strongly agree”.
  3. HazardousMaterial – Represents the six hazardous material codes of ‘A’ through ‘F’.

BahamaLetterGrade

Problem Statement

Write the code for the BahamaLetterGrade class that represents a letter grade as assigned in the Bahamas universities (Source: http://en.wikipedia.org/wiki/Letter_grade). Each letter grade is also associated with a grade value. The solution must meet the following requirements (note – you do not need to perform validation for this exercise):

  • Should get and set the grade (as a single letter)
  • Should ensure the grade is in upper-case
  • Should get the appropriate descriptions for the grade, based on the following table:
Grade Grade Value Description
A 4 A-4 - 90-100%
B 3 B-3 - 71-89%
C 2 C-2 - 56-70%
D 1 D-1 - 46-55%
F 0 F-0 - 0-45%

Use the following class diagram when creating your solution.

Feedback

Represents an opinion rating as feedback, where 1 is “no opinion”, 2 is “strongly disagree”, 3 is “disagree”, 4 is “agree, and 5 is “strongly agree”.

Problem Statement

Write the code for the Feedback class that represents a rating on a survey where the feedback is given using the values 1 through 5, inclusive. The solution must meet the following requirements (note – you do not need to perform validation for this sample):

  • Should get and set the feedback value
  • Should get the appropriate string result when using the ToString() method, based on the following table:
Value Description
1 no opinion
2 strongly disagree
3 disagree
4 agree
5 strongly agree

Use the following class diagram when creating your solution.

HazardousMaterial

The class code for the hazardous material can only be the letters ‘A’ through ‘F’, inclusive.

Problem Statement

Rewrite the code for the HazardousMaterial class to make use of the switch statement. The solution must meet the following requirements (new requirements are in bold):

  • Should return the class code as the classification
  • Should make sure only class codes ‘A’ through ‘F’ are allowed (in either upper or lower case)
  • Should make sure the classification is stored in upper case
  • Should get the description for the class, based on the following table
    You must use a switch statement to get the results
Class Code Description
A Compressed Gas
B Flammable and Combustible Material
C Oxidizing Material
D Poisonous and Infectious Material
E Corrosive Material
F Dangerously Reactive Material
  • Should override the ToString() method to get the full description and class code in the following format:
    • “Class ClassCode - Description”

Use the following class diagram when creating your solution.

Adding Complexity + Looping

Topic I –Enumerations and Composition

Overview

This topic introduces enumerations and composition. The following new keywords are introduced.

  • enum

This topic will reveal how enumerations allow programmers to define new data types and values to represent conceptual information. This topic also discusses the concept of composition, describing how composition is simply the use of objects as fields in a class.


### LOGs

General Programming Concepts and Terms

  • Define the term Enumeration
  • List the benefits of using enumerations
  • Describe where and when enumerations are used
  • Compare and contrast enumerations and classes
  • Use enumerations to define simple data types that are conceptual in nature and that have a limited set of possible “values”

OOP Basics

  • Describe the idea of Composition
  • List the benefits of Composition

Code Samples

Enumerations:

  1. Coin + CoinFace – The CoinFace enumeration helps to describe the tw * sides of a Coin, which can then be used in a tossing game.
  2. Account + AccountType – The Account’s account type is n * longer being represented as a string, but is its own enumeration: AccountType.
  3. LetterGrade + QuebecLetterGrade – The QuebecLetterGrade uses the simple LetterGrade enumeration and assigns specific ranges of percentage marks for the possible LetterGrade values.

Composition:

  1. Address + Student + GenderType – This revised version of the Student class now has an Address field. The address field is new; although similar to the CanadianAddress class, the Address class is simpler and more “generic” (having “State” instead of “Province” and “ZipCode” instead of “PostalCode”).
  2. ImproperFraction + MixedNumber + ProperFraction – In this sample, the idea of a Fraction class is made more specific by replacing it with three more specific types of numbers: MixedNumber, ProperFraction, and ImproperFraction. A MixedNumber is made up of a whole number and a ProperFraction. A MixedNumber can also be expressed as or derived from an ImproperFraction. The reciprocal of a ProperFraction is an ImproperFraction and the reciprocal of an ImproperFraction is a ProperFraction.

Coin + CoinFace

The CoinFace enumeration helps to describe the tw * sides of a Coin, which can then be used in a tossing game.

Problem Statement

Write the code needed to represent a coin that could be used in a coin-toss game. The solution must meet the following requirements.

  • Should randomly generate the coin face that is showing when creating the coin
  • Should get the side of the coin that is face showing
  • Should allow the coin to be tossed to randomly generate a new coin face
  • Should only support tw * sides for a coin’s face: Heads and Tails

Use the following diagram when creating your solution.

 1 public class Coin
 2 {
 3     public enum CoinFace { HEADS, TAILS };
 4 
 5     public CoinFace FaceShowing { get; private set; }
 6 
 7     public Coin()
 8     {
 9         Toss();
10     }
11 
12     public void Toss()
13     {
14         if (Rnd.Next(2) == 0)
15             FaceShowing = CoinFace.HEADS;
16         else
17             FaceShowing = CoinFace.TAILS;
18     }
19 }

Account + AccountType

The Account’s account type is n * longer being represented as a string, but is its own enumeration: AccountType.

Problem Statement

Write the code that will make the account type a type-safe value for the Account class. The solution must meet the following requirements (new requirements are in bold):

  • Should get the bank name, branch number, institution number, account number, balance, overdraft limit, and account type and allow the overdraft limit to be set
  • Should support deposits
  • Should only support withdrawals if the amount does not exceed the sum of the balance and the overdraft limit, otherwise an exception stating “Insufficient Funds” should occur
  • Should identify if the account is overdrawn
  • Should require bank name and account type (that is, they cannot be empty or null)
  • Should trim the bank name
  • Should ensure that the Account Type is type-safe and that it is supplied when creating the account (that is, it cannot be null)
  • Should support the following types of accounts: Chequing, Saving, Credit Card, and Line of Credit
  • Should verify that the branch number is six digits and the institution number is three digits
  • Should require an opening balance
  • Should not allow a negative overdraft limit

Use the following class diagram when creating your solution.

 1 public class Account
 2 {
 3     public Account(string bankName, int branchNumber, int institutionNumber,
 4             int accountNumber, double balance, double overdraftLimit,
 5             AccountType type)
 6     {
 7         if (string.IsNullOrEmpty(bankName) ||
 8             string.IsNullOrEmpty(bankName.Trim()))
 9             throw new System.Exception("Bank name cannot be empty");
10         if (branchNumber < 10000 || branchNumber > 99999)
11             throw new System.Exception("Branch number must be 5 digits");
12         if (institutionNumber < 100 || institutionNumber > 999)
13             throw new System.Exception("Institution number must be 3 digits");
14         if (balance <= 0)
15             throw new System.Exception("Opening balance must be greater than zer\
16 o");
17         OverdraftLimit =overdraftLimit;
18         this.BankName = bankName;
19         this.BranchNumber = branchNumber;
20         this.InstitutionNumber = institutionNumber;
21         this.AccountNumber = accountNumber;
22         this.Balance = balance;
23         this.Type = type;
24     }
25 
26     private double _overdraftLimit;
27 
28     public double Balance { get; private set; }
29     public string BankName { get; private set; }
30     public int BranchNumber { get; private set; }
31     public int InstitutionNumber { get; private set; }
32     public int AccountNumber { get; private set; }
33     public AccountType Type { get; private set; }
34 
35     public double OverdraftLimit
36     {
37         get
38         { return _overdraftLimit; }
39         set
40         {
41             if (value < 0)
42                 throw new System.Exception("Negative overdraft limits not allowe\
43 d");
44             this._overdraftLimit = value;
45         }
46     }
47 
48     public bool IsOverdrawn()
49     {
50         return Balance < 0.0;
51     }
52 
53     public void Deposit(double amount)
54     {
55         Balance += amount;
56     }
57 
58     public double Withdraw(double amount)
59     {
60         if (amount > Balance + _overdraftLimit)
61             throw new System.Exception("Insufficient Funds");
62         Balance -= amount;
63         return amount;
64     }
65 }

LetterGrade + QuebecLetterGrade

The QuebecLetterGrade uses the simple LetterGrade enumeration and assigns specific ranges of percentage marks for the possible LetterGrade values.

Problem Statement

Write the code for the LetterGrade class that represents a letter grade as assigned in Quebec universities (Source: http://en.wikipedia.org/wiki/Letter_grade). The solution must meet the following requirements (new requirements are in bold):

  • Should get and set the grade as a type-safe value
  • Should get the appropriate descriptions for the grade, based on the following table:
Grade Description
A A - 80-100% - Greatly Above Standards
B B - 70-79% - Above Standards
C C - 60-69% - At Government Standards
D D - 50-60% - Lower Standards
F F - 0-49% - Failure

Use the following class diagram when creating your solution.

 1 public enum LetterGrade
 2 {
 3     A, B, C, D, F
 4 }
 5 
 6 public class QuebecLetterGrade
 7 {
 8     public LetterGrade Grade { get; set; }
 9 
10     public QuebecLetterGrade(LetterGrade grade)
11     {
12         this.Grade = grade;
13     }
14 
15     public override string ToString()
16     {
17         string description;
18         switch (Grade)
19         {
20             case LetterGrade.A:
21                 description = "A - 80-100% - Greatly Above Standards";
22                 break;
23             case LetterGrade.B:
24                 description = "B - 70-79% - Above Standards";
25                 break;
26             case LetterGrade.C:
27                 description = "C - 60-69% - At Government Standards";
28                 break;
29             case LetterGrade.D:
30                 description = "D - 50-60% - Lower Standards";
31                 break;
32             case LetterGrade.F:
33                 description = "F - 0-49% - Failure";
34                 break;
35             default:
36                 description = "Invalid Letter Grade";
37                 break;
38         }
39         return description;
40     }
41 }

Address + Student + GenderType

This revised version of the Student class now has an Address field. The address field is new; although similar to the CanadianAddress class, the Address class is simpler and more “generic” (having “State” instead of “Province” and “ZipCode” instead of “PostalCode”).

Problem Statement

Extend the Student class to now include information about the student’s home address. Create an Address class to represent a simple, generic address. In addition, the Student class must represent the Gender using an enumeration.

The solution must meet the following requirements (new requirements are in bold):

  • The Address class must
    • Get and set the city, state, street, unit and zip code.
  • The Student class must
    • Verify that an address object is supplied (is not null)
    • Represent the Gender as a GenderType of Male and Female
    • Should get and set the student’s name, gender, GPA, program of studies, and whether or not the student is full-time.
    • Should override the toString() method to get the student’s ID and name in this format:
      (ID) Name
    • Should n * longer allow the student ID to be set (it’s only set through the constructor)
    • Should reject empty text (and null values) for the student’s name and program of studies.
    • Should trim the student’s name and the program name
    • Should only accept ‘M’ and ‘F’ as valid genders
    • Should set the gender to upper-case
    • Should reject negative GPAs and GPAs over 9

Use the following class diagrams to guide your design.

  1 public enum GenderType
  2 {
  3     MALE, FEMALE
  4 }
  5 
  6 public class Address
  7 {
  8     public string Street { get; set; }
  9     public string Unit { get; set; }
 10     public string City { get; set; }
 11     public string State { get; set; }
 12     public string ZipCode { get; set; }
 13 
 14     public Address(string unit, string street, string city, string state,
 15             string zipCode)
 16     {
 17         this.Unit = unit;
 18         this.Street = street;
 19         this.City = city;
 20         this.State = state;
 21         this.ZipCode = zipCode;
 22     }
 23 }
 24 
 25 public class Student
 26 {
 27     private string _name; // The full name of the student
 28     private string _program; // The course program; e.g.: "CST"
 29     private double _gradePointAverage; // GPA is from 1.0 to 9.0
 30     private Address _homeAddress;
 31 
 32     public Student(string name, Address homeAddress, GenderType gender,
 33         int studentId, string program, double gradePointAverage,
 34         bool isFullTime)
 35     {
 36         if (studentId < 100000000 || studentId > 999999999)
 37             throw new System.Exception("Student Ids must be 9 digits");
 38         Name = name;
 39         HomeAddress = homeAddress;
 40         Gender = gender;
 41         StudentId = studentId;
 42         Program = program;
 43         GradePointAverage = gradePointAverage;
 44         IsFullTime = isFullTime;
 45     }
 46 
 47     public GenderType Gender { get; set; }
 48     public bool IsFullTime { get; set; }
 49     public int StudentId { get; private set; }
 50 
 51     public string Name
 52     {
 53         get
 54         { return _name; }
 55         set
 56         {
 57             if (string.IsNullOrEmpty(value) ||
 58                 string.IsNullOrEmpty(value.Trim()))
 59                 throw new System.Exception("name cannot be empty");
 60             this._name = value.Trim();
 61         }
 62     }
 63 
 64     public Address HomeAddress
 65     {
 66         get
 67         { return _homeAddress; }
 68         set
 69         {
 70             if (value == null)
 71                 throw new System.Exception("Address is required");
 72             this._homeAddress = value;
 73         }
 74     }
 75 
 76     public string Program
 77     {
 78         get
 79         { return _program; }
 80         set
 81         {
 82             if (string.IsNullOrEmpty(value) ||
 83                 string.IsNullOrEmpty(value.Trim()))
 84                 throw new System.Exception("Program cannot be empty");
 85             this._program = value.Trim();
 86         }
 87     }
 88 
 89     public double GradePointAverage
 90     {
 91         get
 92         { return _gradePointAverage; }
 93         set
 94         {
 95             if (value < 0 || value > 9)
 96                 throw new System.Exception("GPA must be between 0 and 9 inclusiv\
 97 e");
 98             this._gradePointAverage = value;
 99         }
100     }
101 
102 
103     public override string ToString()
104     {
105         return "(" + StudentId + ") " + Name;
106     }
107 }

ImproperFraction + MixedNumber + ProperFraction

In this sample, the idea of a Fraction class is made more specific by replacing it with three more specific types of numbers: MixedNumber, ProperFraction, and ImproperFraction. A MixedNumber is made up of a whole number and a ProperFraction. A MixedNumber can also be expressed as or derived from an ImproperFraction. The reciprocal of a ProperFraction is an ImproperFraction and the reciprocal of an ImproperFraction is a ProperFraction.

Problem Statement

The generic Fraction class is now being replaced with a set of three more specific classes for numbers with fractional values: ProperFraction, ImproperFraction, and MixedNumber. Create these classes, using the following requirements and class diagrams.

  • ProperFraction should ensure that it is indeed a proper fraction
  • ImproperFraction should ensure that it is indeed an improper fraction
  • MixedNumber should construct either from a whole number and a proper fraction or from an improper fraction
  • ProperFraction and ImproperFraction should get their respective reciprocals as well as their values as real numbers
  • ProperFraction and ImproperFraction should ensure that the denominator is always positive
  • MixedNumber should get the whole number portion as well as the fractional portion
  • MixedNumber should get its value as a real number as well as get its value as an ImproperFraction
  1 public class ProperFraction
  2 {
  3     public ProperFraction(int numerator, int denominator)
  4     {
  5         if (denominator == 0)
  6             throw new System.Exception("zero denominator fractions are undefined\
  7 ");
  8         if (Math.Abs(numerator) >= Math.Abs(denominator))
  9             throw new System.Exception("Proper fractions must have a numerator t\
 10 hat is less than the denominator");
 11 
 12         if (denominator < 0)
 13         {
 14             numerator *= -1;
 15             denominator *= -1;
 16         }
 17         this.Numerator = numerator;
 18         this.Denominator = denominator;
 19     }
 20 
 21     public int Numerator { get; private set; }
 22     public int Denominator { get; private set; }
 23     public ImproperFraction Reciprocal
 24     {
 25         get
 26         { return new ImproperFraction(Denominator, Numerator); }
 27     }
 28 
 29     public double ToDouble()
 30     {
 31         return (double)(Numerator) / Denominator;
 32     }
 33 
 34     public override string ToString()
 35     {
 36         return Numerator + "/" + Denominator;
 37     }
 38 }
 39 
 40 public class ImproperFraction
 41 {
 42     public ImproperFraction(int numerator, int denominator)
 43     {
 44         if (denominator == 0)
 45             throw new System.Exception("zero denominator fractions are undefined\
 46 ");
 47         if (Math.Abs(numerator) < Math.Abs(denominator))
 48             throw new System.Exception("Improper fractions must have a numerator\
 49  that is greater than or equal to the denominator");
 50 
 51         if (denominator < 0)
 52         {
 53             numerator *= -1;
 54             denominator *= -1;
 55         }
 56         this.Numerator = numerator;
 57         this.Denominator = denominator;
 58     }
 59 
 60     public int Numerator { get; private set; }
 61     public int Denominator { get; private set; }
 62     public ProperFraction Reciprocal
 63     {
 64         get { return new ProperFraction(Denominator, Numerator); }
 65     }
 66 
 67     public double ToDouble()
 68     {
 69         return (double)(Numerator) / Denominator;
 70     }
 71 
 72     public override string ToString()
 73     {
 74         return Numerator + "/" + Denominator;
 75     }
 76 }
 77 
 78 public class MixedNumber
 79 {
 80     public int WholeNumber { get; private set; }
 81     public ProperFraction Fraction { get; private set; }
 82 
 83     public MixedNumber(int wholeNumber, ProperFraction fraction)
 84     {
 85         if (wholeNumber == 0)
 86             throw new System.Exception("wholeNumber portion cannot be zero for a\
 87  Mixed Number");
 88         if (fraction == null)
 89             throw new System.Exception("MixedNumbers must have a fractional port\
 90 ion");
 91         if (fraction.Numerator < 0)
 92         {
 93             fraction = new ProperFraction(-fraction.Numerator, fraction.Denomina\
 94 tor);
 95             wholeNumber *= -1;
 96         }
 97         this.WholeNumber = wholeNumber;
 98         this.Fraction = fraction;
 99     }
100 
101     public MixedNumber(ImproperFraction improperFraction) :
102         this(improperFraction.Numerator / improperFraction.Denominator,
103               new ProperFraction(improperFraction.Numerator %
104                                 improperFraction.Denominator,
105                                 improperFraction.Denominator))
106     {
107     }
108 
109     public ImproperFraction ToImproperFraction()
110     {
111         return new ImproperFraction(WholeNumber * 
112                                     Fraction.Denominator + Fraction.Numerator,
113                                     Fraction.Denominator);
114     }
115 
116     public double ToDouble()
117     {
118         double realValue = Math.Abs(WholeNumber) + Fraction.ToDouble();
119         if (WholeNumber < 0)
120             realValue *= -1;
121         return realValue;
122     }
123 }

Practice Exercises

  1. LetterGrade + BahamaLetterGrade – The BahamaLetterGrade also uses the LetterGrade enumerated type, assigning its own specific ranges and values to the possible LetterGrade values.
  2. HazardousMaterial + ClassCode – The various types of hazardous materials are now identified by their ClassCode enumerated type.
  3. CanadianAddress + Province – The CanadianAddress class is modified to now use a Province enumeration to properly capture the provinces and territories of Canada.
  4. Employee/Student + CanadianAddress + Province – The Employee and Student classes now have address information.
  5. Company + Month + CanadianAddress + Province – The Company now has a CanadianAddress.

LetterGrade + BahamaLetterGrade

The BahamaLetterGrade also uses the LetterGrade enumerated type, assigning its own specific ranges and values to the possible LetterGrade values.

Problem Statement

Write the code for the BahamaLetterGrade class and the LetterGrade enumeration to represent a letter grade as assigned in universities in the Bahamas. (For more information on Bahaman letter grades, see http://en.wikipedia.org/wiki/Letter_grade.) . The solution must meet the following requirements (new requirements are in green, bold italic font):

  • The LetterGrade enumeration should be “generic” and support letter grades of A through F inclusive
  • The BahamaLetterGrade should reject the LetterGrade of E (which is not allowed in the Bahamas) as well as any null letter grade
  • The BahamaLetterGrade should get the appropriate descriptions for the grade, based on the following table:
Grade Grade Value Description
A 4 A-4 - 90-100%
B 3 B-3 - 71-89%
C 2 C-2 - 56-70%
D 1 D-1 - 46-55%
F 0 F-0 - 0-45%

Use the following class diagram when creating your solution.

HazardousMaterial + ClassCode

The various types of hazardous materials are now identified by their ClassCode enumerated type.

Problem Statement

Rewrite the code for the HazardousMaterial class to make use of the ClassCode enumerated type. The solution must meet the following requirements (new requirements are in green, bold italic font):

  • Should return the class code as the classification
  • Should make sure the class code is supplied (is not null)
  • Should get the description for the class, based on the following table
    You must use a switch statement to get the results
Class Code Description
A Compressed Gas
B Flammable and Combustible Material
C Oxidizing Material
D Poisonous and Infectious Material
E Corrosive Material
F Dangerously Reactive Material
  • Should override the ToString() method to get the full description and class code in the following format:
    • “Class ClassCode - Description”

Use the following class diagram when creating your solution.

CanadianAddress + Province

The CanadianAddress class is modified to now use a ProvinceType enumeration to properly capture the provinces and territories of Canada.

Problem Statement

Modify the CanadianAddress class to now use an enumeration for the province. Use the following class diagram as a guide in creating the class and the enumeration.

Employee/Student + CanadianAddress + Province

The Employee and Student classes now have address information.

Problem Statement

Modify the Employee and Student classes to now use the CanadianAddress type for their addresses.

Company + Month + CanadianAddress + Province

The Company now has a CanadianAddress.

Problem Statement

Modify the Company class to now make use of the CanadianAddress type for the address. Also, create an enumeration for the months of the year for representing the company’s fiscal year end.

Topic J - Looping Structures

Overview

LOGs

General Programming Concepts and Terms

  • Identify the C# statements that correspond to Do-While and Do-Until logical structures
  • Translate Do-While structures into code
  • Translate Do-Until structures into code
  • Identify and distinguish the parts of the for statement in code
  • Describe the common situations in which the for statement is used
  • Demonstrate how the various looping statements can be interchanged with slight alterations of the logical structures to maintain the overall logic of a given routine.

Code Samples

  1. Aggregator – The Aggregator class supports static methods for doing various types of aggregation on Numbers. (Numbers is a supplied class that stores a series of real values that can be obtained by calling getNext().) The common aggregations of totalItems(), averageItems(), maxValue() are given as examples of simple looping.
  2. Math – fibonnacciNumber() and isPerfect()
  3. Fraction – The fraction example is now enhanced to simplify the fractional value by finding the greatest common denominator of the fraction’s numerator and denominator.
  4. GuessingGame – This example uses a supplied class called SecretNumber, which picks a random whole number between a specific range. An instance of the SecretNumber is passed to the constructor of the GuessingGame, and the GuessingGame’s guess() method attempts to get the correct guess within a specified number of tries.

Aggregator

The Aggregator class supports static methods for doing various types of aggregation on Numbers. (Numbers is a supplied class that stores a series of real values that can be obtained by calling GetNext().) The common aggregations of TotalItems(), AverageItems(), MaxValue() are given as examples of simple looping.

The Numbers Class

The methods of the Aggregator class all take a single argument: a Numbers object. The Numbers object contains a bunch of real numbers and it has two methods that the Aggregator methods will use:

  • HasNext() – This returns a Boolean indicating that the object has another number available.
  • GetNext() – This returns a real number from the set of values in the Numbers object.

For example, if a Numbers object has a set of four values such as 1.0, 5.5, 3.2, and 5.3, then the GetNext() method can be called four times to retrieve each value. Any attempt to call GetNext() when the object’s HasNext() is false will cause an exception.

Note: This class is already coded for you in the samples.

Aggregator Methods

The following Aggregator methods will demonstrate looping logic and syntax. All of these examples demonstrate the while statement.

  • TotalItems() – This method loops through all the values inside of the Numbers object to calculate and return the total of the values.
  • AverageItems() – This method gets all the values inside of the Numbers object so as to calculate the average value. If no values exist in the Numbers object, then the method returns an average of zero.
  • MaxValue() – This method examines the Numbers object’s values to see which value is the largest. If there are no values inside of the Numbers object, then the method returns the smallest possible value that is supported by the programming language.
 1 public class Aggregator
 2 {
 3     public static double TotalItems(Numbers items)
 4     {
 5         double total = 0;
 6         while (items.HasNext())
 7             total += items.Next();
 8         return total;
 9     }
10 
11     public static double AverageItems(Numbers items)
12     {
13         double average, total = 0;
14         int count = 0;
15         while (items.HasNext())
16         {
17             total += items.Next();
18             count++;
19         }
20         if (count > 0)
21             average = total / count;
22         else
23             average = 0;
24         return average;
25     }
26 
27     public static double MaxValue(Numbers items)
28     {
29         double max = double.MinValue;
30         while (items.HasNext())
31         {
32             double value = items.Next();
33             if (max < value)
34                 max = value;
35         }
36         return max;
37     }
38 }

Math

The Math class provides methods for the following mathematical algorithms not found in the default Math class.

  • FibonacciNumber() – Returns a number from the Fibonacci sequence for a given position. If the given position is less than or equal to zero, then this method should throw an exception. This example demonstrates the for statement. An alternative version illustrates the do-while statement.
  • IsPerfect() – Indicates whether or not a number is a “perfect” number. A perfect number is a number where the sum of all the factors equals the number. By definition, any number less than 1 (including all negative numbers) are not perfect numbers. This example uses a while statement. An alternative version illustrates a do-while statement.
 1 public class Math
 2 {
 3     public static int FibonacciNumber(int i)
 4     {
 5         int current = 1, previous = 1, beforePrevious = 0;
 6         if (i >= 1)
 7         {
 8             for (int counter = 3; counter <= i; counter++)
 9             {
10                 beforePrevious = previous;
11                 previous = current;
12                 current = beforePrevious + previous;
13             }
14         }
15         else
16             throw new Exception("Can only create a fibonnaci number based on a p\
17 ositive non-zero position");
18         return current;
19     }
20 
21     public static bool IsPerfect(int number)
22     {
23         bool perfect = true;
24         if (number <= 1)
25             perfect = false;
26         else
27         {
28             // The following logic attempts to prove it is imperfect
29             int halfWay = number / 2;
30             int total = 0;
31             int count = 1;
32             while (total != number && total <= halfWay && total < number)
33             {
34                 if (number % count == 0) // Then count is a factor of number
35                     total += count;
36                 count++;
37             }
38             if (total != number)
39                 perfect = false;
40         }
41         return perfect;
42     }
43 }

Fraction

The fraction example is now enhanced to simplify the fractional value by finding the greatest common denominator of the fraction’s numerator and denominator.

The Fraction class represents a fraction as two integers: one for the numerator and one for the denominator. When a Fraction object is created, the class must now simplify the fractional values by calculating the greatest common denominator.

  • GreatestCommonDenominator() – This private method is used by the Simplify() method to get the greatest common denominator for the numerator and denominator. Remember to allow for dealing with negative fractions (in which case, the negative sign will be on the numerator). This example uses a while statement (though it is possible to re-work the logic to use a do-while statement).
 1     private int GreatestCommonDenominator()
 2     {
 3         int commonDenominator = 1;
 4         int count = 2, halfWay;
 5         int absoluteNumerator = System.Math.Abs(Numerator);
 6         if (absoluteNumerator > Denominator)
 7             halfWay = absoluteNumerator / 2;
 8         else
 9             halfWay = Denominator / 2;
10 
11         while (count <= halfWay)
12         {
13             if (absoluteNumerator % count == 0 && 
14                 Denominator % count == 0)
15                 commonDenominator = count;
16             count++;
17         }
18 
19         return commonDenominator;
20     }

GuessingGame

This example uses a supplied class called SecretNumber, which picks a random whole number between a specific range. An instance of the SecretNumber is passed to the constructor of the GuessingGame, and the GuessingGame’s Guess() method attempts to get the correct guess within a specified number of tries.

In a regular number guessing game between two people, one person asks another person to guess a whole number between a pair of values. In this example, two different classes take on the roles of the two people in the game: The SecretNumber class takes on the role of the person who has picked a value between some lower and upper limit, while the GuessingGame class takes on the role of the person who has to guess what that hidden number is.

Note: This class is already coded for you in the samples.

SecretNumber

Objects of this class will store a hidden value between some upper and lower limit (inclusive). The SecretNumber class supports three public methods:

  • GetLowerLimit() – Returns a number representing the lower end (inclusive) of the range of possible values for the hidden value.
  • GetUpperLimit() – Returns a number representing the upper end (inclusive) of the range of possible values for the hidden value.
  • Guess() – Returns true if the supplied value matches the hidden value, otherwise it returns false.

GuessingGame

This class simulates the action of guessing what hidden value is stored inside of a SecretNumber object. The SecretNumber is supplied to the constructor of the GuessingGame, and the following methods attempt to find out what that number is.

  • GuessNumber() – This first method simply tries to guess the hidden value of the SecretNumber. It has “unlimited” guesses, and it will return the number of attempts it took to find out what that hidden number is.
  • GuessNumber(MaxAttempts : Integer) – This method will also try to guess the SecretNumber’s hidden value, but it is limited to a maximum number of guesses. This method will return the actual number of attempts it took to find the hidden value, or it will return the GUESS_FAILED constant if it was unable to guess the secret number.

Try creating alternate versions of this GuessingGame that will use a while statement and a for statement in the GuessNumber methods.

 1 public class GuessingGame
 2 {
 3     private SecretNumber Number { get; set; }
 4     public const int GUESS_FAILED = -1;
 5 
 6     public GuessingGame(SecretNumber number)
 7     {
 8         if (number == null)
 9             throw new System.Exception("SecretNumber cannot be null");
10         this.Number = number;
11     }
12 
13     public int GuessNumber(int maxAttempts)
14     {
15         int numberOfAttempts = 0;
16         bool correct = false;
17         while (maxAttempts > 0 && !correct)
18         {
19             // Make a guess
20             int myBestGuess = Rnd.Next(Number.LowerLimit, Number.UpperLimit);
21             if (Number.Guess(myBestGuess))
22                 correct = true;
23             numberOfAttempts++;
24             maxAttempts--;
25         }
26         if (!correct)
27             numberOfAttempts = GUESS_FAILED; // a "flag" to say the guess was in\
28 correct
29         return numberOfAttempts;
30     }
31 
32     public int GuessNumber()
33     {
34         bool correct = false;
35         int numberOfAttempts = 0;
36         while (numberOfAttempts < int.MaxValue && !correct)
37         {
38             // Make a guess
39             int myBestGuess = Rnd.Next(Number.LowerLimit, Number.UpperLimit);
40             if (Number.Guess(myBestGuess))
41                 correct = true;
42             numberOfAttempts++;
43         }
44         if (!correct)
45             numberOfAttempts = GUESS_FAILED;
46         return numberOfAttempts;
47     }
48 }

Practice Exercises

  1. Aggregator – countItems(), minValue()
  2. Math – factorial(), isPrime(), power(), and greatestCommonDenominator()
  3. GuessingGame – This example expands on the sample GuessingGame by 1) re-working the guess() method to make guessing more efficient by using the SecretNumber’s guessWithHint() method, and 2) overloading the guess() method to continue guessing until the correct answer is found (and returning the number of attempts it took to find the correct answer).

Aggregator

Expand on the sample Aggregator class to perform the following aggregations.

  • CountItems() – Return the count of the number of values in the Numbers object.
  • MinValue() – Return the smallest value in the set of values of the supplied Numbers object. If no values exist in the Numbers object, return the largest whole number supported by the programming language.

Math

Expand on the sample Math class by providing methods to perform the following.

  • Factorial() – Calculate the factorial of a given number. If the given number is negative, throw an exception. If the calculated value for the factorial will exceed the maximum integer value (int.MaxValue), then return zero (0) as a result.
  • IsPrime() – Identify if a number is or is not a prime number. A prime number is a number with only two divisors: 1 and the number itself. By definition for this problem, numbers less than one are not considered prime numbers.
  • Power() – Calculate the value of x to the power of y (as in xy). Use looping logic (addition) to get the result.
  • GreatestCommonDenominator() – Find the greatest common denominator between two whole numbers.

GuessingGame

This example expands on the sample GuessingGame by adding more guess methods to make guessing more efficient by using the SecretNumber’s guessWithHint() method.

In a regular number guessing game between two people, one person asks another person to guess a whole number between a pair of values. In this example, two different classes take on the roles of the two people in the game: The SecretNumber class takes on the role of the person who has picked a value between some lower and upper limit, while the GuessingGame class takes on the role of the person who has to guess what that hidden number is.

SecretNumber

Objects of this class will store a hidden value between some upper and lower limit (inclusive). The SecretNumber class supports these public methods:

  • GetLowerLimit() – Returns a number representing the lower end (inclusive) of the range of possible values for the hidden value.
  • GetUpperLimit() – Returns a number representing the upper end (inclusive) of the range of possible values for the hidden value.
  • GuessWithHint() – Returns CORRECT if the supplied value matches the hidden value, otherwise it returns GUESS_HIGHER if the attempted guess was too low or GUESS_LOWER if the attempted guess was too high.

Note: This class is already coded for you in the samples.

GuessingGame

This class simulates the action of guessing what hidden value is stored inside of a SecretNumber object. The SecretNumber is supplied to the constructor of the GuessingGame, and the following methods attempt to find out what that number is.

  • GuessUsingHints() – This first method simply tries to guess the hidden value of the SecretNumber. It has “unlimited” guesses, and it will return the number of attempts it took to find out what that hidden number is. Use the GuessWithHint method of the SecretNumber object.
  • GuessUsingHints(MaxAttempts : Integer) – This method will also try to guess the SecretNumber’s hidden value, but it is limited to a maximum number of guesses. This method will return the actual number of attempts it took to find the hidden value, or it will return the GUESS_FAILED constant if it was unable to guess the secret number. Use the GuessWithHint method of the SecretNumber object.
    As an additional exercise, create a simple driver that instantiates a SecretNumber object and supplies it to a GuessingGame object. Show how many attempts it took to guess the hidden number when using hints.

Interlude 2 - A General-Purpose Driver

The following is a nice general-purpose console-based driver that can be used for the remaining topics.

 1 class Program
 2 {
 3     #region Driver Method
 4     static void Main(string[] args)
 5     {
 6         string menuChoice;
 7         do
 8         {
 9             DisplayMenu();
10             menuChoice = Console.ReadLine().ToUpper();
11             ProcessMenuChoice(menuChoice);
12         } while (menuChoice!="X");
13     }
14     #endregion
15 
16     #region General Purpose Methods
17     private static void DisplayMenu()
18     {
19         Console.ForegroundColor = ConsoleColor.DarkGreen;
20 
21         Console.WriteLine("A) ");
22         Console.WriteLine("B) ");
23         Console.WriteLine("C) ");
24         Console.WriteLine("X) ");
25         Console.ResetColor();
26         Console.Write("Select an option from the menu: ");
27     }
28 
29     private static void ProcessMenuChoice(string choice)
30     {
31         switch(choice)
32         {
33             case "A":
34                 break;
35             case "B":
36                 break;
37             case "C":
38                 break;
39             case "X":
40                 break;
41             default:
42                 Console.ForegroundColor = ConsoleColor.DarkRed;
43                 Console.WriteLine("Invalid menu choice.");
44                 break;
45         }
46         Pause();
47         Console.ResetColor();
48     }
49 
50     private static void Pause()
51     {
52         Console.ForegroundColor = ConsoleColor.Gray;
53         Console.WriteLine("\n\nPress any key to continue...");
54         Console.ReadKey(true);
55         Console.Clear();
56     }
57     #endregion
58 
59     #region Menu Processing Methods
60     // TODO: Your specific menu processing methods.
61     #endregion
62 }

Topic K - Looping and Collections

Overview

This topic provides further examples of looping logic, but involves the use of collections. All of these samples make use of the List<T> class to maintain a collection or group of objects.

The List<T> class is a Generic class, meaning that the item in the angled brackets - <T> - is a placeholder for the name of the actual class that is being managed in the List. For example, to have a list of Integers we would declare that as List<Integer>. Likewise, if we wanted a list of Student objects, it would be declared as List<Student>.

The List<T> class supports a number of methods and properties for working with the collection.

  • Add() – Used to add an item to the collection
  • [index] – Used to retrieve an item in the collection
  • Remove() – Used to remove an item from the collection
  • Count – Identifies the number of items in the collection

LOGs

OOP Basics

  • Define the term Generics as used in C# and give an example

General Programming Concepts and Terms

  • Describe what is meant by a “collection” class and give an example
  • List and describe the common methods of collection classes such as the List<T>
  • Identify the parts of the foreach statement
  • Describe the common situations in which the foreach statement is typically used
  • Identify the major benefit of using Generics
  • List the major benefits of using collections instead of arrays

Code Samples

  1. Math – The Math class is expanded to produce a collection of Integers for the sequence of Fibonacci numbers.
  2. PhoneBook – The PhoneBook class provides simple management of a collection of PhoneNumber objects. The PhoneBook allows for adding and retrieving phone numbers; it supports search for phone numbers by the telephone number or by a last name.
  3. ClassList – The ClassList example maintains a list of students for a particular course by offering methods to add and remove students from a course. In addition, the ClassList ensures that students are not added to the course twice (based on the student’s Id).
  4. MultipleChoiceMarker – This class is used for marking multiple choice exams. It takes a collection of MultipleChoice objects as the answer key when it is first created. It provides a method to mark the student’s answers.
  5. BankStatement – This class represents a bank statement for a BankAccount for a given month. The statement allows BankTransaction objects to be added, and performs deposits and withdrawals on the BankAccount. The statement reports the starting and ending balance and also summarizes the total amount deposited and withdrawn for the month.
  6. DeckOfCards –The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports a method to draw a card.

Math

This sample leverages the existing calculation of a number in the Fibonacci sequence to generate the sequence itself.

  • FibonacciSequence(Length : Integer) – This method generates the sequence of Fibonacci numbers to a specific length in the sequence.
 1 public static List<int> FibonacciSequence(int length)
 2 {
 3     List<int> fib = new List<int>();
 4     if (length >= 1)
 5     {
 6         for (int index = 0; index < length; index++)
 7             fib.Add(FibonacciNumber(index + 1));
 8     }
 9     return fib;
10 }

PhoneBook

The PhoneBook class provides simple management of a collection of PhoneNumber objects. The PhoneBook allows for adding and retrieving phone numbers; it supports search for phone numbers by the telephone number or by a last name.

  • Constructor – Create a new List<PhoneNumber> for the numbers field.
  • AddPhoneNumber(Entry : PhoneNumber) – Add a PhoneNumber to the collection. Ensure that the PhoneNumber exists (is not null) before adding; if the PhoneNumber is null, throw an exception.
  • GetPhoneNumber(Index : Integer) : PhoneNumber – Get an item from a particular position in the collection.
  • GetCount() : Integer – Get the size of the collection, which is a count of how many PhoneNumber objects are in the collection.
  • FindPhoneNumber(TelephoneNumber : String) : PhoneNumber – Look through the collection and return a PhoneNumber with a matching telephone number. If none is found, return null.
  • FindPhoneNumbersByLastName(LastName : String) : List<PhoneNumber> - Look through the collection for PhoneNumber objects with a matching last name. Add those objects to a new collection and return the collection of matching PhoneNumbers. If no items are found, return an empty collection.

Supporting Classes

The PhoneNumber class used in this sample is provided for you. The following class diagram shows the design of this class.

PhoneBook Class

 1 public class PhoneBook
 2 {
 3     private List<PhoneNumber> Number { get; set; }
 4 
 5     public PhoneBook()
 6     {
 7         Number = new List<PhoneNumber>();
 8     }
 9 
10     public void AddPhoneNumber(PhoneNumber entry)
11     {
12         if (entry == null)
13             throw new System.Exception("The phone number entry cannot be null");
14         Number.Add(entry);
15     }
16 
17     public PhoneNumber GetPhoneNumber(int index)
18     {
19         return Number[index];
20     }
21 
22     public int Count
23     {
24         get
25         {
26             return Number.Count;
27         }
28     }
29 
30     public PhoneNumber FindPhoneNumber(string telephoneNumber)
31     {
32         PhoneNumber found = null;
33         foreach (PhoneNumber item in Number)
34         {
35             if (item.Number.Equals(telephoneNumber))
36             {
37                 found = item;
38                 break;
39             }
40         }
41         return found;
42     }
43 
44     public List<PhoneNumber> FindPhoneNumbersByLastName(string lastName)
45     {
46         List<PhoneNumber> found = new List<PhoneNumber>();
47         foreach (PhoneNumber item in Number)
48         {
49             if (item.LastName.Equals(lastName))
50             {
51                 found.Add(item);
52             }
53         }
54         return found;
55     }
56 }

ClassList

The ClassList example maintains a list of students for a particular course by offering methods to add and remove students from a course. In addition, the ClassList ensures that students are not added to the course twice (based on the student’s Id). The following parts of the ClassList must be coded to complete the solution.

  • Constructor – Set the course id and the collection of students. Ensure that the supplied arguments are valid
    • CourseId cannot be empty or null, and must be trimmed of leading or trailing spaces
    • The collection object cannot be null and cannot have more students than the constant CLASS_LIMIT
    • There cannot be any duplicate students in the collection (where a duplicate is defined as two or more Student objects with identical Ids)
  • AddStudent() – Add the supplied student object to the collection. Ensure that
    • The Student object is not null
    • The class limit is not exceeded
    • The Student object does not already exist in the collection (that is, there are no duplicates allowed, based on the student’s id)
  • FindStudent() – Search the collection for a Student with a matching Id. If none is found, return null.
  • RemoveStudent() – Search for a Student with a matching Id; if one is found, remove it from the collection.

Student

ClassList

 1 public class ClassList
 2 {
 3     public const int CLASS_LIMIT = 25;
 4     public string CourseId { get; private set; }
 5     private List<Student> students;
 6 
 7     public ClassList(string courseId, List<Student> students)
 8     {
 9         if (String.IsNullOrEmpty(courseId) || string.IsNullOrEmpty(courseId.Trim\
10 ()))
11             throw new Exception("Course Id is required");
12         if (students == null)
13             throw new Exception("Students cannot be a null list");
14         if (students.Count > CLASS_LIMIT)
15             throw new Exception("Class Limit Exceeded");
16         for (int index = 0; index < students.Count - 1; index++)
17         {
18             int id = students[index].StudentId;
19             for (int innerLoop = index + 1; innerLoop < students.Count; innerLoo\
20 p++)
21                 if (students[innerLoop].StudentId == id)
22                     throw new Exception(
23                             "Duplicate student Ids not allowed in the class list\
24 ");
25         }
26         this.CourseId = courseId.Trim();
27         this.students = students;
28     }
29 
30     public ClassList(string courseId) :
31         this(courseId, new List<Student>())
32     {
33     }
34 
35     public int ClassSize
36     {
37         get
38         {
39             return students.Count;
40         }
41     }
42 
43     public void AddStudent(Student anotherStudent)
44     {
45         if (anotherStudent == null)
46             throw new Exception("Cannot add null student");
47         if (students.Count >= CLASS_LIMIT)
48             throw new Exception("Class Limit Exceeded - Cannot add student");
49         for (int index = 0; index < students.Count - 1; index++)
50         {
51             int id = students[index].StudentId;
52             if (anotherStudent.StudentId == id)
53                 throw new Exception(
54                         "Duplicate student Ids not allowed in the class list");
55         }
56         students.Add(anotherStudent);
57     }
58 
59     public Student FindStudent(int studentId)
60     {
61         Student found = null;
62         for (int index = 0; index < students.Count && found == null; index++)
63             if (students[index].StudentId == studentId)
64                 found = students[index];
65         return found;
66     }
67 
68     public Student RemoveStudent(int studentId)
69     {
70         Student found = FindStudent(studentId);
71         if (found != null)
72             students.Remove(found);
73         return found;
74     }
75 }

MultipleChoiceMarker

This class is used for marking multiple choice exams. It takes a collection of MultipleChoice objects as the answer key when it is first created. It provides a method to mark the student’s answers. The following methods must be coded to complete the solution.

  • MarkExam() – This method takes the supplied exam answers and compares them against the answers in the marking key. It then constructs a Mark object, based on the earned marks and the possible marks (each answer is worth one mark). Before marking the exam, the method must ensure that
    • The supplied collection of multiple choice answers is not null
    • The supplied collection of multiple choice answers has the same number of answers as the MultipleChoiceMarker’s answer key

MultipleChoice and Mark Classes

MultipleChoiceMarker

 1 public class MultipleChoiceMarker
 2 {
 3     private List<MultipleChoice> Key { get; set; }
 4 
 5     public MultipleChoiceMarker(List<MultipleChoice> key)
 6     {
 7         if (key == null)
 8             throw new Exception("Answer key cannot be null");
 9         this.Key = key;
10     }
11 
12     public Mark MarkExam(List<MultipleChoice> examAnswers)
13     {
14         if (examAnswers == null)
15             throw new Exception("Cannot mark null answers");
16         if (examAnswers.Count != Key.Count)
17             throw new Exception(
18                     "The number of student answers does not match the number of \
19 items in the answer key");
20         int possible = Key.Count;
21         int earned = 0;
22         // Calculate earned marks
23         for (int index = 0; index < Key.Count; index++)
24         {
25             if (examAnswers[index] != null)
26                 if (Key[index].Choice == examAnswers[index].Choice)
27                     earned++;
28         }
29         Mark examMark = new Mark(possible, earned);
30         return examMark;
31     }
32 
33     public int Count
34     {
35         get
36         {
37             return Key.Count;
38         }
39     }
40 }

BankStatement

This class represents a bank statement for a BankAccount for a given month. The statement allows BankTransaction objects to be added, and performs deposits and withdrawals on the BankAccount. The statement reports the starting and ending balance and also summarizes the total amount deposited and withdrawn for the month. The following methods must be coded to complete the solution.

  • GetTotalDeposits() – Loop through the collection of transactions to total all those transactions with a positive amount.
  • GetTotalWithdrawals() – Loop through the collection of transactions to total all those transactions with a negative amount.

Account and BankTransaction

Bank Statement

 1 public class BankStatement
 2 {
 3     public Account BankAccount { get; private set; }
 4     public double StartingBalance { get; private set; }
 5     public Month Month { get; private set; }
 6     public List<BankTransaction> Transactions { get; private set; }
 7     public double EndingBalance
 8     {
 9         get
10         {
11             return BankAccount.Balance;
12         }
13     }
14 
15 
16     public BankStatement(Account bankAccount, Month month)
17     {
18         if (bankAccount == null)
19             throw new System.Exception("Bank account cannot be null");
20         this.BankAccount = bankAccount;
21         this.StartingBalance = bankAccount.Balance;
22         this.Month = month;
23         this.Transactions = new List<BankTransaction>();
24     }
25 
26     public void Add(BankTransaction trans)
27     {
28         if (trans == null)
29             throw new System.Exception("Cannot add null transactions");
30         double amount = trans.Amount;
31         if (amount < 0)
32             BankAccount.Withdraw(-amount); // Amount is "negated" to make positi\
33 ve
34         else
35             BankAccount.Deposit(amount);
36         Transactions.Add(trans);
37     }
38 
39     public double TotalDeposits
40     {
41         get
42         {
43             double total = 0;
44             for (int index = 0; index < Transactions.Count; index++)
45             {
46                 BankTransaction aTransaction = Transactions[index];
47                 if (aTransaction.Amount > 0)
48                     total += aTransaction.Amount;
49             }
50             return total;
51         }
52     }
53 
54     public double TotalWithdrawals
55     {
56         get
57         {
58             double total = 0;
59             foreach (BankTransaction aTransaction in Transactions)
60                 if (aTransaction.Amount < 0)
61                     total += aTransaction.Amount;
62             return total;
63         }
64     }
65 }

DeckOfCards

The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports a method to draw a card. The following methods must be coded to complete the solution.

  • Constructor – Create all the cards for all the CardSuit values and all the CardValue values.
  • DrawCard() – Return the card at the “top” of the deck (that is, at position zero). If the deck is empty, return a null.
  • Shuffle() – Mix up the order of the PlayingCards in the Cards list. Shuffle should work regardless of the number of cards still in the deck.

PlayingCard and DeckOfCards

 1 public class DeckOfCards
 2 {
 3     private List<PlayingCard> Cards { get; set; }
 4 
 5     public int Count
 6     { get { return Cards.Count; } }
 7 
 8     public bool IsEmpty
 9     { get { return Count == 0; } }
10 
11     public DeckOfCards()
12     {
13         Cards = new List<PlayingCard>();
14         foreach (PlayingCard.CardSuit suit in System.Enum.GetValues(typeof(Playi\
15 ngCard.CardSuit)))
16             foreach (PlayingCard.CardValue value in System.Enum.GetValues(typeof\
17 (PlayingCard.CardValue)))
18                 Cards.Add(new PlayingCard(value, suit));
19     }
20 
21     public PlayingCard DrawCard()
22     {
23         PlayingCard card = null;
24         if (Cards.Count != 0)
25         {
26             card = Cards[0];
27             Cards.Remove(card);
28         }
29         return card;
30     }
31 
32     public void Shuffle()
33     {
34         for (int counter = 0; counter < 100; counter++)
35         {
36             int index = Rnd.Next(Cards.Count);
37             PlayingCard card = Cards[0];
38             Cards.RemoveAt(0);
39             Cards.Insert(index, card);
40         }
41     }
42 }

Practice examples

  1. PhoneBook – This extends the PhoneBook class by ensuring that duplicate phone numbers are not added to the collection.
  2. Registrar – The Registrar class is responsible to support the enrollment of students. This class maintains the student body as a collection of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program.
  3. BookBag – The BookBag class represents a simple “shopping cart” for a book consignment store. Books are sold on consignment, and customers can add or remove books from their BookBag as well as search their BookBag for books by ISBN. Customers can also see the total price of the items in their BookBag.
  4. DeckOfCards –The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports two public methods: Draw() and Shuffle().

PhoneBook

This extends the PhoneBook class by ensuring that duplicate phone numbers are not added to the collection. Make the following additions and modifications to complete the solution.

  • AddPhoneNumber() – This method must be modified to ensure that the telephone number does not already exist; that is, no duplicate phone numbers are allowed, and an exception must be thrown if the supplied PhoneNumber already exists.

Registrar

The Registrar class is responsible to support the enrolment of students. This class maintains the student body as a collection of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program. Code the following methods to complete the Registrar class.

  • Add() – This method takes the supplied Person information as well as the program of study to create a new Student, adding them to the collection of students in the student body. It returns the student Id for the new enrolment.
  • FindStudent() – This method searches the student body for a student with a matching Id.
  • RemoveStudent() – This method searches the student body for a student with a matching Id and removes them from the collection, if found.
  • GetProgramEnrollment() – This method searches the collection of students to find out how many are enrolled in a particular program. Validate the Program name before performing the search.

BookBag

The BookBag class represents a simple “shopping cart” for a book consignment store. Books are sold on consignment, and customers can add or remove books from their BookBag as well as search their BookBag for books by ISBN. Customers can also see the total price of the items in their BookBag. Code the following methods to complete the BookBag class.

  • GetTotal() – Loop through the collection of books and total the price of all the books. Ensure that the amount is rounded to two decimal places (for dollars and cents).
  • FindBook() – Look through the collection of books to find a book with the specified ISBN number. Throw an exception if the supplied ISBN is null.
  • RemoveBook() – Remove the book with a matching ISBN from the collection of book consignments.

DeckOfCards

Modify the DeckOfCards class to support shuffling of the deck.

  • Shuffle() – This method resets the deck to a full deck of cards and then “shuffles” the deck until the cards are randomly distributed through the collection.

Topic L - Arrays - Not Sorted

Overview

All of these classes are used to illustrate working with un-sorted arrays.

LOGs

General Programming Concepts and Terms

  • Describe what makes an array different from other collections in C#
  • Describe the situations in which arrays are preferable over the use of collections

Code Samples

  1. Math - The Math class is modified to produce the sequence of Fibonacci numbers as an array.
  2. PhoneBook - The PhoneBook class provides simple management of an array of PhoneNumber objects. The PhoneBook allows for adding and retrieving phone numbers; it supports search for phone numbers by the telephone number or by a last name. The PhoneBook is initialized with a physical limit for the arrays, and the actual number of entries in the phone book is tracked as phone numbers are added to the phone book.
  3. ClassList - The ClassList example maintains an array of students for a particular course by offering methods to add and remove students from a course. In addition, the ClassList ensures that students are not added to the course twice (based on the student’s Id). The internal array is of a fixed size (ClassList.CLASS_LIMIT) as well as the logical size of the array. If the ClassList is provided with an array of students in its constructor, that list is “copied” to the internal array of the ClassList object.
  4. MultipleChoiceMarker - This class is used for marking multiple choice exams. It takes an array of MultipleChoice objects as the answer key when it is first created. It provides a method to mark the student’s answers.
  5. BankStatement - This class represents a bank statement for a BankAccount for a given month. The statement allows BankTransaction objects to be added, and performs deposits and withdrawals on the BankAccount. The statement reports the starting and ending balance and also summarizes the total amount deposited and withdrawn for the month.
  6. DeckOfCards -The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports a method to draw a card.

Math

This sample leverages the existing calculation of a number in the Fibonacci sequence to generate the sequence itself. The sequence is returned as an array of integers.

  • FibonacciSequence(Length : Integer) - This method generates the sequence of Fibonacci numbers to a specific length in the sequence; the results are returned as an array of integers. If the specified length is negative, throw an exception.
 1     public static int[] FibonacciSequence(int length)
 2     {
 3         int[] fib = new int[0];
 4         if (length >= 1)
 5         {
 6             fib = new int[length];
 7             for (int index = 0; index < length; index++)
 8                 fib[index] = FibonacciNumber(index + 1);
 9         }
10         return fib;
11     }

PhoneBook

The PhoneBook class provides simple management of an array of PhoneNumber objects. The PhoneBook allows for adding and retrieving phone numbers; it supports search for phone numbers by the telephone number or by a last name. The PhoneBook is initialized with a physical limit for the arrays, and the actual number of entries in the phone book is tracked as phone numbers are added to the phone book.

  • Constructor - Create a new array of PhoneNumber objects for the numbers field.
  • AddPhoneNumber(Entry : PhoneNumber) - Add a PhoneNumber to the array. Ensure that the PhoneNumber exists (is not null) before adding; if the PhoneNumber is null, throw an exception. If there isn’t any room to add the PhoneNumber, then throw an exception.
  • GetPhoneNumber(Index : Integer) : PhoneNumber - Get an item from a particular position in the array.
  • Count : Integer - Get the logical size of the array.
  • FindPhoneNumber(TelephoneNumber : String) : PhoneNumber - Look through the array and return a PhoneNumber with a matching telephone number. If none is found, return null.
  • FindPhoneNumbersByLastName(LastName : String) : PhoneNumber[ ] - Look through the array for PhoneNumber objects with a matching last name. Add those objects to a new array and return it. If no items are found, return an empty array.
  • Supporting Classes
    • ArrayFullException - This class is used to indicate that the array is full and no more items can be added to the array.
    • PhoneNumber - This class contains a telephone number and the name that the number is registered to.
 1 public class PhoneBook
 2 {
 3     private const int MAX_RECORDS = 1000;
 4     private PhoneNumber[] Number { get; set; }
 5     public int Count { get; private set; }
 6 
 7     public PhoneBook()
 8     {
 9         Number = new PhoneNumber[MAX_RECORDS];
10     }
11 
12     public void AddPhoneNumber(PhoneNumber entry)
13     {
14         if (entry == null)
15             throw new System.Exception("The phone number entry cannot be null");
16         if (Count == MAX_RECORDS)
17             throw new ArrayFullException("The phone book cannot hold any more Ph\
18 one Numbers");
19 
20         Number[Count] = entry;
21         Count++;
22     }
23 
24     public PhoneNumber GetPhoneNumber(int index)
25     {
26         return Number[index];
27     }
28 
29     public PhoneNumber FindPhoneNumber(string telephoneNumber)
30     {
31         PhoneNumber found = null;
32         int foundIndex = -1;
33         for (int index = 0; index < Count; index++)
34         {
35             if (Number[index].Number.Equals(telephoneNumber))
36             {
37                 foundIndex = index;
38                 break;
39             }
40         }
41         if (foundIndex >= 0)
42             found = Number[foundIndex];
43         return found;
44     }
45 
46     public PhoneNumber[] FindPhoneNumbersByLastName(string lastName)
47     {
48         PhoneNumber[] found = new PhoneNumber[MAX_RECORDS];
49         // Find the numbers
50         int foundCounter = 0;
51         for (int index = 0; index < Count; index++)
52         {
53             PhoneNumber item = Number[index];
54             if (item.LastName.Equals(lastName))
55             {
56                 found[foundCounter] = item;
57                 foundCounter++;
58             }
59         }
60 
61         // Trim the array
62         PhoneNumber[] foundTrimmed = new PhoneNumber[foundCounter];
63         for (int index = 0; index < foundCounter; index++)
64         {
65             foundTrimmed[index] = found[index];
66         }
67 
68         return foundTrimmed;
69     }
70 }

ClassList

The ClassList example maintains an array of students for a particular course by offering methods to add and remove students from a course. In addition, the ClassList ensures that students are not added to the course twice (based on the student’s Id). The internal array is of a fixed size (ClassList.CLASS_LIMIT) as well as the logical size of the array. If the ClassList is provided with an array of students in its constructor, that list is “copied” to the internal array of the ClassList object.

  • Constructor - Set the course id and the array of students. Ensure that the supplied arguments are valid
    • CourseId cannot be empty or null, and must be trimmed of leading or trailing spaces
    • The array of students cannot be null and cannot have more students than the constant CLASS_LIMIT
    • There cannot be any duplicate students in the array (where a duplicate is defined as two or more Student objects with identical Ids)
  • AddStudent() - Add the supplied student object to the array. Ensure that
    • The Student object is not null
    • The class limit is not exceeded
    • The Student object does not already exist in the array (that is, there are no duplicates allowed, based on the student’s id)
  • FindStudent() - Search the array for a Student with a matching Id. If none is found, return null.
  • RemoveStudent() - Search for a Student with a matching Id; if one is found, remove it from the array.
  • Supporting Classes
    • Student -
  1 public class ClassList
  2 {
  3     public const int CLASS_LIMIT = 25;
  4     public string CourseId { get; private set; }
  5     public Student[] Students { get; private set; }
  6     public int ClassSize { get; private set; }
  7 
  8     public ClassList(string courseId) :
  9         this(courseId, new Student[CLASS_LIMIT])
 10     {
 11     }
 12 
 13     public ClassList(string courseId, Student[] existingStudentList)
 14     {
 15         if (String.IsNullOrEmpty(courseId) || string.IsNullOrEmpty(courseId.Trim\
 16 ()))
 17             throw new Exception("Course Id is required");
 18         if (existingStudentList == null)
 19             throw new Exception("Students cannot be a null list");
 20         if (existingStudentList.Length > CLASS_LIMIT)
 21             throw new Exception("Class Limit Exceeded");
 22         CopyClassList(existingStudentList);
 23         CheckforDuplicates();
 24         this.CourseId = courseId.Trim();
 25     }
 26 
 27     private void CopyClassList(Student[] students)
 28     {
 29         ClassSize = 0;
 30         this.Students = new Student[CLASS_LIMIT];
 31         for (int i = 0; i < students.Length; i++)
 32         {
 33             if (students[i] != null)
 34             {
 35                 this.Students[ClassSize] = students[i];
 36                 ClassSize++;
 37             }
 38             else
 39                 break; // Treat the first null instance as a "flag" indicating t\
 40 he end of actual student objects in the array
 41         }
 42     }
 43 
 44     private void CheckforDuplicates()
 45     {
 46         for (int index = 0; index < ClassSize - 1; index++)
 47         {
 48             int id = Students[index].StudentId;
 49             for (int innerLoop = index + 1; innerLoop < ClassSize; innerLoop++)
 50                 if (Students[innerLoop].StudentId == id)
 51                     throw new Exception(
 52                             "Duplicate student Ids not allowed in the class list\
 53 ");
 54         }
 55     }
 56 
 57     public void AddStudent(Student anotherStudent)
 58     {
 59         if (anotherStudent == null)
 60             throw new Exception("Cannot add null student");
 61         if (ClassSize >= CLASS_LIMIT)
 62             throw new ArrayFullException("Class Limit Exceeded - Cannot add stud\
 63 ent");
 64         for (int index = 0; index < ClassSize - 1; index++)
 65         {
 66             int id = Students[index].StudentId;
 67             if (anotherStudent.StudentId == id)
 68                 throw new Exception(
 69                         "Duplicate student Ids not allowed in the class list");
 70         }
 71         Students[ClassSize] = anotherStudent;
 72         ClassSize++;
 73     }
 74 
 75     public Student FindStudent(int studentId)
 76     {
 77         Student found = null;
 78         int foundPosition = FindIndexPosition(studentId);
 79         if (foundPosition >= 0)
 80             found = Students[foundPosition];
 81         return found;
 82     }
 83 
 84     private int FindIndexPosition(int studentId)
 85     {
 86         int foundPosition = -1;
 87         for (int index = 0; index < ClassSize; index++)
 88             if (Students[index].StudentId == studentId)
 89                 foundPosition = index;
 90         return foundPosition;
 91     }
 92 
 93     public Student RemoveStudent(int studentId)
 94     {
 95         Student found = null;
 96         int foundPosition = FindIndexPosition(studentId);
 97         if (foundPosition >= 0)
 98         {
 99             found = Students[foundPosition];
100             Students[foundPosition] = Students[ClassSize - 1];
101             ClassSize--;
102         }
103         return found;
104     }
105 }

MultipleChoiceMarker

This class is used for marking multiple choice exams. It takes an array of MultipleChoice objects as the answer key when it is first created. It provides a method to mark the student’s answers. The following methods must be coded to complete the solution.

  • MarkExam() - This method takes the supplied exam answers and compares them against the answers in the marking key. It then constructs a Mark object, based on the earned marks and the possible marks (each answer is worth one mark). Before marking the exam, the method must ensure that
    • The supplied array of multiple choice answers is not null
    • The supplied array of multiple choice answers has the same number of answers as the MultipleChoiceMarker’s answer key
  • Supporting Classes
    • MultipleChoice -
 1     public Mark MarkExam(MultipleChoice[] examAnswers)
 2     {
 3         if (examAnswers == null)
 4             throw new Exception("Cannot mark null answers");
 5         if (examAnswers.Length != Key.Length)
 6             throw new Exception(
 7                     "The number of student answers does not match the number of \
 8 items in the answer key");
 9         int possible = Key.Length;
10         int earned = 0;
11         // Calculate earned marks
12         for (int index = 0; index < Key.Length; index++)
13         {
14             if (examAnswers[index] != null)
15                 if (Key[index].Choice == examAnswers[index].Choice)
16                     earned++;
17         }
18         Mark examMark = new Mark(possible, earned);
19         return examMark;
20     }

BankStatement

This class represents a bank statement for a BankAccount for a given month. The statement allows BankTransaction objects to be added, and performs deposits and withdrawals on the BankAccount. The statement reports the starting and ending balance and also summarizes the total amount deposited and withdrawn for the month. The following methods must be coded to complete the solution.

  • Add() - Add a BankTransaction to the array of transactions. If the BankTransaction is null, throw an exception. Otherwise, process the transaction as either a deposit or a withdrawal, depending on if the amount is positive or negative, and then add it to the array of transactions.
  • GetTotalDeposits() - Loop through the array of transactions to total all those transactions with a positive amount.
  • GetTotalWithdrawals() - Loop through the array of transactions to total all those transactions with a negative amount.
  • Sort() - Sorts the array of transactions by date.
  • Supporting Classes
    • Account -
    • BankTransaction -
    • AccountType -
 1 public class BankStatement
 2 {
 3     private const int MAX_TRANSACTIONS = 500;
 4     private int LogicalSize { get; set; }
 5     public Account BankAccount { get; private set; }
 6     public double StartingBalance { get; private set; }
 7     public Month Month { get; private set; }
 8     public BankTransaction[] Transactions { get; private set; }
 9     public double EndingBalance
10     {
11         get
12         {
13             return BankAccount.Balance;
14         }
15     }
16 
17     public BankStatement(Account bankAccount, Month month)
18     {
19         if (bankAccount == null)
20             throw new Exception("Bank account cannot be null");
21         this.BankAccount = bankAccount;
22         this.StartingBalance = bankAccount.Balance;
23         this.Month = month;
24         this.Transactions = new BankTransaction[MAX_TRANSACTIONS];
25         LogicalSize = 0;
26     }
27 
28     public void Add(BankTransaction trans)
29     {
30         if (trans == null)
31             throw new Exception("Cannot add null transactions");
32         if (LogicalSize == MAX_TRANSACTIONS)
33             throw new ArrayFullException("The bank statement cannot accept furth\
34 er transactions; the array is full");
35 
36         double amount = trans.Amount;
37         if (amount < 0)
38             BankAccount.Withdraw(-amount); // Amount is "negated" to make positi\
39 ve
40         else
41             BankAccount.Deposit(amount);
42         Transactions[LogicalSize] = trans;
43         LogicalSize++;
44     }
45 
46     public double TotalDeposits
47     {
48         get
49         {
50             double total = 0;
51             for (int index = 0; index < LogicalSize; index++)
52             {
53                 BankTransaction aTransaction = Transactions[index];
54                 if (aTransaction.Amount > 0)
55                     total += aTransaction.Amount;
56             }
57             return total;
58         }
59     }
60 
61     public double TotalWithdrawals
62     {
63         get
64         {
65             double total = 0;
66             for (int index = 0; index < LogicalSize; index++)
67             {
68                 BankTransaction aTransaction = Transactions[index];
69                 if (aTransaction.Amount < 0)
70                     total += aTransaction.Amount;
71             }
72             return total;
73         }
74     }
75 
76     public void Sort()
77     {
78         Array.Sort<BankTransaction>(Transactions, new BankTransactionDateCompare\
79 r());
80     }
81 }
 1 public class BankTransactionDateComparer : IComparer<BankTransaction>
 2 {
 3     #region IComparer<BankTransaction> Members
 4 
 5     public int Compare(BankTransaction x, BankTransaction y)
 6     {
 7         return x.Date.CompareTo(y.Date);
 8     }
 9     #endregion
10 }

DeckOfCards

The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports a method to draw a card. The following methods must be coded to complete the solution.

  • Constructor - Create all the cards for all the CardSuit values and all the CardValue values.
  • DrawCard() - Return the card at the “top” of the deck (that is, at position zero). If the deck is empty, return a null.
  • IsEmpty - Returns true if the logical size of the deck of cards has reached zero, otherwise it returns false.
  • Supporting Classes
    • PlayingCard - The PlayingCard class, along with its two enumerated types CardSuit and CardValue, are the basis for the DeckOfCards class.
 1 public class DeckOfCards
 2 {
 3     private PlayingCard[] Cards { get; set; }
 4     public int Count { get; private set; }
 5     public bool IsEmpty { get { return Count == 0; } }
 6 
 7     public DeckOfCards()
 8     {
 9         Cards = new PlayingCard[52];
10 
11         foreach (PlayingCard.CardSuit suit in System.Enum.GetValues(typeof(Playi\
12 ngCard.CardSuit)))
13             foreach (PlayingCard.CardValue value in System.Enum.GetValues(typeof\
14 (PlayingCard.CardValue)))
15             {
16                 Cards[Count] = new PlayingCard(value, suit);
17                 Count++;
18             }
19     }
20 
21     public PlayingCard DrawCard()
22     {
23         PlayingCard card = null;
24         if (Count != 0)
25         {
26             // get the first card
27             card = Cards[0];
28             // "pull" the other items up in the array
29             for (int i = 0; i < Count - 1; i++)
30             {
31                 Cards[i] = Cards[i + 1];
32             }
33             // "clear" the last element & adjust the count
34             Cards[Count - 1] = null;
35             Count--;
36         }
37         return card;
38     }
39 
40     public void Shuffle()
41     {
42         for (int counter = 0; counter < 100; counter++)
43         {
44             int index = Rnd.Next(Count);
45             PlayingCard card = Cards[0];
46             Cards[0] = Cards[index];
47             Cards[index] = card;
48         }
49     }
50 }

Practice Exercises

  1. PhoneBook – This extends the PhoneBook class by ensuring that duplicate phone numbers are not added to the collection.
  2. Registrar – The Registrar class is responsible to support the enrollment of students. This class maintains the student body as a collection of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program.
  3. BookBag – The BookBag class represents a simple “shopping cart” for a book consignment store. Books are sold on consignment, and customers can add or remove books from their BookBag as well as search their BookBag for books by ISBN. Customers can also see the total price of the items in their BookBag.
  4. DeckOfCards –The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports two public methods: Draw() and Shuffle().
  5. CD – [Not yet implemented] This class represents an array of Songs. It supports the ability to calculate the total running time and the average running time of all the songs on the CD.

PhoneBook

This extends the PhoneBook class by ensuring that duplicate phone numbers are not added to the collection. Make the following additions and modifications to complete the solution.

  • AddPhoneNumber() – This method must be modified to ensure that the telephone number does not already exist; that is, no duplicate phone numbers are allowed, and an exception must be thrown if the supplied PhoneNumber already exists.

Registrar

The Registrar class is responsible to support the enrolment of students. This class maintains the student body as a collection of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program.

The Registrar class is responsible to support the enrolment of students. This class maintains the student body as an array of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program. Code the following methods to complete the Registrar class.

  • Add() – This method takes the supplied Person information as well as the program of study to create a new Student, adding them to the array of students in the student body. It returns the student Id for the new enrolment.
  • FindStudent() – This method searches the student body for a student with a matching Id.
  • RemoveStudent() – This method searches the student body for a student with a matching Id and removes them from the collection, if found.
  • GetProgramEnrollment() – This method searches the array of students to find out how many are enrolled in a particular program. Validate the Program name before performing the search.

BookBag

The BookBag class represents a simple “shopping cart” for a book consignment store. Books are sold on consignment, and customers can add or remove books from their BookBag as well as search their BookBag for books by ISBN. Customers can also see the total price of the items in their BookBag. Code the following methods to complete the BookBag class.

  • GetTotal() – Loop through the array of books and total the price of all the books. Ensure that the amount is rounded to two decimal places (for dollars and cents).
  • FindBook() – Look through the array of books to find a book with the specified ISBN number. Throw an exception if the supplied ISBN is null.
  • RemoveBook() – Remove the book with a matching ISBN from the array of book consignments.

DeckOfCards

The DeckOfCards class represents a complete deck of cards. When the deck is first created, a card is created for each suit. The DeckOfCards supports two public methods: Draw() and Shuffle(). Modify the DeckOfCards class to support shuffling of the deck.

  • Shuffle() – This method resets the deck to a full deck of cards and then “shuffles” the deck until the cards are randomly distributed through the collection.

CD

[Not yet implemented]

This class represents an array of Songs. It supports the ability to calculate the total running time and the average running time of all the songs on the CD.

Topic M - Arrays - Sorted

Overview

The focus of this topic is sorting arrays and performing searches, inserts, and deletions from a sorted array.

LOGs

Code Samples

  1. BranchVault - The BranchVault class manages safety deposit boxes. Each box has a unique number, and may be assigned to a particular account number. This class demonstrates the bubble sort and the binary search.
  2. PhoneBook - The PhoneBook class provides simple management of an array of PhoneNumber objects. The PhoneBook allows for adding and retrieving phone numbers; it supports search for phone numbers by the telephone number or by a last name. The PhoneBook is initialized with a physical limit for the arrays, and the actual number of entries in the phone book is tracked as phone numbers are added to the phone book. The AddPhoneNumber() method demonstrates adding to an array that is to be sorted.
  3. ClassList -The ClassList example maintains an array of students for a particular course by offering methods to add and remove students from a course. In addition, the ClassList ensures that students are not added to the course twice (based on the student’s Id). The internal array is of a fixed size (ClassList.CLASS_LIMIT) as well as the logical size of the array. If the ClassList is provided with an array of students in its constructor, that list is “copied” to the internal array of the ClassList object.
  4. BankStatement - [Not Implemented - Sorting by Date] This class represents a bank statement for a BankAccount for a given month. The statement allows BankTransaction objects to be added, and performs deposits and withdrawals on the BankAccount. The statement reports the starting and ending balance and also summarizes the total amount deposited and withdrawn for the month.

BranchVault

The BranchVault class manages safety deposit boxes. Each box has a unique number, and may be assigned to a particular account number. This class demonstrates the bubble sort and the binary search. Code the following methods to complete this class.

  • SortBoxes() - This private method performs a bubble sort of the array of SafetyDepositBox objects. The boxes are to be sorted in ascending order according to their box number.
  • Find() - This public method performs a binary search of the SafetyDepositBox array for a particular box number. If the box number is not found, it returns a null.

PhoneBook

The PhoneBook class provides simple management of an array of PhoneNumber objects. The PhoneBook allows for adding and retrieving phone numbers; it supports search for phone numbers by the telephone number or by a last name. The PhoneBook is initialized with a physical limit for the arrays, and the actual number of entries in the phone book is tracked as phone numbers are added to the phone book. The AddPhoneNumber() method demonstrates adding to an array that is to be sorted. Code the following methods to complete this class.

  • BubbleSortByPhoneNumber() - This private method performs a bubble sort of the array of PhoneNumber objects. They are to be sorted in ascending order, based on the telephone number.
  • InsertSortedByPhoneNumber() - This private method will insert a PhoneNumber object into the array while preserving the sort order of the array (based on the array being sorted in ascending order by telephone number).

ClassList

The ClassList example maintains an array of students for a particular course by offering methods to add and remove students from a course. In addition, the ClassList ensures that students are not added to the course twice (based on the student’s Id). The internal array is of a fixed size (ClassList.CLASS_LIMIT) as well as the logical size of the array. If the ClassList is provided with an array of students in its constructor, that list is “copied” to the internal array of the ClassList object (to ensure that the internal array has the appropriate physical size).

All of the Student objects in the ClassList are stored in a sorted array, based on the student Id. Code the following methods to complete this class.

  • AddInsertSortedByStudentId() - This private method is called by both the AddStudent method and the constructor. It adds a student to the class list while maintaining a sort order (sorted by student Id in ascending order).
  • FindStudent() - This public method performs a binary search of the array of Student objects. If the Student is found, this method will return that Student object, otherwise it will return null.
  • RemoveStudent() - This public method will remove a particular Student from the array, while maintaining the sort order of the array. If the Student is found, this method will return that Student object, otherwise it will return a null.
  • GetStudents() - This public method will generate and return a copy of the array of Student objects.
    Supporting Classes

Practice Exercises

  1. PhoneBook - [Sorting by Name and Sorting by Phone Number] This extends the PhoneBook class by adding sorting by phone number and a binary search.
  2. Registrar - [Sorting by ID] The Registrar class is responsible to support the enrollment of students. This class maintains the student body as a collection of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program.
  3. CDLibrary - [Not Yet Implemented] This class manages a collection of CDs that are stored in alphabetical order. It supports searching the library for CDs based on the title.

PhoneBook

Extend the PhoneBook class by adding sorting by name and a binary search when sorted by number.

  • FindPhoneNumberUsingBinarySearch() - This private method will do a binary search of the PhoneNumber array to find a PhoneNumber with a matching telephone number.
  • BubbleSortByLastNameThenFirstName() - This private method sorts the array by first name within last name, in ascending alphabetical order.

Registrar

[Sorting by ID] The Registrar class is responsible to support the enrolment of students. This class maintains the student body as an array of Student objects. It supports the ability to find and remove students, switch students to another program, and get the number of students enrolled in a specific program. Code the following methods to complete the Registrar class.

  • RemoveStudent() - This method must be modified to maintain the sort order when removing a student from the array.

CDLibrary

[Not Yet Implemented]

OOP - Getting Real

Topic N - Modularization and Utility Classes

Overview

This topic examines the technique of modularization as a way to simplify complex logic. In addition, this topic looks at the use of “utility” classes to aid in simplifying code and enabling better “code-reuse” for repetitive tasks. This technique of “simplifying” complex logic is also known as “refactoring”.

Modularization will be examined in the context of simplifying the internal working of a class’ methods and in the context of organizing and simplifying a driver. For classes, modularization is simply taking any repetitive or overly-complex code out of the class’ existing methods and placing that code inside of private methods. For console drivers (which typically consist of static methods), to be continued…

LOGs

Code Sample

  1. CD - This class represents a CD of Songs. It supports a public method to get long songs (which are songs whose RunningTime is greater than the average running time). A private method called resizeArray() is created to “modularize” this public method’s behaviour.
  2. RunningTime - This class represents an amount of time in minutes and seconds, and is used as the length of time for a Song. This class introduces the Scanner class for one of its constructors, which generates the running time from a string that is formatted as “minutes:seconds” (such as “5:39”, which would be 5 minutes and 30 seconds).
    This class also uses an internal private method called paddZero() that ensures the seconds whose values are less than 10 have a leading zero when converted to a string.
  3. TextFormatter - This class provides static methods for common string formatting needs, such as right and left justifying strings.
  4. MusicInfoFormatter - This class provides static methods for formatting CD information, such as the CD’s title and the information for a given Song. This kind of formatting is commonly seen, for example, in CD players that display the currently playing song.

CD

This class represents a CD of Songs. It supports a public method to get long songs (which are songs whose RunningTime is greater than the average running time). A private method called resizeArray() is created to “modularize” this public method’s behaviour.

  • getLongSongs() - Refactor this method so that the code that resizes the array of songs is put into its own private method, called resizeArray.

RunningTime

This class represents an amount of time in minutes and seconds, and is used as the length of time for a Song. This class introduces the Scanner class for one of its constructors, which generates the running time from a string that is formatted as “minutes:seconds” (such as “5:39”, which would be 5 minutes and 30 seconds).

This class also uses an internal private method called paddZero() that ensures the seconds whose values are less than 10 have a leading zero when converted to a string.

  • toString() - Refactor this method to use a new private method called paddZero. The paddZero method will return a string version of the integer value passed in and will ensure that the string has a leading zero character if the supplied value is less than ten.

TextFormatter

This class provides static methods for common string formatting.

  • leftJustify() - This static method will append spaces after the supplied text until the supplied text is at least the required length. Note that this method will not trim the supplied text if it is longer than the required length.
  • rightJustify() - This static method will prepend spaces before the supplied text until the supplied text is at least the required length. Note that this method will not trim the supplied text if it is longer than the required length.
  • shortenWithEllipsis() - This static method will check the length of the supplied text against the desired length. If the supplied text is longer, it will trim off trailing characters and append an ellipsis (…) , while ensuring that the resulting text is the desired length.

MusicInfoFormatter

This class provides static methods for formatting CD information, such as the CD’s title and the information for a given Song. This kind of formatting is commonly seen, for example, in CD players that display the currently playing song.

  • formatTitleInfo() - This method generates a string that has title information for a CD that includes the CDs title and the name of the performing artist. The title name must be shortened with an ellipsis to a maximum length of 30 characters. The generated string must use the following overall format:
    Title: ‘CD Title’ (Artist: Performing Artist Name)
  • formatSongInfo() - This method generates a string that follows specific formatting for a given song. It must use the following format:
     Track Number: Song Title [Running Time] (by Song Writer)
    The running time must be in the format of MM:SS.

## Practice Exercises

  1. TextFormatter - This class provides static methods for formatting strings. Expand this class by providing overloaded versions of the leftJustify() and rightJustify() methods that allow the padding character to be supplied through the parameter list.

TextFormatter

This class provides static methods for formatting strings. Expand this class by providing overloaded versions of the leftJustify() and rightJustify() methods that allow the padding character to be supplied through the parameter list.

Topic O - File I/O

Overview

All of the File I/O examples follow the same design pattern. This pattern is a form of what is called the Adapter Pattern. Each class has the following characteristics.

All of the text files used in this topic have their records delimited by carriage returns and their fields delimited by commas. File input is achieved through use of the Scanner class. The Scanner is also used to parse each record by specifying the use of the comma delimiter.

File Input/Output (IO) is all about using files for storing and retrieving data. These files exist “outside” of your program, and code is required to transfer the data between the file and the objects/variables in your program.

Data inside of files can be stored in either a binary or a text format. All of these examples will deal with text files. When using text files, the text itself needs to follow some pattern in order to distinguish the individual pieces of data from each other.

An old and traditional way of storing the text is to use a CSV (Comma-Separated Values) format. In this format, each row of information (also known as a “record” of data) is broken down into individual pieces of data by separating each piece (or “field”) by a comma. Rows are separated by a new line (or “carriage return”) marker. This format has had the advantage of being easy for humans to read and edit directly; it is also fairly flexible and programmers can easily adapt the form to fit the shape of the data they wish to store.

A more modern approach is to store the textual information in XML (eXtensible Markup Language) format. While also being human-readable and easy to format, XML has the advantage of making it easier for computer programs to read and save data that is both relational and complex. XML format uses “tags” (or “mark-up”) to wrap data. For example, if information on a person (“Bob Smith”) is stored in an XML file, it might look like this.

1 <Person>
2   <FirstName>Bob</FirstName>
3   <LastName>Smith</LastName>
4 </Person>

File Input/Output is best performed by having one class (or object) deal with formatting the data and a separate class to deal with directly accessing the file. In the following examples, the CSVFileIO and XMLFileIO classes read and write directly to the files, while the other classes (which end with “Adapter”) are concerned with determining the format of the data.

CSVFileIO

 1 /// <summary>
 2 /// The CSVFileStorage class provides simple reading of all the lines of text of\
 3  a CSV (Comma-Separated-Values) file.
 4 /// </summary>
 5 public class CSVFileIO
 6 {
 7     public string FilePath { get; private set; }
 8 
 9     /// <summary>
10     /// Initializes a new instance of the CSVFileStorage class.
11     /// </summary>
12     public CSVFileIO(string filePath)
13     {
14         FilePath = filePath;
15     }
16 
17     public List<string> ReadAllLines()
18     {
19         List<string> lines = new List<string>();
20         using (TextReader reader = new StreamReader(FilePath))
21         {
22             string aSingleLine = reader.ReadLine();
23             while (aSingleLine != null)
24             {
25                 lines.Add(aSingleLine);
26                 aSingleLine = reader.ReadLine();
27             }
28         }
29         return lines;
30     }
31 
32     public void WriteAllLines(List<string> lines, bool append)
33     {
34         using (TextWriter writer = new StreamWriter(FilePath, append))
35         {
36             foreach (string line in lines)
37             {
38                 writer.WriteLine(line);
39             }
40         }
41     }
42 }

XMLFileIO

 1 /// <summary>
 2 /// The XMLFileIO class manages loading and saving any type to an XML file.
 3 /// </summary>
 4 public class XMLFileIO<T>
 5 {
 6     public string FilePath { get; private set; }
 7 
 8     public XMLFileIO(string filePath)
 9     {
10         FilePath = filePath;
11     }
12 
13     public List<T> LoadAll()
14     {
15         XmlSerializer deserializer = new XmlSerializer(typeof(List<T>));
16         List<T> data;
17         using (TextReader textReader = new StreamReader(FilePath))
18         {
19             data = (List<T>)deserializer.Deserialize(textReader);
20             textReader.Close();
21         }
22         return data;
23     }
24 
25     public void SaveAll(List<T> data, bool append)
26     {
27         if (append && File.Exists(FilePath))
28         {
29             List<T> existingData = LoadAll();
30             existingData.AddRange(data);
31             data = existingData;
32         }
33         using (Stream stream = File.Open(FilePath, FileMode.OpenOrCreate))
34         {
35             XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
36             using (TextWriter writer = new StreamWriter(stream))
37             {
38                 serializer.Serialize(writer, data);
39                 writer.Close();
40             }
41         }
42     }
43 }

LOGs

  • A constructor that takes a valid File object
  • A method called fill() that takes an array as the parameter and returns the number of entries created in the array from having read the file.

Code Samples

  • PhoneNumberFileAdapter - This reads a text file to fill a list of PhoneNumber data.
  • StudentFileAdapter - This reads a text file to fill a list of Student data.
  • BookFileAdapter - This reads a text file to fill a list of Book data. Note that in this example, not every field in the record structure is used in creating the required Book objects; unused fields are simply read and “discarded” by the BookFileAdapter. In addition, the Book class and text file used in this example allows for a book to have multiple authors.
  • SafetyDepositBoxFileAdapter - This reads a text file to fill a list of SafetyDepositBox data. Note that in this particular example, some records may not have an account number for the box number.

PhoneNumberFileAdapter

This reads a text file to fill a list of PhoneNumber data.

  • Record Structure:
    1. Telephone Number : String
    2. Last Name : String
    3. First Name : String
 1 public class PhoneNumberFileAdapter
 2 {
 3     #region Read from a file
 4     public static List<PhoneNumber> LoadList(string filePath, FileFormat format)
 5     {
 6         List<PhoneNumber> data;
 7         if (format == FileFormat.CSV)
 8             data = LoadList(new CSVFileIO(filePath));
 9         else
10             data = LoadList(new XMLFileIO<PhoneNumber>(filePath));
11         return data;
12     }
13 
14     private static List<PhoneNumber> LoadList(CSVFileIO reader)
15     {
16         List<PhoneNumber> data = new List<PhoneNumber>();
17         List<string> lines = reader.ReadAllLines();
18         foreach (string individualLine in lines)
19         {
20             // code specifics here..
21             string[] fields = individualLine.Split(',');
22             string firstName = fields[0], lastName = fields[1], number = fields[\
23 2];
24             data.Add(new PhoneNumber(firstName, lastName, number));
25         }
26         return data;
27     }
28 
29     private static List<PhoneNumber> LoadList(XMLFileIO<PhoneNumber> reader)
30     {
31         return reader.LoadAll();
32     }
33     #endregion
34 
35     #region Write to a file
36     public static void SaveList(List<PhoneNumber> data, string fileName, FileFor\
37 mat format, bool append)
38     {
39         if (format == FileFormat.CSV)
40             SaveList(new CSVFileIO(fileName), data, append);
41         else
42             SaveList(new XMLFileIO<PhoneNumber>(fileName), data, append);
43     }
44 
45     private static void SaveList(CSVFileIO writer, List<PhoneNumber> data, bool \
46 append)
47     {
48         List<string> lines = new List<string>();
49         foreach (PhoneNumber item in data)
50         {
51             lines.Add(item.FirstName + "," + item.LastName + "," + item.Number);
52         }
53         writer.WriteAllLines(lines, append);
54     }
55 
56     private static void SaveList(XMLFileIO<PhoneNumber> writer, List<PhoneNumber\
57 > data, bool append)
58     {
59         writer.SaveAll(data, append);
60     }
61     #endregion
62 }

StudentFileAdapter

This reads a text file to fill a list of Student data.

  • Record Structure:
    1. Student Id : Integer
    2. Name : String
    3. Gender : GenderType
 1 public class StudentFileAdapter
 2 {
 3     #region Read from a file
 4     public static List<Student> LoadList(string filePath, FileFormat format)
 5     {
 6         List<Student> data;
 7         if (format == FileFormat.CSV)
 8             data = LoadList(new CSVFileIO(filePath));
 9         else
10             data = LoadList(new XMLFileIO<Student>(filePath));
11         return data;
12     }
13 
14     private static List<Student> LoadList(CSVFileIO reader)
15     {
16         List<Student> data = new List<Student>();
17         List<string> lines = reader.ReadAllLines();
18         foreach (string individualLine in lines)
19         {
20             // code specifics here..
21             string[] fields = individualLine.Split(',');
22             int id = System.Convert.ToInt32(fields[0]);
23             string name = fields[1];
24             GenderType gender = (GenderType)System.Enum.Parse(typeof(GenderType)\
25 , fields[2]);
26             data.Add(new Student(name, gender, id));
27         }
28         return data;
29     }
30 
31     private static List<Student> LoadList(XMLFileIO<Student> reader)
32     {
33         return reader.LoadAll();
34     }
35     #endregion
36 
37     #region Write to a file
38     public static void SaveList(List<Student> data, string fileName, FileFormat \
39 format, bool append)
40     {
41         if (format == FileFormat.CSV)
42             SaveList(new CSVFileIO(fileName), data, append);
43         else
44             SaveList(new XMLFileIO<Student>(fileName), data, append);
45     }
46 
47     private static void SaveList(CSVFileIO writer, List<Student> data, bool appe\
48 nd)
49     {
50         List<string> lines = new List<string>();
51         foreach (Student item in data)
52         {
53             lines.Add(item.StudentId.ToString() + "," + item.Name + "," + item.G\
54 ender.ToString());
55         }
56         writer.WriteAllLines(lines, append);
57     }
58 
59     private static void SaveList(XMLFileIO<Student> writer, List<Student> data, \
60 bool append)
61     {
62         writer.SaveAll(data, append);
63     }
64     #endregion
65 }

BookFileAdapter

This reads a CSV text file to fill a list of Book data. Note that in this example, not every field in the record structure of CSV files is used in creating the required Book objects; unused fields are simply read and “discarded” by the BookFileAdapter. In addition, the Book class and text file used in this example allows for a book to have multiple authors.

  • Record Structure in the file:
    1. Title : String
    2. Authors : String - delimited by semi-colons
    3. Publication year : Integer
    4. Publisher : String
    5. Format : String
    6. Dewey Decimal Number : String - could be empty in the file
    7. ISBN : String
    8. Number of Pages : Integer
    9. Cover Price : Money
  1 /// <summary>
  2 /// BookFileAdapter provides a way to read and write
  3 /// Book information to and from text files.
  4 /// </summary>
  5 /// <remarks>
  6 /// This class requires that the file structure be in the following format:
  7 /// <ol><li>Title : String
  8 /// <li>Authors : String[]
  9 /// <ol><li>The Author information is a semicolon (;) separated list of authors
 10 /// </li></ol>
 11 /// <li>Publication Year : Integer
 12 /// <li>Publisher : String
 13 /// <li>Format : String
 14 /// <li>Dewey Decimal Number : String
 15 /// <li>ISBN : String
 16 /// <li>Number of Pages : Integer
 17 /// <li>Cover Price : Money
 18 /// </ol>
 19 /// <para>
 20 /// This method fills a List of Book data. Each Book only needs
 21 /// the title, the authors (as an array of Strings), and the ISBN. 
 22 /// Therefore, the other data in the file will simply be discarded as it
 23 /// is read. In the file, the Author information is a semicolon (;)
 24 /// separated list of authors.
 25 /// </para>
 26 /// </remarks>
 27 public class BookFileAdapter
 28 {
 29     #region Read from a file
 30     public static List<Book> LoadList(string filePath, FileFormat format)
 31     {
 32         List<Book> data;
 33         if (format == FileFormat.CSV)
 34             data = LoadList(new CSVFileIO(filePath));
 35         else
 36             data = LoadList(new XMLFileIO<Book>(filePath));
 37         return data;
 38     }
 39 
 40     private static List<Book> LoadList(CSVFileIO reader)
 41     {
 42         List<Book> data = new List<Book>();
 43         List<string> lines = reader.ReadAllLines();
 44         foreach (string individualLine in lines)
 45         {
 46             string title, authorList;
 47             ISBN bookUPC;
 48             // Parse the record
 49             string[] fields = individualLine.Split(',');
 50             title = fields[0];
 51             authorList = fields[1];
 52             // fields[2] Publication Year
 53             // fields[3] Publisher
 54             // fields[4] Format
 55             // fields[5] Dewey Decimal Number
 56             bookUPC = new ISBN(fields[6]);
 57             // fields[7] Number of Pages
 58             // fields[8] Cover Price
 59 
 60             // Parse the authorList
 61             string[] authors = null;
 62             authors = authorList.Split(';');
 63 
 64             // Create the book and add it to the array
 65             data.Add(new Book(title, authors, bookUPC));
 66         }
 67         return data;
 68     }
 69 
 70     private static List<Book> LoadList(XMLFileIO<Book> reader)
 71     {
 72         return reader.LoadAll();
 73     }
 74     #endregion
 75 
 76     #region Write to a file
 77     public static void SaveList(List<Book> data, string fileName, FileFormat for\
 78 mat, bool append)
 79     {
 80         if (format == FileFormat.CSV)
 81             SaveList(new CSVFileIO(fileName), data, append);
 82         else
 83             SaveList(new XMLFileIO<Book>(fileName), data, append);
 84     }
 85 
 86     private static void SaveList(CSVFileIO writer, List<Book> data, bool append)
 87     {
 88         List<string> lines = new List<string>();
 89         foreach (Book item in data)
 90         {
 91             string formattedRecord;
 92             formattedRecord = item.Title;
 93             formattedRecord += string.Join(";", item.Authors);
 94             formattedRecord += item.Isbn.BarCode;
 95 
 96             lines.Add(formattedRecord);
 97         }
 98         writer.WriteAllLines(lines, append);
 99     }
100 
101     private static void SaveList(XMLFileIO<Book> writer, List<Book> data, bool a\
102 ppend)
103     {
104         writer.SaveAll(data, append);
105     }
106     #endregion
107 }

SafetyDepositBoxFileAdapter

This reads a text file to fill a list of SafetyDepositBox data. Note that in this particular example, some records may not have an account number for the box number.

  • Record Structure:
    1. Box Number : Integer
    2. Account Number : Integer - may not exist
 1 /// <summary>
 2 /// SafetyDepositBoxFileAdapter provides a way to read and write
 3 /// SafetyDepositBox information to and from text files.
 4 /// </summary>
 5 /// <remarks>
 6 /// This class requires that the file structure be in the following format:
 7 /// <ol><li>StudentId : Integer
 8 /// <li>StudentName : String
 9 /// <li>StudentGender : GenderType
10 /// </ol>
11 /// </remarks>
12 public class SafetyDepositBoxFileAdapter
13 {
14     #region Read from a file
15     public static List<SafetyDepositBox> LoadList(string filePath, FileFormat fo\
16 rmat)
17     {
18         List<SafetyDepositBox> data;
19         if (format == FileFormat.CSV)
20             data = LoadList(new CSVFileIO(filePath));
21         else
22             data = LoadList(new XMLFileIO<SafetyDepositBox>(filePath));
23         return data;
24     }
25 
26     private static List<SafetyDepositBox> LoadList(CSVFileIO reader)
27     {
28         List<SafetyDepositBox> data = new List<SafetyDepositBox>();
29         List<string> lines = reader.ReadAllLines();
30         foreach (string individualLine in lines)
31         {
32             // code specifics here..
33             string[] fields = individualLine.Split(',');
34             int boxNumber, accountNumber;
35             boxNumber = Convert.ToInt32(fields[0]);
36             if (fields.Length > 1)
37             {
38                 accountNumber = Convert.ToInt32(fields[1]);
39                 data.Add(new SafetyDepositBox(boxNumber, accountNumber));
40             }
41             else
42             {
43                 data.Add(new SafetyDepositBox(boxNumber));
44             }
45         }
46         return data;
47     }
48 
49     private static List<SafetyDepositBox> LoadList(XMLFileIO<SafetyDepositBox> r\
50 eader)
51     {
52         return reader.LoadAll();
53     }
54     #endregion
55 
56     #region Write to a file
57     public static void SaveList(List<SafetyDepositBox> data, string fileName, Fi\
58 leFormat format, bool append)
59     {
60         if (format == FileFormat.CSV)
61             SaveList(new CSVFileIO(fileName), data, append);
62         else
63             SaveList(new XMLFileIO<SafetyDepositBox>(fileName), data, append);
64     }
65 
66     private static void SaveList(CSVFileIO writer, List<SafetyDepositBox> data, \
67 bool append)
68     {
69         List<string> lines = new List<string>();
70         foreach (SafetyDepositBox item in data)
71         {
72             string lineOfText = item.BoxNumber.ToString();
73             if (item.IsLeased)
74                 lineOfText += "," + item.AccountNumber;
75             lines.Add(lineOfText);
76         }
77         writer.WriteAllLines(lines, append);
78     }
79 
80     private static void SaveList(XMLFileIO<SafetyDepositBox> writer, List<Safety\
81 DepositBox> data, bool append)
82     {
83         writer.SaveAll(data, append);
84     }
85     #endregion
86 }

Practice Exercises

  1. PersonFileAdapter – This reads a text file to fill an array of Person data.
  2. SongFileAdapter – This reads a text file to fill an array of Song data.

PersonFileAdapter

This reads a text file to fill an array of Person data.

  • Record Structure:
    1. Record Structure:
    2. First Name : String
    3. Last Name : String
    4. Gender : GenderType
    5. Birthdate : Date

SongFileAdapter

This reads a text file to fill an array of Song data.

  • Record Structure:
    1. Record Structure:
    2. Title : String
    3. Song Writer : String
    4. Length : RunningTime

Topic P - Exception Handling

Overview

The code for real-world programs is typically divided into distinct “layers” in order to make programs more flexible and maintainable. The layer that corresponds to the drivers we have seen so far is called the “Presentation Layer”. It’s called a “presentation layer” because its sole purpose is to interact with a user.

Almost all exception handling should take place in the driver, or presentation layer, of an application. Part of the reason for this is because the presentation layer is the “top” or “front-most” part of the program. When exceptions are handled at this layer, an application can report on the errors that occurred and give opportunity for the user to choose their desired response to the error.

LOGS

Code Samples

  1. DemoTestingForExceptions - This class is a very simple demonstration of how to catch exceptions and how exception handling allows a program to keep running even when a problem occurs.
  2. DemoBookFileAdapter - This class demonstrates displaying book information read from a file. It also demonstrates attempting to read from a file or directory that does not exist, and capturing an exception thrown by classes within the .Net Framework.
  3. (Not Available) MediaPlayer - This class demonstrates a complete working program that presents the user with a menu of various tasks related to loading and displaying songs on a CD. This class also demonstrates exception handling.

DemoTestingForExceptions

This class is a very simple demonstration of how to catch exceptions and how exception handling allows a program to keep running even when a problem occurs.

 1 public class DemoTestingForExceptions
 2 {
 3     private static ConsoleColor _Normal = Console.ForegroundColor;
 4 
 5     public static void Start()
 6     {
 7         string[] actualAuthors = { "Dan Gilleland", "B. N. D'erdundat", "Dr. Ink\
 8 " };
 9         string actualTitle = "Java: Bean There, Done That";
10         string actualBarCode = "0-12345678-9";
11 
12         // Demo a normal creation of a Book object
13         Console.WriteLine("Testing valid data");
14         TestBook(actualTitle, actualAuthors, actualBarCode);
15 
16         // Demo testing the Book class for various combinations of data
17         Console.WriteLine("Testing empty title");
18         TestBook("", actualAuthors, actualBarCode);
19         Console.WriteLine("Testing null title");
20         TestBook(null, actualAuthors, actualBarCode);
21         Console.WriteLine("Testing empty author list");
22         TestBook(actualTitle, new String[0], actualBarCode);
23         Console.WriteLine("Testing null author list");
24         TestBook(actualTitle, null, actualBarCode);
25         Console.WriteLine("Testing empty bar code");
26         TestBook(actualTitle, actualAuthors, "");
27         Console.WriteLine("Testing null bar code");
28         TestBook(actualTitle, actualAuthors, null);
29         Console.WriteLine("Testing all nulls");
30         TestBook(null, null, null);
31     }
32 
33     private static void TestBook(string title, string[] authors, string barCode)
34     {
35         try
36         {
37             Book theBook = new Book(title, authors, new ISBN(barCode));
38             Console.WriteLine("I creatd the following book:");
39             Console.WriteLine("    Title: " + theBook.Title);
40             Console.Write("    Authors: ");
41             foreach (string author in theBook.Authors)
42                 Console.Write(author + ", ");
43             Console.WriteLine("(" + theBook.Authors.Length + " authors)");
44             Console.WriteLine("    ISBN: " + theBook.Isbn.BarCode);
45             Console.WriteLine("-----------------------------------------");
46             Console.WriteLine();
47         }
48         catch (Exception ex)
49         {
50             Console.ForegroundColor = ConsoleColor.Red;
51             Console.WriteLine("!-- " + ex.Message + " --!");
52             Console.ForegroundColor = _Normal;
53         }
54     }
55 }

DemoBookFileAdapter

This class demonstrates displaying book information read from a file. It also demonstrates attempting to read from a file or directory that does not exist, and capturing an exception thrown by classes within the .Net Framework.

 1 public class DemoBookFileAdapter
 2 {
 3     private static ConsoleColor _Normal = Console.ForegroundColor;
 4 
 5     public static void Start()
 6     {
 7         try
 8         {
 9             Book[] myBooks;
10             myBooks = BookFileAdapter.LoadList("BookList.txt", FileFormat.CSV).T\
11 oArray();
12             DisplayBooks(myBooks);
13 
14             myBooks = BookFileAdapter.LoadList(@"V:\ThisDriveNameDoesNotExist", \
15 FileFormat.CSV).ToArray();
16             myBooks = BookFileAdapter.LoadList("ThisFileNameDoesNotExist", FileF\
17 ormat.CSV).ToArray();
18 
19             DisplayBooks(myBooks);
20         }
21         catch (DirectoryNotFoundException ex)
22         {
23             Console.ForegroundColor = ConsoleColor.Red;
24             Console.WriteLine("!-- " + ex.Message + " --!");
25             Console.ForegroundColor = _Normal;
26         }
27         catch (FileNotFoundException ex)
28         {
29             Console.ForegroundColor = ConsoleColor.Red;
30             Console.WriteLine("!-- " + ex.Message + " --!");
31             Console.ForegroundColor = _Normal;
32         }
33         catch (Exception ex)
34         {
35             Console.ForegroundColor = ConsoleColor.Red;
36             Console.WriteLine("!-- " + ex.Message + " --!");
37             Console.ForegroundColor = _Normal;
38         }
39     }
40 
41     private static void DisplayBooks(Book[] myBooks)
42     {
43         for (int index = 0; index < myBooks.Length; index++)
44         {
45             Console.WriteLine("Title  : " + myBooks[index].Title);
46             Console.WriteLine("ISBN   : " + myBooks[index].Isbn.BarCode);
47             Console.WriteLine("Authors: ");
48             foreach (string author in myBooks[index].Authors)
49                 Console.WriteLine("\t" + author);
50             Console.WriteLine();
51         }
52     }
53 }

MediaPlayer

This class demonstrates a complete working program that presents the user with a menu of various tasks related to loading and displaying songs on a CD. This class also demonstrates exception handling.

Practice Exercises

  1. Testing Suite - Using any two classes from previous topics, create a program that tests the construction of objects with complete exception handling.
  2. Working Program - With the help of the UserPrompt class, create a simple program involving any classes from previous topics. Be sure to include exception handling in your program.

Testing Suite

Using any two classes from previous topics, create a program that tests the construction of objects with complete exception handling.

Working Program

With the help of the UserPrompt class, create a simple program involving any classes from previous topics. Be sure to include exception handling in your program.

Appendix

Learning Outcome Guide Review

Learning Outcome Guides (LOGs) are an excellent tool for instructors in the classroom and for students when they are reviewing their notes for each class. A Learning Outcome Guide is simply a list of specific things that the student (or reader, in this case) should be able to do or understand as a result of learning the material. LOGs give the learner the ability to self-check their progress (“Can I do X?”).

This appendix provides a shortened review of what each learning outcome is all about. For instructors, it provides a quick summary of the intent of the LOG. For students, it provides the answers. :)

Topic A - Starting Classes

OOP Basics

Define the term “class” as used in OOP
A class is a template that acts as the basis for creating objects and describes a) What it “looks like”, and b) How it “works”.
Explain the purpose of classes in computer programs
Classes allow programmers to define their own complex data types, complete with their own internal data (fields) and behaviours (methods).
Describe the primary keywords used in declaring a class
public/private - identifies whether the class is visible to other code; public means all other code can see this class, while private means
class - declares that this is a class definition (tells the compiler to interpret this as a new “classification” or “kind” of data type; that is, a complex )
Define the term “method” and give an example
A method is a set of instructions that manipulate information.
Create simple classes with methods only
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Explain what is meant by “overloading”
Overloading describes creating more than one method with the same method name (but different parameters) in the same class. Overloaded methods allow for alternate ways to perform the same general behaviour of an object or a class.
Describe the syntax of a method declaration (aka, method implementation)
Explain how classes with identical names can be distinguished from each other
Different classes can have identical names provided that they exist in different namespaces. (Namespaces help to prevent a “collision” or confusion on the part of a compiler when confronted with two or more classes with the same name.)

General Programming Concepts and Terms

Define the term “keyword” as it applies to programming languages
A keyword is a special command or instruction that is part of (that is, built in to, or “intrinsic” to) a programming language. Keywords are “reserved” words, meaning that they cannot be used for other purposes, such as being a name of a class, a variable, or a method.
Define the term “identifier” as it applies to programming languages
An identifier is a programmer-supplied name for some item, either a class name, a field or local variable, or a method.
Define the term “program statement” and identify how the computer recognizes a program statement
A program statement is combination of keywords, identifiers, punctuation, and/or literal values that, together, represent a single “instruction” or “command” that a compiler can translate into executable code.
Define the term “syntax” as it applies to programming languages.
Syntax refers to the rules of a programming language that define how to combine keywords, identifiers, literal values, and other symbols to create specific instructions for a computer program.
Identify the entry point for every computer program
Every computer program must supply a method called “main” as the method that the operating system will call (execute) to begin running the program.
Perform simple output to the console using System.Console
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Identify the basic structure of a simple C# program
A C# program must consist of at least one class and have a single “main” method as the program’s entry point. Typically, a C# program will consist of a “driver” (the class that has the main method) and other classes used to represent objects (data) in the program.
Explain what is meant by a “driver”
A “driver” is a method or set of methods that “run” or control the execution of a program; it’s responsibility is to direct and maintain the “lifetime” of a program, and makes use of classes and objects to achieve the purpose of the program. Every driver begins its execution in a method called “main” (which is the name given for the entry point for every computer program).
Explain what is meant by a “case-sensitive” programming language
A case-sensitive language is one where the compiler regards “identical” words as different if they differ only in their case. In other words, a case-sensitive language will regard two identifiers are distinct if the only difference is whether they are spelled with upper- or lower-case characters. For example, HelloWorld and Helloworld will be regarded as different because one has a capital “W” and the other has a lower-case “w”.
Explain what is meant by a “strongly-typed” programming language
A “strongly-typed” programming language is one that requires all variables or objects to always match or conform to whatever data type they were originally declared as. Some programming languages (such as C#Script) allow variables or objects to “change” their data type whenever a programmer wishes to use it for other purposes; strongly-typed languages do not allow variables to “change” the type of data they can store. Strongly-typed programming languages provide better security and make it more difficult for programmers to inadvertently corrupt, mangle or expose important data.
Explain what “string concatenation” is and how it works
String concatenation is where two or more strings are “combined” to create a longer string; this is represented in C# by “adding” strings together. For example, given two literal strings whose values are “One” and “word”, the result of “One” + “word” would be the string “Oneword”.
Define and distinguish the terms “argument” and “parameter”
A parameter is a variable declared in the parameter list of a method declaration; parameters are used to hold or capture information (values) that are sent or passed into the method. An argument is some value (either a literal value, a value stored in a variable, or some other value that comes from an “expression”) that is sent (passed) into a method; arguments appear in the syntax of method calls.
Use single-line, multi-line and XML comments as a means of documenting code
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
List the four pieces of information to include in comments at the top of every source file
The file name, author, creation date, and purpose of the file.

Intro to IDEs

Define the term “IDE” as it relates to software development tools
The acronym “IDE” stands for “Integrated Development Environment”. An IDE brings together separate, but complementary, software development tools that aide developers in creating computer programs. For example, most IDEs bring a sophisticated text editor together with file management tools, a compiler, a debugger, and a program execution environment, as well as other useful tools.
Define the terms “project” and “solution”
A solution is a folder in which one or more projects can be managed and “kept together”; it is the “area” in which a developer can create projects. A project is as set of classes designed to achieve a particular purpose; a project may represent a complete program in and of itself, or may be a single component of a larger, more complex computer program.
Identify the various parts of the IDE (Integrated Development Environment) used in this course
[– image here –]
Create a new project in the IDE for this course
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Create new source files in the IDE for this course
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Add existing files to a project
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.

Topic B - Starting Classes

OOP Basics

Define the term “object” as used in OOP
An object is an instance of a class.
Each object has its own “state” (values) for its fields, and all objects based on any given class are distinct from each other. The internal values (state)for an object’s fields can be changed independently of other objects of the same class.
Describe the syntax of static and non-static method declarations
Static methods are “shared” by all instances (objects) of a class, and can be called without even having to have an instance of the method’s class.
Non-static methods, on the other hand, can only be called for a given object (instance of a class) and will “act on” (or “act on behalf of”) that object (and any other objects are not affected by the given object’s method call).
Compare and contrast the syntax for method declarations (implementations) vs. method calls (for both static and non-static methods)
Define the term “field” as used in OOP and give an example
A field is a variable that belongs to a class and is shared by all the methods of a class.
private static int sharedCount; // a static field
private String name; // an instance field
Compare and contrast instance and class members, for both methods and fields
Static methods are shared by all instances of a class, and can be called independently from instances of a class, whereas instance methods can only be called if you have an object (an instance of a class).
Static fields are shared by and fully accessible to all methods, but non-static fields, also called “instance” fields, are only shared by other non-static methods. In the following example, the first field is a static fields and the second is an instance field.
Identify the “member access operator” and explain it’s purpose
The member access operator (also called the “dot” operator) is the period. It is used to access a field or method of an object or a class.
Create (instantiate) objects
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Distinguish between classes and objects in OOP
A class is merely a “template” for creating objects and describes a) what the object will “look like” (that is, what fields or data it will contain) and b) how the object works (that is, what methods can be called and what those methods will do).
Explain what is meant by the phrase “type extensibility” and how classes represent “complex” data types in OOP
“Type extensibility” is where a programming language allows developers to create or design their own “data types”.
All programming languages support the “simplistic” data types (for numeric information, such as whole and real numbers, as well as simple text or character representation). These simple data types are intrinsic (“build into”) the programming language. A language that supports “type extensions” simply allows the programmer to create or design new data types; these new types are typically “complex” types made up of zero or more other (either simple or complex) data types.

General Programming Concepts and Terms

List the three categories of simple information
Textual, numeric, and conceptual
Define the term “intrinsic data type”
An “intrinsic data type” is one that is built into the programming language.
Explain what an assignment statement is and how it works
An assignment statement is an instruction to the computer to store a value into a specific variable (or object). The variable (or object) is placed on the left-hand side of the equals sign, and the value to be stored in the object is placed on the right-hand side of the equals sign.
The left-hand side of an assignment statement must be a single variable, whereas the right-hand side can be any expression as long as the resulting value of the expression is the same (or compatible) data type as the variable on the left-hand side.
Compare and contrast the three categories of simple information with the complex types of information which classes represent
Simple information is either textual (such as a name), numeric (such as a total or count), or “conceptual” (that is, representing a more “abstract” value that is neither textual or numeric). An example of a textual type in C# is the char type. An example of a numeric type in C# is the double type. An example of a “conceptual” type is the boolean type. A variable whose type is one of the simple types can only hold a single, simple value at any given time.
Complex types of information can be constructed from many simple types or from simple and complex types. A “class” is used to describe or define what the complex type looks like and how it works. Complex types are the basis for creating objects, and while any given “object variable” can only reference a single object, that object may consist of many distinct “values”, each one being stored in a field that is “hidden” (or “encapsulated”) inside the object.
Explain the advantages of using classes and objects instead of only using intrinsic data types
By using objects, the programmer is no longer limited to having to only deal with simple values. By designing and using complex types (classes), the programmer is able to create complex programs using less code in a way that is simpler and more reliable than if the programmer were only allowed to use the simple types built into the programming language.

Topic C - Starting Classes

OOP Basics

Define the term “encapsulation” as used in OOP
Encapsulation is a design principle of “hiding” fields in a class by always making them private and only allowing a “controlled access” to the values in fields by providing getters and setters.
Encapsulation also includes the idea that all of the items (methods and fields) in a class always have access to each other (inside the class) while also providing the ability to control the external access to those items (methods and fields) by other classes.
Explain why encapsulation is a good design principle
Encapsulation is a good design principle because every object must be responsible for its own data; if an object “exposes” its fields for direct access (that is, makes those fields public), then that object cannot exert any control over the values that may be stored in those fields.
Encapsulation, as a part of Object Oriented design, also facilitates the aspect of “grouping together” related fields and methods.
Define the term “access specifier” and identify where it occurs in the code for a class
An access specifier is a keyword in a programming language that identifies whether an item, such as a field or a method, is or is not accessible from outside of an object.
List the two access specifiers that are used in this course
The two main access specifiers of this course are public and private.
Describe the difference between “private” and “public” members of a class
Private methods and fields are not accessible from outside the class (they are only internally accessible). Public methods and fields are accessible both from outside and from inside the class.
Describe the concepts of “Properties” as used in OOP
“Properties” allow for controlled access to read (get) or change (set) fields in a class. When fields are used with properties, the field is sometimes called a “backing store” because it stores the actual value that is accessed through the property.
Properties do not have to have fields as “backing stores”; a property can calculate its value (during a get) instead of simply retrieving it from a field. These types of properties are sometimes called “derived” properties.
A “getter” is a method whose sole responsibility is to provide a means for retrieving (getting) a value. Getters are typically (that is, almost always) public, thereby allowing information (typically stored in a field) to be “extracted” from outside the class.
A “setter” is a method whose sole responsibility is to control the storing of a value into a field of a class. Setters are typically (that is, almost always) public, thereby allowing code that is outside the class a way to store information inside the class (that is, inside of the fields of a class).
Define the term “backing store” as it applies to properties and fields
A “backing store” is a field that stores information which is accessible only through a property; the field variable is used in the “background” by the property’s get and/or set.
Describe and explain the purpose and function of a constructor for a class
A constructor has one purpose: To ensure that all the fields of the class are filled with meaningful values at the moment that an object is created (instantiated).
Describe the syntax of a class constructor
TBA…
Identify when a class constructor is “called”
A class’ constructor is never explicitly “called” in the traditional sense of “invoking” (calling) a method on a class. Rather, the class constructor is “called” when an object is instantiated using the new keyword.
Define the term “class scope” as used in OOP
Class scope is the idea that all of the methods and fields of a class are accessible to all the methods in a class.
Define the term “local scope” as used in OOP
Local scope is the idea that all of the variables declared in a parameter list and inside of the body of a method are only accessible from within that method. In other words, parameters and “local variables” are only accessible from within the method (or block of code) in which they were declared.
Define the term “state” as applied to objects used in OOP
“State” is the idea that objects have an “internal value” at any given point in time (as viewed from outside the class’ methods). In other words, an object has “state” simply because it has fields which hold (or “store”) information.
Objects are responsible for ensuring that their internal state is always valid (or “stable”) at the end of each method’s execution.
Define the term “override” as used in OOP
Override is a term used to indicate that a class is re-defining the behaviour of a method that it is inheriting from a base class.
All classes inherit from a class called Object. The Object class defines common methods that every class must have, such as equals() and ToString(). Any class has the option to “override” or re-define how the equals() and ToString() methods work for that class.
Explain the purpose and function of the ToString() method and why we sometimes want to change its default behaviour when we create classes
The ToString() method is meant to provide a way to represent any given object as a String. This method is inherited from the Object class; the Object class, by default, returns the data type of the object, expressed as a String.
A programmer may choose to override the default behaviour of the ToString() method in order to represent the internal state of the object (that is, the values stored in some select fields) as a String.
Create simple class diagrams to represent classes
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.

General Programming Concepts and Terms

List three levels of scope
Class scope - All the fields and methods of a class share a common class scope, and are accessible to any and all methods of a class.
Local scope - All the variables and parameters of a method are accessible only to the body of the method; local variables and parameters are not accessible to other methods.
Block scope - All the variables declared inside a block are only accessible to the code inside that block. A block of code is denoted by being enclosed by a set of curly braces - { }.

Topic D - Debugging and Testing

General Programming Concepts and Terms

Explain the role of testing as it applies to software development
Testing is a form of “quality assurance” in which steps are taken to verify that a program is behaving or working as intended.
Testing has traditionally been treated as a “follow-up” activity that takes place after a program is written. Currently, other approaches, such as TDD (Test-Driven Development) place the “testing” activity at the start of the programming efforts, thereby integrating tests as a driving element in software development.
Define and compare the terms “compile-time error” and “run-time error”
A “compile-time error” is an error where a program does not “compile”. In other words, compile-time errors are due to code that does not follow the rules of the programming language.
A “run-time error” is an error where a running program does not produce the desired result. In other words, run-time errors are due to logical errors in a computer program. Sometimes these errors are “fatal” (meaning that they result in “abnormal program termination” - the program “crashes”). Other times the errors are subtle; the subtle errors can be the most difficult to detect, particularly when relying on “manual” verification, such as found with ad-hoc test drivers.
Define the term “test driver”
A “test driver” is a driver (which is a program with a main method) whose sole purpose is to “test” the components of a program. Test drivers provide a simple “ad-hoc” form of testing. Test drivers are basically considered “throw-away” programs, as their usefulness does not extend beyond the tests.
Create simple ad-hoc test drivers to test for run-time errors
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Define the term “TDD”
TDD refers to “Test Driven Development”. Test Driven Development is an approach to programming that starts with creating “unit tests” that reflect the business and design requirements of a program, and then writing the classes and methods that will pass the unit tests. The idea here is to help drive the programmer toward code that “stays on focus” of the needs of and solutions for a given problem.
Compare and contrast Test Drivers and Unit Tests
Test Drivers are small programs with a main() that tests classes by creating objects, calling methods, and output results to the console.
Unit Tests are small “units” (which are simply methods) that calls methods on objects and classes and “tests” if they work as intended by running “asserts”. Unit Tests display the results of the test in Red/Green/Yellow results, where Red ( ) represents run-time errors, Yellow ( ) represents ignored tests, and Green ( ) represents success.
Define the terms “false positive” and “false negative”
A “false positive” is a test result that shows success for a test which in reality should be a failure.
A “false negative” is a test result that shows failure for a test which in reality should be a success.
Both false positives and false negatives are a result of an error in the unit test (or test driver).
List three downfalls of using Test Drivers
Can grow in size and become bulky & difficult to use (poor scalability)
Requires considerable effort to generate and distinguish tests
Difficult to verify tests due to heavy manual intervention & verification
Identify four benefits of using Unit Tests
Provides simple tests to verify specific parts of a system
Easy to verify tests (minimal manual effort); errors are clearly identified and described
A clear graphical response it provided, leading to the popular development mantra “Keep it Green”
Increases productivity (by focusing development efforts)
Captures design requirements in code
Increases programmer confidence when modifying and expanding code
Easily isolate smaller parts (“units”) of the program for verification; these tests can run independently of each other (even if the other tests have compiler issues with the classes being tested).
Add unit testing libraries and unit testing packages to existing programs
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Use unit tests to validate the requirements of a class’ design and behaviour
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Diagnose and correct software problems by using unit tests
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.

## Topic E - Expressions and Math

OOP Basics

Explain how method overloading is applied to constructors
Using overloaded constructors means that it is possible to create objects in “different ways”. What this means is that when a class has an overloaded constructor, anytime we wish to instantiate (create) an object using the new keyword, we must be explicit about which constructor we are invoking (calling).

General Programming Concepts and Terms

Name at least three kinds of program statements commonly seen in all high-level programming languages
Declaration/initialization statements
Assignment statements
Flow-control statements
Distinguish between Variables, Values and Data Types
Variables act as “containers” for values, allowing programmers to access and manipulate the value via the variable.
A Value is simply a piece of data. It may be simple (such as a number or some text), or it may be complex (that is, based on a class).
Data Types are “blueprints” or “templates” that describe what values “look like” and how they “work”.
When a variable is declared to be of a certain data type, this means that the variable is only allowed to hold values that match that data type.
List the five basic rules governing variables, values and data types
Any value stored in a variable must be of the same data type as the variable.
Variables must be declared before they can be used.
A variable’s data type can only be declared once.
Each primitive variable can only hold one value at a given time.
Each variable must have a distinct name.
List the intrinsic (built-in) data types in C#
Textual data types: char
Numeric data types: int, long, short, byte, double, float
Conceptual data types: bool
Explain what is meant by the phrase “type extensibility”
Modern languages are able to define brand new data types (classes), thereby increasing the ability to manage complex information and perform complex operations.
Define the terms Reference Type and Value Type as they apply to data types in C#
A “value type” is a data type whose information is stored “directly” in a variable. In memory, this means that there is only one direct location in memory where the data is stored. The only data types that are “value types” are those that are built into the language: char, int, byte, short, long, double, float, and bool.
For example, in the following statements,
  double count;
  count = 0;
the value of zero is stored directly at the memory location labelled count.
A “reference type” is a data type whose information is stored and accessible only “indirectly” through the variable. Whenever you declare a “reference type” variable, that variable actually stores a memory address of where the “actual” object is stored. The “actual” object is only created using the new keyword; that new keyword will set aside a separate, “new”, area of memory which is then accessed “indirectly” through the “reference type” variable.
For example, in the following statements,
  Car hotrod;
  hotrod = new Car();
the first line creates a single memory location, labelled hotrod, which will store the address to a Car object. The second line creates the actual Car object somewhere in memory and then the address to that object is stored in the hotrod variable.
All classes, whether those supplied in the C# library (such as the String and Date classes) or those created by you, are “reference types”.
Define the term Identifier
An identifier is the term used to refer to some “named” item in your code. Typically, we apply the term identifier to variable names, field names, property names and method names.
Create and initialize variables in C#
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Explain what is meant by the terms “scope” and “lifetime” as they apply to variables
Scope refers to the “context” in which a variable is accessible. Fields are variables with “Class Scope”, meaning that they are accessible to all the methods from within the class; properties, methods and constructors also have class scope. Parameters and variables declared within a method have “local scope”, meaning that they can only be accessed by code from within the method that they are declared in.
Lifetime refers to the period of time from when a variable is first declared to the time that they are “destroyed”. For fields, their lifetime exists as long as the object in which they are declared. For parameters and local variables, they exist only as long as there is still code to be executed in the method to which they belong; as soon as the method “returns” or exits, these local variables and parameters are destroyed.
Describe what is meant by the term “expression”
An expression is any combination of literal values (literal strings or numbers), variables, operators, or method calls which return a value. An expression can be as simple as a single variable or literal value, or it can be as complex as a long mathematical expression that involves calls to various methods.
An important characteristic of expressions is to note that they are always reduced to a single value by the computer.
Explain the difference between program statements and expressions as well as how the two relate to each other
A program statement represents a complete instruction that the compiler can translate into machine language. An analogy can be made that a program statement is like a sentence: Just as a sentence communicates a complete thought or idea, so a program statement represents a complete instruction.
An expression is not a complete instruction; rather it is a combination of values, variables, method calls, and operators that will eventually be reduced to a single “value” by the computer. Expressions are often a part of program statements, and their role in program statements is akin to the role of phrases in English sentences: A phrase is not, by itself, a complete thought or idea; it must exist in a context in order to have its complete meaning. In a similar way, expressions play a part in the grammar of various kinds of program statements, providing a way of generating values that will be used by the program statement.
List the four general sets of operators in C#
Assignment, Arithmetic, Relational, and Logical
Describe the two basic rules of using arithmetic operators that every compiler must follow.
For an arithmetic operator to work, both sides of the operator must be the same data type.
The resulting value of an arithmetic operation is of the same data type as the operands involved in the operation.
Use the arithmetic operators to create arithmetic expressions
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Explain what is meant by “integer division” and how that can be useful in solving particular problems regarding numbers.
“Integer division” is the term for what occurs when both operands of a division operation are whole numbers (which can apply to byte, int, short, and long data types). Because the basic rule of arithmetic operations is that the data type of the final value of an operation is the same as that of the operands, any time we divide one whole number by another whole number, the result is a whole number: Any “fractional portion” is automatically discarded.
For example,
1 / 3 -> 0
7 / 2 -> 3
Explain the purpose of the modulus (%) operator.
The modulus operator (%) is used to find the remainder of a division operation. This operator is typically used with integers.
List and describe how to use the various assignment operators in C#
All assignment operators require a variable on the left side and an expression on the right side. Assignment operators take the final value of the expression on the right and stores that value in the variable on the left.
=
This is the standard assignment operator. It performs a simple assignment of the value on the right to the variable on the left.
+=
This assignment operator takes the value on the right and adds it to the value already existing in the variable on the left. For example
x += y;
is the same as writing
x = x + y;
-=
This assignment operator takes the value on the right and subtracts it from the value already existing in the variable on the left. For example
x -= y;
is the same as writing
x = x - y;
*=
This assignment operator takes the value on the right and multiplies it to the value already existing in the variable on the left. For example
x *= y;
is the same as writing
x = x * y;
/=
This assignment operator takes the value on the right and divides it into the value already existing in the variable on the left. For example
x /= y;
is the same as writing
x = x / y;
%/
This assignment operator takes the value on the right and divides it into the value already existing in the variable on the left to generate the remainder. For example
x %= y;
is the same as writing
x = x % y;
Explain the difference between binary and unary operators
Binary operators require a variable or value on both sides of the operator.
Unary operators only require a variable or value on one side of the operator for it to perform its operation.
Demonstrate understanding of operator precedence and how to override the default precedence of the arithmetic operators
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Summarize and distinguish the rules for automatic type conversion involving arithmetic operators and the assignment operator
Automatic type conversion takes place for the data types that are built in to the programming language.
The basic rule of automatic type conversion involving arithmetic operators is that if two operands of a binary operator are of different data types, then the value of the one that is “smaller” is “upsized” to the data type of the “larger” operand.
For the assignment operators, automatic type conversion is limited to only allowing the right-hand value to be converted to the data type of the variable on the left-hand side. Type conversion cannot convert a value from the right hand side if that value’s data type is larger than the data type of the left hand side; if the right hand side is a larger data type than the left hand side, then a compiler error is generated that states the value cannot “fit” into the variable on the left.
Determine the final data type for expressions involving mixed data types and type conversion
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Describe “type casting” and explain how to use it appropriately.
Type casting is where we explicitly tell the compiler to “re-interpret” a particular value as a different data type than what the compiler is currently treating it as.
Type casting is appropriate when we want to avoid integer division in order to retain the fractional portion in the final result. For example, if the variables numerator and denominator are both integers, it is appropriate to use type casting in the following line of code:
double value = (double) (numerator) / denominator;
It is also appropriate when we need to “downcast” a value from a larger data type to a smaller data type (and can do so safely).
Note that type casting does not (and can not) change the data type of a variable; type casting is only a re-interpretation of a value.
Note that type casting is not the same as converting. For example, any attempt to type cast the char value of the character ‘4’ to an int will not produce a numeric value of 4; rather, it will produce the numeric value of 52 (which is the underlying decimal value for the character ‘4’).
Compare and contrast the prefix and postfix behaviour of the unary arithmetic operators
Identify and explain how to use the common Math library routines (for Power, Square Root, Absolute, random numbers, pi, trigonometry, and the various types of rounding)
Use Math rounding methods with arithmetic expressions to round real numbers to a specific precision
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Create random whole number values within a specific range
Use type casting appropriately in C#
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Create constants in C#
Constants in C# are created using the keyword final and assigning the value to the constant at the time that it is declared. For example, to create a constant value for GST, you could code the following:
const double GST = 0.05; // 5% GST
Explain how arithmetic operations affect character values in C#
Because the char data type is regarded as one of the “integral” data types, along with int, short and long, any arithmetic operations on char values will manipulate the underlying value as if it were simply a whole number.
(Note: “Integral” data types are data types without a fractional component.)
List the most common math functions of the Math class
Demonstrate how to use the various Math functions in simple programs
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
List and describe some of the commonly used fields and methods of the String class
.ToUpper() - returns a String that has all the characters converted to their upper-case equivalents.
.ToLower() - returns a String that has all the characters converted to their lower-case equivalents.
.Trim() - returns a String that has all leading and trailing whitespace removed from the original String.
.Chars(int index) - returns the character at the index position for the string. (All strings have the first character as index position zero.)
.Substring(int beginIndex) and .Substring(int beginIndex, int endIndex) - returns a string that is the text inside of the first string beginning at a specified index. (All strings have the first character as index position zero.)
.Length - returns the total number of characters in the string.
Demonstrate how to use “String Arithmetic” (concatenation)
To concatenate two or more strings, use the plus (+) operator.
To append one string onto another, simply add the string to be appended to the end of the original string. For example, to append “ing” to the word “end” in order to produce “ending”, you could do the following:
String myWord = "end";
myWord = myWord + "ing"
To pre-pend one string on another, add the string to be prepended to the start of the original string. For example, to prepend “un” to the word “imaginative” so as to produce “unimaginative”, you would do the following:
String myWord = "imaginative";
myWord = "un" + myWord;
List the equivalent “wrapper” classes for each of the primitive types.
Integer for int
Character for char
Double for double
Byte for byte
Long for long
Short for short
Float for float

## Topic F - If-Else Structures

General Programming Concepts and Terms

Describe and draw a diagram of the If-Then-Else logical structure
Identify the programming statement that corresponds to the If-Then-Else logical structure.
The if-else statement is used for If-Then-Else logical structures in C#.
Translate If-Then-Else structures into code.
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Describe what is meant by a “conditional expression”
A conditional expression is any expression which results in a Boolean (true/false) value.
List the operator precedence for mixing logical, arithmetic, and relational operations
Logical Not (!), Arithmetic, Relational, Logical And/Or
List the relational operators

, >=, ==, <=, <

Greater Than (>)
Greater Than or Equal To (>=)
Is Equal To (==)
Less Than or Equal To (<=)
Less Than (<)
List the logical operators
&&,   , !
And (&&)
Or (   )
Not (!)
Use relational, logical, and arithmetic operators to construct conditional expressions
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Demonstrate an understanding of operator precedence in conditional expressions
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Use statement blocks to allow nesting program statements into control structures
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Define the term “boundary condition” as it relates to if-else statements and testing
A “boundary condition” is also known as a “fence-post condition”.
The “boundary” is the border of a range of values that are regarded as “acceptable” for some variable. For example, if a particular variable named percent is to represent a range of values from zero through 100 inclusive, then the “boundary” values are zero and 100.
A boundary condition, then, is a test or comparison that is made against some boundary values. For example,
1 if(percent >= 0 && percent <= 100)
2 {
3     // code to perform if true
4 }
5 else
6 {
7     // code to perform if false
8 }
Identify the correct way to compare or check the contents of strings in conditional expressions
The proper way to compare String values is to use the .Equals(), .CompareTo() and .IsNullOrEmpty() methods.
Generally, the relational operators (==, <, etc) should not be used directly on string values.
List and describe the commonly used fields and methods of the String class that would be used in if-else statements
.Equals(String) - returns a Boolean, true or false, as to whether the two strings are or are not equal.
.Equals(String, StringComparison) - returns a Boolean, true or false, as to whether the two strings are or are not equal, according to the value of the StringComparison argument (which includes values to ignore any differences in upper and lower case).
.CompareTo(String anotherString) - compares two strings “lexographically” (that is, alphabetically) and returns either
a. a zero if they are the same, or
b. a negative number if anotherString is greater than the first string, or
c. a positive number if anotherString is less than the first string
.IsNullOrEmpty(string) - returns true if the string is an empty string (“”), false if it is not an empty string.
.IsNullOrWhiteSpace(string) - (only in .NET 4.0 and higher) returns true if the string is null, an empty string (“”), or all “whitespace” (tab, newline) characters; false if it is not.
.Length - returns the total number of characters in the string.

Topic G - Raising Exceptions

General Programming Concepts and Terms

Describe how object-oriented programs run.
A computer program is a set of instructions for manipulating information.
Every computer program has a single starting (or entry) point called the Main method. The main method is responsible to “run” (or “execute) the program, and when the main method exits, the program closes and stops “running”. The length of time that a program is running is called its “lifetime”. As a program runs, it executes instructions in the program’s code, one at a time; this is called the “flow of execution”.
During the lifetime of a program, the main method creates objects and calls methods on those objects. Each method is basically a set of instructions to be executed. Those methods can, in turn, create other objects and call other methods.
Whenever a method is called, the operating system keeps track of which method is calling another method through something known as a “call stack”.
Describe what is meant by a “call stack”.
A call stack is a mechanism to track which method is calling another method while the program is running. Call stacks allow the computer to know where to “return to” when a method exits.
At any given point during the program’s execution, the method that is currently executing is referred to as the “called method”. When the called method exits, it returns control back to the “calling method”, thereby allowing the calling method to continue its own execution.
Whenever a method calls another method, the “calling method” pauses and waits for the “called method” to finish; once the called method returns, the calling method will resume executing its own code.
Define the term “Exception”
An exception is a message of some run-time error that has occurred in a program. Exceptions interrupt the normal flow of execution in methods, forcing the method to immediately exit. Methods generate exceptions by using the “throw” statement. Any method may generate an exception (including constructors).
The throw statement exits the method by sending back an object (called an “Exception Object”, or simply an “Exception”) that can be used to identify the kind of error that has occurred. The calling method then has the opportunity to deal with (or “handle”) the error; if the calling method does not handle the error, then the exception continues to go back through the call stack until it finds a method that will handle the exception.
If none of the methods on the call stack handle the exception that was thrown, control is eventually returned to the main method. If the main method does not handle the exception, then the exception is sent to the operating system. At that point, the operating system shuts down the program in what is called an “abnormal program termination”.
Describe what is meant by the phrase “raising (or throwing) an exception”
To “raise an exception” (or “throw an exception”) is to force a method to exit prematurely by sending back an “Exception object”.
Describe the role that exceptions play in a computer program
An exception is an interruption in the normal flow of execution in a method; exceptions force the method to immediately exit.
Exceptions provide a way for methods (including constructors) to report errors to whatever code that is calling the method. These errors are usually (but not always) due to invalid information passed into the methods via the parameters. Through the use of exceptions, methods can perform validation on their parameters and report any errors that might prevent the method from being able to perform its task.
Identify the three most commonly used Exception types used in this course.
.NET Framework
ArgumentException - Typically thrown whenever an argument passed to a parameter does not have an “acceptable” value.
For example, if a method has a parameter called “percent”, it might perform validation to ensure that the value is not less than zero or greater than 100. If the value is not valid, it may be appropriate to throw an ArgumentException.
ArgumentNullException - Typically thrown whenever an object is checked for and found to be “null”.
(ArgumentNullException will be discussed in the topic on Enumerations and Composition.)
*Exception** - This represents a general exception, and can be used whenever there is no other suitable exception type.

OOP Basics

Explain why methods (including constructors) should perform validation of their parameter values
One of the principles of object-oriented design is that objects must be responsible for ensuring that their fields have correct values. This is known as ensuring a “valid state” for an object.
Typically, the values that are stored in fields come in through the parameters of a constructor or a method. Because objects are responsible for ensuring a valid state, the class’ methods must check all parameters that might allow “invalid” data to be passed in.
Explain the significance of raising an exception in the constructor
If an exception is thrown from a constructor (or passes through it on its way up the call stack), the object’s construction is interrupted. Because the construction of that object is interrupted, the object does not get instantiated.
Use exceptions as part of the validation of parameter values in methods and constructors.
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Explain why property setters are a good place for throwing exceptions.
Generally speaking, the only method that should directly modify a field is the property setter associated with the field. Because of this principle, the property setter is the ideal place to perform validation and to throw exceptions. When validation takes place here, it eliminates the need for duplicating the validation elsewhere in the class.
Validating input and throwing exceptions from within setters is a good way to follow the DRY principle: “Don’t Repeat Yourself”.
Identify when constructors should throw exceptions directly.
Whenever a field has a property setter that performs validation, the constructor should use that setter to store information in the field. If no property setter is available to process the parameter values sent through the constructor, then the constructor should perform its own validation on those parameters.

Topic H - Case Structures

General Programming Concepts and Terms

Describe the syntax of the switch statement
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.
Discuss the limitations of the switch statement in C# and the available alternatives for the times that we can’t use a switch statement
Switch statements only work with integral data types (such as char and int).
The individual case values must be constants; variable expressions are not allowed for the matching cases.
Switch statements only check for exact matches (meaning that there is an implied “is-equal-to” comparison); other relational comparisons, such as greater than or less than, are not allowed.
When it is not possible to use switch statements, case structures can be written up as nested and/or stacked if-else structures to make use of the if-else statement.

Topic I Enumerations and Composition

General Programming Concepts and Terms

Define the term Enumeration
An enumeration is a simple program-defined data type with a limited set of possible values. Enumerations represent information that is “conceptual” in nature (as opposed to information that is textual, numeric, or complex).
For example, a coin has two sides that are commonly referred to as HEADS and TAILS. Rather than creating two constant strings with the values “Heads” and “Tails” and a String variable called FaceShowing, you can use an enumeration.
There are two parts to enumerations:
a. The name of the enumeration, which is the name of the new data type; this is sometimes referred to as the “enumerated data type”.
b. A set of enumerated values, which represent all of the possible values for a variable of that enumerated type. These values act like “constants” that can be used to distinguish different “states” for the conceptual data.
List the benefits of using enumerations
Type Safety - Enumerations allow a program to be “type safe”, meaning that there is less likelihood of creating logical errors or other mistakes through the use of constants or literal values.
Code Readability - Enumerations make code more readable than constants or literal values (like integers).
Compatibility with Switch Statements - Enumerations are compatible with switch statements, making them a great option for describing distinct values for matching against different cases. Because enumerations are like constants, and are treated as integral data types by the compiler, they are often the best choice when working with case structures.
Useful as Flags - Because the programmer can associate specific integer values to the enumerated values, it is possible to use an enumerated data type to create complex “flags” for representing distinct “states” that can be combined together.
For example, if you had an enumerated type such as the following, you could combine two states together in a variable’s value to represent distinct but compatible states, such as ACTIVE and MEDIUM_PRIORITY.
1 enum Status
2 {
3     INACTIVE = 0
4     ACTIVE = 1
5     LOW_PRIORITY = 2
6     MEDIUM_PRIORITY = 4
7     HIGH_PRIORITY = 8
8 }
Describe where and when enumerations are used
Enumerations are used wherever a clearly defined set of values can be “classified” and used to represent conceptual information.
Enumerations should be used whenever you might be inclined to use a set of two or more constants to represent distinct “states” or values for comparing against a variable.

For example, if you want to represent the two sides of a coin, it is better to use an enumeration for the coin’s HEADS and TAILS sides, rather than declaring some String or integer constants. The problem with using strings or simple integers to represent possible coin faces is that any variable that is defined as a string or integer can have values that won’t match either of the declared constants, as in this example:

1 const string Heads = "Heads";
2 const string Tails = "Tails";
3 // There is nothing preventing "invalid" values for the following coin face...
4 string theFaceShowingOnTheCoin = "Sailboat";

An enumerated type called CoinFace with the values HEADS and TAILS is better, because any variable declared of type CoinFace can only have the values defined in the enumeration.

```csharp
// The only other possible value that could be assigned is
// CoinFace.TAILS
CoinFace theFaceShowingOnTheCoin = CoinFace.HEADS;
``

Compare and contrast enumerations and classes
Enumerations and classes both define new data types that can be used by our program to represent custom data. However, while classes are useful in describing complex data types (that is, data types with assorted fields and that can perform various tasks), enumerations are only used to create new data types that are simple in nature. Enumerations only define a set of possible values, and each variable defined by an enumeration can only hold one of those possible values at any given time; there is no inner complexity to enumerations, as there is with classes.
Use enumerations to define simple data types that are conceptual in nature and that have a limited set of possible “values”
Demonstrate your ability to meet this learning outcome guide by completing the related assignments.

OOP Basics

Describe the idea of Composition
Composition refers to the situation where one or more of the fields in a class are objects. All classes are capable of having objects as fields, rather than just using the simple primitive types that come with the language.
For example, if a class called Address represents some mailing address, another class, such as Student, Company, School, or Business, could have a field whose data type is Address.
List the benefits of Composition
Composition is an aspect of modern programming languages that makes it possible to create new data types (classes) of ever increasing complexity.
Composition also makes it possible to get better code re-use, because classes can be more distinct, rather than overlapping. For example, both Students and Employees can have Addresses, so it is not necessary to code individual fields in the Student and Employee class for each part of an address; rather, a common type (called Address) can be shared by both classes.
 1 public class Employee {
 2     // ... other fields, followed by these Address fields:
 3     public string street { get; set; }
 4     public string city { get; set; }
 5     public string province { get; set; }
 6     // ... etc.
 7 }
 8 
 9 public class Student {
10     // ... other fields, followed by these Address fields:
11     public string street { get; set; }
12     public string city { get; set; }
13     public string province { get; set; }
14     // ... etc.
15 }

These could be coded like this:

1 public class Employee {
2     // ... other fields, followed by these Address fields:
3     public Address mailingAddress { get; set; }
4 }
5 
6 class Student {
7     // ... other fields, followed by these Address fields:
8     public Address homeAddress { get; set; }
9 }

: advanced benefit - Composition promotes the “Has-A” approach to designing objects rather than the “Is-A” design approach that makes use of inheritance. This “Has-A” approach gives programmers more flexibility in their coding and promotes the use of Design Patterns.

Topic J - Looping Structures

General Programming Concepts and Terms

Identify the C# statements that correspond to Do-While and Do-Until logical structures
TBA
Translate Do-While structures into code
TBA
Translate Do-Until structures into code
TBA
Identify and distinguish the parts of the for statement in code
TBA
Describe the common situations in which the for statement is used
TBA
Demonstrate how the various looping statements can be interchanged with slight alterations of the logical structures to maintain the overall logic of a given routine.
TBA

Topic K - Looping and Collections

OOP Basics

Define the term Generics as used in C# and give an example
TBA

General Programming Concepts and Terms

Describe what is meant by a “collection” class and give an example
TBA
List and describe the common methods of collection classes such as the List<T>
TBA
Identify the parts of the foreach statement
TBA
Describe the common situations in which the foreach statement is typically used
TBA
Identify the major benefit of using Generics
Type Safety –
List the major benefits of using collections instead of arrays
Collections such as List<T> can grow in capacity whenever items are added
Collections such as List<T> do not need special management of the boundaries (such as the index of the upper limit of an array)
Collections provide simple methods for quick adding and removing of “elements”

Topic L - Arrays - Not Sorted

General Programming Concepts and Terms

Describe what makes an array different from other collections in C#
The programmer is responsible to manage the boundaries of the array when manipulating the array’s contents.
Arrays do not automatically “re-size” when “adding” or “removing” elements; the size of the array is fixed at the time the array is created.
Describe the situations in which arrays are preferable over the use of collections
Arrays are preferred whenever multi-dimensional data is required (such as 2D, 3D, or n-dimensional data is needed)
Arrays are sometimes preferred whenever the size (number of elements) is unlikely to change and/or whenever the array is based on a primitive data type or an enumeration.

Notes

Thinking In OOP

What is a Computer Program

1The rule that “once a variable’s data type has been declared, its data type cannot be changed” is true for those programming languages which are described as type-safe, such as C#, Java and VB.Net. Other modern languages, such as JavaScript, do not have this rule.