You are on page 1of 27

Introduction

Introduction
Hi, this is Jesse Liberty from Pluralsight, and welcome to C# From Scratch. This
course is about everything you need to know about C#, but we make no assumption
s that you're already a programmer. I will teach you everything you need to know
from the very beginning. If you do have experience in other programming languag
es, you can easily use our controls to skip ahead to the parts that are of inter
est to you. One question that may immediately be on your mind is what software a
nd hardware do you need? As for hardware, you need a PC, needs to be running a v
ersion of Windows, and as for software, you will need some version of Visual Stu
dio. You can download a free version of Visual Studio, and we'll look at how to
do that in just a moment, at this URL. This course is very much about learning t
hrough programming rather than theory. We're going to spend a lot of time in Vis
ual Studio examining code, looking at code, and learning how to code by coding.
We will also spend time on object-oriented programming in great detail, and that
will mean talking about classes and objects, as well as other aspects of object
-oriented programming. Object-oriented programming is a technique that allows yo
u to map your program to the problem domain. The problem domain is whatever it i
s you're trying to solve. With object-oriented programming, you can create objec
ts that represent customers or bank accounts or any other thing in the problem d
omain, and that approach greatly reduces cognitive load, makes it much easier to
understand your program and understand what you're building with your program.
All of this will make a lot more sense as we begin coding. But before we can do
that, we need to take a look at how to get a copy of Visual Studio. So, let's go
to that URL, just open up a browser, and in the URL enter librt.me/VizStudioEx
for Visual Studio Express, and hit Enter. That will take you to the Visual Studi
o editions page. If it is possible for you to purchase an edition of Visual Stud
io, that's great. You get more with the commercial versions, of course, but you
can download a free version by clicking on Download and then clicking on Visual
Studio Express 2012. The version you're going to want for this course is Visual
Studio Express 2012 for Windows Desktop. You'll see that you can download that i
n two ways. One is a direct over the internet install, and the other is to downl
oad an ISO file to your computer. Do whichever is more convenient for you until
Visual Studio is running on your computer. Once you have that up and running, yo
u're ready to get started with coding in C#.
Fundamentals
Introduction
In this section, we will discuss the fundamentals necessary for C# programming.
Before we can begin to look at the aspects of C# programming, we need to underst
and how we're going to write C#, and for that we need a quick tour of the develo
pment environment, that is Visual Studio. By now, you should've installed Visual
Studio, so let's take a look at building your very first C# application.
Hello World
Let me reiterate that for this course you can use any version of Visual Studio i
ncluding the free Express 2012 for Windows Desktop. You can also use versions 20
10. I have here Express 2012 for Windows Desktop, and I'm going to click on New
Project. When it comes up, there are a number of things to see in the new projec
t dialog. The first is the Template section on the left. We will want Visual C#,
and we will choose Windows. On the right side that brings up a number of possib
le applications, and for now we will choose Console Application. Console applica
tions are the simplest possible applications, they're text only. Down here in Lo
cation, you can use the project subdirectory or you can create a subdirectory of
f of that for your own programs or place them wherever is appropriate on your di
sk. Let's call this first application CSharpFromScratchHelloWorld. It is a tradi
tion in programming that your first application is one that spits out the phrase
hello world, and who am I to fight with tradition. We can leave the rest of the
defaults as they are and click OK. Visual Studio will take a couple seconds to
settle down, and you will find yourself in the editor for your C# program. There
are many things to discuss here, and we will be coming back to many of them inc
luding these using statements on the top, what namespaces are, what classes are,

and so forth. But for now, inside your main function, between the curly braces,
you can simply type Console.WriteLine, which is how you write a line of text ou
t, and you put in parentheses whatever it is you want to write in quotes, Hello
World! End quote, end parentheses, and a semicolon to end the statement. Let's t
ake a quick look around. We have many menu choices. We also have a Save button,
folder buttons, and a Start button. Notice the drop down next to it says we're i
n Debug mode, which is what we want to be, and so let's go ahead and click on St
art. The application comes up and closes. That's not terribly useful to us, so l
et's hit Control+F5, which will tell it to keep the application up until we pres
s a key. That brings up the command window, and sure enough we see Hello World!
and Press any key to continue. We can go ahead and press a key, and we have now
written our first C# program. I don't expect that you will understand every bit
of this, but it does give a sense of how easy it is to at least write a little b
it of text out to the console. We'll be taking everything step-by-step as we bui
ld increasingly complicated and interesting programs.
Building Blocks Introduction
Here's the good and bad news. You are right now at the hardest part of learning
C# because it feels like you have to know everything before you can know anythin
g. In order to overcome that, you simply have to become comfortable with partial
knowledge as we work our way through all the many new concepts that C# introduc
es. I have great faith that you will be fearless in this endeavor. Let's get sta
rted by looking at the building blocks of a C# application. C# applications cons
ist of numbers, strings, which are just a series of characters, variables, and w
e'll discuss what variables do and how they work, operators, and you're familiar
with many operators already such as plus and minus and equals, expressions, whi
ch is any set of C# that evaluates to a value, statements, the basic building bl
ocks of applications. We'll talk just a little bit about whitespace, which is th
e space between words or expressions or operators in C#. And, over much of this
course, we'll be talking about objects as objects are the core, center, heart, a
nd soul of C#.
Building Blocks
Here's how we're going to go about learning how to use the building blocks in C#
. Rather than talking about numbers and strings in the abstract, we'll build som
e very simple applications and see how these are put to use. Once again, we clic
k on New Project, we choose in the Template section Visual C# Windows, and then
over in the list of templates, Console Application. Choose your location, and le
t's call this BuildingBlocks. This puts us into a new program as we saw in the H
ello World example. Let's take a little closer look at some of what's in here. F
irst are a number of using statements. Using statements bring in to your program
pre-created code that your program can use. Visual Studio has put into your pro
gram a number of using statements that simplify your coding that you may or may
not need. As we go along, we'll add additional using statements and delete the u
sing statements we don't need. Next comes a namespace. A namespace is a way to s
ay that everything I declare, everything I name within this namespace, is separa
te from anything named in a different namespace. By having multiple namespaces,
you can avoid having collisions in names. Now what does that mean? Well, for exa
mple, you might create a variable. We'll talk about a variable in a moment. But
you might create a variable named my variable. Well, it may turn out that Micros
oft has in one of its libraries a variable named my variable. Those names will n
ot collide as long as they're in separate namespaces. In the console application
, we have a single class called Program. Classes are a way of creating new types
. We're going to talk types and classes a great deal. For now, we can ignore thi
s code. Within this class we have a function called Main. Functions are essentia
lly subroutines, small programs that you can call by name and have them execute
code. Once again, we're going to ignore the structure of all of this and accept
that within this function we can put code that when we run the application that
code will run. We already saw this with Hello World, which, by the way, was a go
od introduction to the idea of strings. A string is a series of characters betwe
en double quotes. Here's a string Hello World. Notice the red squiggly line unde
r Hello World. That's the compiler telling you that you don't have a legal C# st

atement. You can't just write a string and leave it out there unattached to anyt
hing else. I can, however, create a string variable. A variable is essentially a
holder for some kind of object. In this case, we're going to create a string va
riable. Variables can be identified by their type or by using the keyword var. I
f I write var myString = Hello World and then go to my end of my statement and e
nd it with a semicolon because all statements must end with a semicolon, then th
e red squiggly line goes away because I now have a legal statement. Notice the g
reen squiggly line. That indicates that I've created a variable that I've not us
ed anywhere, and that's fine. The var keyword does not say, oh this can be any t
ype. It says compiler, please figure out the type. And the net effect is exactly
the same as if I had written string myString. So, I can explicitly identify the
type or, under many conditions, I can let the compiler identify the type by usi
ng the var keyword. Notice what happens if I hover over the var keyword. It says
that it's a string. So, the editor has also figured out that myString is really
of type string. C# is what is called a strongly typed language. Items have a ty
pe, and the compiler helps enforce using the correct type. This can cut down on
bugs and make programming much, much easier. We can see the effect that string c
an have by outputting it using Console.WriteLine. What we'll put into Console.Wr
iteLine is myString. Notice that we can use the variable as a substitution for t
he string itself. And, once again, this will work as we saw in the previous exam
ple. If I hit Control+F5, Hello World comes up. Variables, of course, can be of
other types. One type it can be is a number type. Now, in C#, there are numerous
types of number types. That is to say that you might declare a number to be an
integer by saying int myFirstValue =, and now we to assign an integer, so we'll
assign 23. There are other numeric types. The most common other numeric type is
a double. Doubles are used when you have fractional values. So, for example, 45.
79 would be a good use of a double. We can add those two numbers and put the ans
wer into another double. When you add an integer and a double, the integer is qu
ietly and implicitly converted to be a double, so 23 becomes effectively 23.0. L
et's add our int and our double and assign the result to a third double called s
um. Notice that we use the plus sign, that's an operator, and we add myFirstValu
e and mySecondValue and assign the sum of those two to a variable I've named sum
. We can now call Console.WriteLine and pass its sum. Console.WriteLine expects
a string. We're passing in a double, but WriteLine will be smart enough to call
a function on that double ToString and treat it as a string. We can also explici
tly call ToString on it to make clear our intent that we want a string here that
we're passing to WriteLine. Let's go ahead and run this with Control+F5. And no
tice we see Hello World and then we see the sum of the two values, 68.79. I prom
ised to talk a little bit about whitespace. Whitespace is any space or tab or ne
w line. Notice that there is whitespace between the keyword var and the keyword
myString. The compiler does not care how much whitespace you put in there. You c
an put one space, two spaces, three, add a tab, and as far as the compiler is co
ncerned, it's all the same. There are some limits. You must have at least one sp
ace between the keyword var and myString. Otherwise, the compiler can't tell wha
t that is. Is that a new variable? Is that a declaration? No way to tell. So, yo
u must have at least one space there in order for that to be legitimate. Also, s
paces within strings do matter. If I put a number of spaces in this Hello World,
then when I display it, those spaces are going to display. So, spaces within st
rings matter. Most space outside of strings doesn't matter. And, for example, I
could even add new lines as whitespace and spread this out across three lines, a
nd that's just fine as far as the compiler is concerned. We can run that and tha
t'll work just as it did before. Control+Z is our friend in getting this back to
the way it was.
Summary
In this module, we began to look at the core fundamentals of programming in C#.
We took a look a couple of number types and at strings, we saw our first variabl
es and operators, and we looked at expressions, which is any set of C# that retu
rns a value, and statements, a complete instruction that ends in a semicolon.
Truth
Introduction

A good place to start a discussion of C# programming, and most anything else for
that matter, is with a discussion of the nature of truth. In C#, true and false
are represented as Boolean values. Boolean values can have only one of two valu
es, true or false. There are operations that you can perform on Boolean values s
uch as and, is statement one true and statement two true, or, which would be tru
e if statement one is true or statement two is true, and not, which reverses the
truth of a given statement.
Booleans
We can explore Boolean values by creating a new application in Visual C# where w
e can declare variables of type bool. Each time we declare a variable, we give i
t the type or the keyword var, followed by the name of the variable, and we assi
gn to that variable a value. Since this is a Boolean value, the expression that
we assign to it must evaluate to true or false. In this case, we're testing the
equality of 3 + 2 with the value 5. Notice that the assignment is a single equal
sign, but the test for equality is a double equal sign, equal, equal. So, we sa
y 3 + 2 == 5, which will evaluate true, and we can display that using WriteLine.
We simply put our Boolean value in, and let's run the application, and it says
True. So, the value of my first Boolean is true, which makes sense. Let's create
a second Boolean value. This one states that 3 + 2 is greater than 5, manifestl
y false, and we can prove that by printing it out, or more accurately, displayin
g it to the console. And now we get True and False. This will allow us to play w
ith some of the Boolean operators. Here we are using the double ampersand, which
is the and value, and the and value only returns true if both expressions are t
rue. We're assigning the result to the Boolean both are true. But in this case,
the Boolean both are true will return false because the second expression, mySec
ondBoolean is false, and as I said, the double ampersand only returns true if th
ey're both true. Here in the WriteLine, I've added a string bothAreTrue evaluate
s and then the bothAreTrue Boolean. I'm not going to bother adding ToString beca
use WriteLine will do that for me. And when I hit Control+F5, I see True and Fal
se for the first two values, and then bothAreTrue evaluates False as we expect.
In this next example, we set oneIsTrue equal to myFirstBoolean or mySecondBoolea
n. Or will evaluate if either expression is true. I've modified WriteLine to use
a substitution argument. Substitution arguments are placed in curly braces and
numbered sequentially from 0, 0, 1, 2, 3. The way this works is we put the subst
itution parameter right in line inside the double-quoted string, followed with a
comma, and whatever is going to be substituted into the first argument comes fi
rst, and if there were a second argument, it would be comma and the second argum
ent. So, what's going to happen is this value oneIsTrue will substitute for this
substitution argument and we'll end up with oneIsTrue evaluates whatever the va
lue of oneIsTrue is because one expression is true, and we expect that to say tr
ue because we're using an or here. OneIsTrue evaluates True because one expressi
on is true. So, the difference between an and or is and requires both sides to b
e true, or requires either side to be true. It's important to know that both of
these arguments short-circuit, and that means they evaluate the first argument,
and if that's enough to satisfy, they don't bother with the second. For example,
and requires that both sides be true. If the first argument is false, it never
bothers to evaluate the second because they must both be true. Similarly, or req
uires that either side be true. So, when it hits myFirstBoolean, which is true,
it doesn't bother with evaluating mySecondBoolean because as long as one is true
, the expression is true. That short-circuiting can come in very handy. The thir
d operator that's of interest is the not operator. Here we have set a new Boolea
n, reverseMyFirstBoolean equal to not myFirstBoolean, that is bang or exclamatio
n mark for not myFirstBoolean. In the console WriteLine, we're going to use two
substitution parameters. MyFirstBoolean is substitution parameter one, which is
actually numbered 0, but reverseMyFirstBoolean is substitution parameter and the
second one, which is numbered 1. Remember we count from 0, and we count from 0
throughout C#. We then put in the arguments myFirstBoolean and reverseMyFirstBoo
lean. Let's look at the results by running the program. MyFirstBoolean is True b
ut reverseMyFirstBoolean is False. In the next section, we'll see how these Bool
ean values are put to use.

Summary
In this module, we looked at Boolean values, which can have only the values true
or false, we looked at the and operator, which evaluates true if both expressio
ns are true, we looked at the or operator, which evaluates true if either expres
sion is true, and we looked at the not operator, which reverses the truth of a B
oolean.
Program flow
Introduction
Before we turn to object-oriented programming, we need to spend a little time ta
lking about program flow. Programs work from top to bottom. The compiler works i
ts way through your code from the first line to the last, but if that were all i
t did, programs would be overly simple and not capable of the kind of complexity
required by today's modern applications. To solve that simple problem, you can
have the logic of your program divert based on conditions, and to test those con
ditions, you have a number of different statements starting with if. If some con
dition is true, take this action. If else. If some condition is true, take actio
n A, else take action B. If, else, else if. That allows you to put together cons
tructs such as if condition A, take this action, else if condition B, take this
action, else take some third action. Another construct for controlling the flow
of your program is a while loop. While some condition is true, take these action
s. And a do while loop, which ensures that the action is taken at least once. A
for loop allows you to count or iterate over a collection or to do something a g
iven number of times. And we'll look at for loops very closely. We'll also look
at the break statement, which breaks you out of other loops. And finally, we'll
look at the switch statement, which can greatly simplify your if, else if, and e
lse statements.
If Statements
The best way to explore conditionals is with a new application. Let's create an
application called conditionals, and in the main program we're going to want to
ask the user for their age. We've seen Console.WriteLine. Here we will use Conso
le.Write, which does not put a new line at the end of its output. In order to re
trieve information, we will use Console.ReadLine, which reads a line of text fro
m the console. We need to do something to that text, so we'll assign it to a str
ing variable. We really want that age as an integer, and so we will convert the
string to an integer by calling parse on the integer itself. Notice we're callin
g parse on the integer class, not on age itself. And we pass in ageAsString, and
what we get back is age as an integer. We now have an integer. A perfectly legi
timate if statement is to test that integer for a given value. We'll test to see
if the age is over 21. The way if statements work is you say if and then you pu
t your conditional inside parentheses. The next line will be executed if, in fac
t, the conditional is true. This is perfectly correct code, but not the way I ad
vise doing it. You can create a block using braces, and that block will consist
of one or more statements, all of which will be treated as a single statement. S
o, if you wanted more than one statement in your if statement, then you would pu
t it inside the braces. I strongly recommend using the braces even when you have
only a single line. The logic of this program right now says what is your age,
you enter your age, and if the age is greater than 21, it displays "You are an a
dult." Let's run that. It says what is your age? I'll lie and say 35, and it say
s you are an adult. Let's run it one more time to make sure that it's really wor
king. We'll put in an age of 17, and it doesn't say anything. It would be nice i
f it said you are not yet an adult. That's what else statements are for. Else st
atements say if the condition is false, then take this action. And, once again,
I'm going to put that inside braces. Now, if we run the program and we enter a v
alue that's less than 21, it says you are not yet a legal adult. What if we want
to handle senior citizens? We can do that by changing our if statement and addi
ng an else if statement. So, let's change our if statement to if age greater tha
n 65, it will say "You are a senior citizen." Now, we want to handle what happen
s if they're over 21, but not over 65. In that case, we can say else if age grea
ter than 21, and we can write "You are an adult." And finally, we want to handle
all other cases, which will be the cases for under 21 or not over 21 in which c

ase we'll say else "You are not yet a legal adult." Let's try this out. What is
your legal age? 72. You are a senior citizen. Let's run it again. What is your l
egal age? 22. You are an adult. And let's run it again. What is your legal age?
16. You are not yet a legal adult. And so our logic is working; however, there i
s a subtle bug in this program. We have written if age is greater than 21 you ar
e an adult. What if your age is 21. Well, if we run this and we put in 21, it sa
ys you are not yet a legal adult, and that's incorrect. So, what we really want
to say here, if your age is greater than or equal to 21, you are an adult. We al
so could have made it greater than 20. Now, when I run it and I say my age is 21
, it says I'm an adult. So, that's if, else if, and else.
While Loops
While loops allow you to do some work while a condition is true. That condition
can be any Boolean value. Let's take a simple example. Here we begin by asking t
he user how old are you, we call Console.ReadLine, and we pass that as a paramet
er to the parse function of int, and assign the result to age. This is just what
we did in the previous program, but we've eliminated the temporary intermediate
variable ageAsString by combining the parse and the ReadLine. This is very comm
on in C#. C# programmers hate extra typing. There are times that you will want t
o use interim variables because they're easier for debugging, and other times yo
u'll want a sparser style of coding. In any case, once we have the age, that bec
omes the condition for our while loop, while age is greater than 0. What we'll d
o in our while loop is execute two statements. First, we will write happy birthd
ay, and secondly, we will decrement age. Notice the two minus signs after age. T
hat means reduce by one. There are a number of ways we could have written that.
For example, you can instead write age = age - 1 or you can even write age -= 1
or you can use the decrement operator. All three of these mean the same thing. L
et's run this program. It asks how old you are. Let's put in 12. And sure enough
, it's going to print out 12 happy birthdays. Let me try that again with control
+F5 so that we can see it, and there's our 12 happy birthdays with a space betwe
en each. The while loop will continue iterating as long as age is greater than 0
. If we pass in 12, 12 is greater than 0, we print happy birthday, we decrement
the age, it's now 11, which is greater than 0, we print happy birthday and it be
comes 10, and we continue that until age is 1, we print happy birthday, we decre
ment age to 0. At that point, the while test fails, age is no longer greater tha
n 0, it's equal to 0, and we fall through the bottom of the while loop, and any
statements after the while loop would then be executed. For example, we could ad
d this line of code where we have a WriteLine that calls out TaDa!! However, bef
ore TaDa, it has backslash N. The backslash is an escape character and it means
what follows is not a literal character, but a special character. In this case,
the new line character. So backslash N means enter a new line and then print TaD
a. Let's run the program and see the effect. Control+F5, How old are you? This t
ime we'll just put in 5. Five happy birthdays. And then on a new line the TaDa!!
There is one real limitation to this program, which is if I enter the age as 0,
age will not ever be greater than 0, and we will never print happy birthday. If
you want to ensure that happy birthday is printed at least once, you can use a
do while loop. The way you do that is you take the condition while and you move
it to the end of the block, and you put the keyword do at the top. And that esse
ntially says do this work while age is greater than 0. Because it's going to do
the work before it does the test, it's guaranteed to run at least once. So, if w
e hit control+F5 and enter 0, it prints one happy birthday. And the logic behind
that is it hits the do, it does the console.Write and the age decrement, and th
en it tests while age is greater than 0, which, of course, it is no longer, neve
r was, and so the do while loop ends. The key difference between a do while loop
and a while loop is a do while loop is guaranteed to run at least once. They're
otherwise identical.
For Loops
Let's take a look at for loops, which are one of the more powerful ways to loop
through values. You'll remember our while loop looked like this. We asked the us
er to enter an age, and while the age was greater than some value, in this case
0, we did some work, and then we decremented the age. It's very common to have t

his three part pattern. Set up a value, in this case age, test the value, in thi
s case while age is greater than 0, do some work, and then decrement the age or
increment the age or in some way change it so that the while loop will end. You
can combine all three of those steps into the header of a for loop. The first ar
gument to the for loop is your setup. Here we're describing an integer named age
and we're initializing it to 5. The second argument, which comes after a semico
lon is the test, while age is greater than 0, also a semicolon, and then the cha
nge, age decrement. Inside the body of the for loop is the work you're going to
do. The logic of the for loop is initialize once, test, run the body, do the cha
nge, test, if the test is true, run the body, do the change, and repeat until th
e test if false, and then fall out of the for loop. And so if we run this, we sh
ould get five happy birthdays followed by a TaDa, which we do. A more common loo
k to a for loop is to use a counter variable. And for historic reasons, that's o
ften just the letter I. The reasoning behind this is interesting. It turns out t
hat this goes all the way back to Fortran, and early scientific programming lang
uage in which the letters I, J, K, and L were the only legal counter variables.
In any case, it's common to initialize a variable such as I equal to 5, set some
condition such as I is less than 10, and you'll find that most initializations
are to 0, although that's not at all required, it's just very common, and then,
of course, you're going to want to increment the age variable. By the way, there
are two ways to increment the age variable using the increment operator. One is
++ after the term, and the other is ++ before the term. And they actually are d
ifferent. We'll take a look at that difference in just a moment. In any case, th
is is a more common looking for loop, for int equal I, I is less than some value
, increment I, and then we're going to run through the loop this many times. If
you set it to 0 and say less than 10, it will run 10 times because remember the
first one is a type 0. And we can run that. And we, in fact, get 10 happy birthd
ays. The for loop will come in very handy very often, and is probably the most c
ommon loop to use. Let's take one moment and examine that issue of increment bef
ore the I and after the I. The first thing I'm going to do is comment out these
lines of code because we don't want our for loop to run. There are two ways to c
omment out lines of code. One is on a per line basis using the double slash. If
I mark double slash, everything from the double slash to the end of the line is
a comment, and notice that it turned green because Visual Studio marks comments
in green. The other is to use slash star at the beginning of your comment and th
en to use star slash at the end of your comment, and that comments everything be
tween them. The nice thing about having two ways to be able to comment is that y
ou can nest your comments. That is to say, I could start out here and put a comm
ent with a double slash that says a for loop for counting happy birthday. Not a
terribly useful comment, but a comment nonetheless. I can then nest that comment
inside a star comment, slash star to begin, star slash to end, and this comment
is preserved within this entire commented out block. Then later, when I uncomme
nt this block, that comment is preserved. A shortcut to commenting a number of l
ines is to highlight them, let's get rid of this line, highlight the lines you w
ant to comment, and then in Visual Studio on your menu you should see a comment
out the selected lines button, and when you click that, it uses the line comment
for all of the highlighted lines. By the way, there's a corresponding uncomment
to undo that comment, and that can save a great deal of time. Returning to the
issue at hand. The difference between the prefix increment and the postfix incre
ment, that is the one that comes after the variable, can be a little bit subtle.
Let's look first at the prefix. We initialize a variable age to 35. We then set
newAge to increment age, whatever ++age is going to be. Well, ++age is going to
increment age and then assign it to newAge. So, when we type this out, age will
have been incremented to 36, and newAge will be 36 because the increment happen
ed before the assignment. And sure enough, they're both 36. If, however, we are
to reverse those, and here we assign age and then increment it because we're usi
ng the postfix operator, age will start at 36 and that's what will be assigned t
o newAge, and then age will be incremented to 37. And so when we run it, age is
37, but newAge is still 36. So, the net effect is that the prefix increment oper
ator says increment and then assign, whereas the postfix operator says assign an

d then increment. In the case of our for loop, it doesn't matter which we use be
cause there is no assignment, we're just incrementing the value. It is common, a
lthough not required, to use the prefix operator in that case.
For Loops Part 2
It turns out that with for loops, each of the arguments in the header to the for
loop is optional. So, you could, for example, do your initialization outside of
the header. Here we initialize I to 0 outside the header, and notice we leave t
he initial semicolon in place as a place marker, and now we test I is less than
10, and then we increment I. Similarly, if we wanted to, we could remove the inc
rement of I and move that down into the body of the for loop, and now we have so
mething that is very much like a while loop. We can even remove the test, and no
w we have what is called a forever loop. This loop will run without end. It is p
ossible, however, to put in an ending condition. Here we've put an if statement
into the body of the for loop. If I is greater than 10, and we add the keyword b
reak, break will break out of the loop. This will work exactly the way our earli
er for loop worked, will initialize to I, each time through we will increment, a
nd we will test if I is greater than 10 we'll break out of the loop. And so we s
hould get 10 happy birthdays. And sure enough, we do plus a little bit of extra
material from our earlier exploration. Let's comment that out. Why you would wan
t to do this is, of course, not obvious at the moment, but there are times that
the initialization needs to happen interactively, and you might want to leave th
at out, and there are times that you might want to interrupt a for loop or a whi
le loop or do while loop with the break statement under unusual conditions where
you want to break out of the loop without completing it. Not only can you break
out of loops, but you can also cause loops to restart based on certain conditio
ns. Here, and again this is very artificial, we're going to test I to see if it'
s equal to 5, and if it is, we're going to hit the keyword continue, which says
start the loop over, don't break out, but start over. Now, if we leave it the wa
y it is, when we hit 5 we'll hit an infinite loop because it'll never not be 5,
so let's be careful about that and move the increment. This way, the increment h
appens before the test. When the increment increments I to 5 we hit continue, we
loop through an increment of 6, and then we fall through that if statement and
continue on. In order to make sure that this is working, let's put a little bit
of information into our happy birthday statement so that we can see what I is at
each iteration. And let's run that. Happy Birthday! 1, 2, 3, 4, 6. It did succe
ssfully skip over 5. Finally, let's say we were counting a very large number. Le
t's return our for loop to something more normal for a for loop. We'll comment o
ut what we have in our for loop to preserve that for when you examine this file,
and let's create a common, but larger for loop. This for loop will iterate 2000
times. I don't want to write happy birthday 2000 times. What I want to do is it
erate 2000 times, do some work during those 2000 iterations, and then every 100
times I want to print happy birthday. The way I say every 100 is I say if I modu
lus 100 equals 0, and we're going to talk about that in just a moment, then I ca
n print happy birthday. The modulus operator is like division that you learned i
n fourth grade. When you modulus a number, you divide it, and what you get is th
e remainder. So, if I were to say 2 modulus 9, I would divide 9 by 2 and get 4 w
ith a remainder of 1. Modulus returns the 1. If modulus returns 0, then it's an
even division. Two modulus 8 is 4 with a remainder of 0. I modulus 100 means eve
ry time I is a multiple of 100, it will have 0 remainder and will be able to dis
play this message. Let's run this. And what we see is Happy Birthday! 0Happy Bir
thday! 100Happy Birthday 200, 300, 400, all the way up through 1700, 1800, and 1
900. The modulus operator is used quite a bit in for loops to keep the user info
rmed of updates or to otherwise do something periodically.
Switch Statements
Earlier we looked at if, else, and else if. A greatly simplifying statement when
you need to pick among various values is the switch statement. Here we'll ask t
he user to pick a number between 1 and 5, and once we have that number, which we
've stored in the integer choice, we can say switch choice, and we can switch on
the various possible values between 1 and 5. For example, if they pick 5, we sa
y case 5, follow that by a colon, and then whatever work we want to do. In this

case, we'll simply display the line, "You picked the biggest legal value." That'
s followed by a break and then the next case. In addition to handling all of the
legal entries, I would like to have a default that will be called in case there
's a problem with the user's entry. And, in fact, a perfectly legal statement in
a switch statement is default, which means call if none of the above cases fit.
And here we're going to display "Not a legal entry. Please try again." If we ru
n this application and we enter the number 3, the case statement for 3 is what i
s called, and it displays you chose 3. If we run it again and we enter the numbe
r 9, none of the case statements match, the default is called. There are times t
hat you may want to allow two values to do the same work. For example, I choose
"Pick a number between 1 and 6:" and I want the case for 5 and 6 to be the same.
In that case, I can put case 6: case 5:, and case 6 will just fall right throug
h to case 5. The key is that case 6 cannot do any work on its own and then fall
through. It must be completely empty. And this will work as we can see by enteri
ng the value 6, and it says you picked biggest legal value, which is falling thr
ough to 5 and printing that value.
Enumerations
When using switch statements, and throughout your use of C#, you may find enumer
ated constants to be extremely helpful. An enumerated constant is just a constan
t term, looks like a string that stands for a value. The way you create an enume
rated constant is with the keyword enum. Let's created the enumerated constant s
et color. I place the keyword enum followed by the name of my enumeration, color
, and then braces. Inside the braces, I separate each of the colors or each of t
he enumerations by commas. Once I have my enumeration in place, it is very easy
for me to use that enumeration. For example, in the body of my program, I can de
clare a variable of type color, call it anything I like, let's say favorite, and
assign to it anything from the color enumeration. And notice IntelliSense is pr
epared to help. It immediately goes to color, and when I hit the dot, I get a li
st of all of the enumerated values. I'll choose green and set that as my favorit
e. I can also use colors in my switch statement. So, I can switch on my favorite
color, and again, the enumeration will help me as I say case Color. and I can c
hoose Red: and then whatever work I want to for that, and I can go ahead and do
that for all of the colors. Once again, it's a good idea to put in a default, no
t required, but good programming practice, and you can see how the enumeration n
ot only simplifies my programming, but makes my switch statement more meaningful
and gives me a greater ability to write code that is readily recognizable and t
herefore easily maintained. If I haven't said it before, writing code is cheap,
maintaining code is expensive, and the clearer you can make your code, the easie
r it is to maintain, and the less expensive it is in the long run.
Summary
In this module, we looked at the fact that braces create a block, and with that,
scope. We also looked at the if statement and how we can test a conditional, an
d we looked at the variations on the if including the else statement and the els
e if statement. We looked at the while loop that allows you to loop through and
iterate over a series of statements while a condition is true, and the do while
loop, which guarantees that the body of your loop will run at least once. We loo
ked at the more powerful for loop that allows you to initialize, test, and chang
e a condition all in the header. And we looked at the break statement that break
s out of a loop, and the continue statement for continuing within a loop. We als
o looked at the switch statement, which simplifies the if else syntax, and we lo
oked at enumerations for creating enumerated values.
Objects
Introduction
Whatever the true nature of the universe proves to be, our perception of the wor
ld is that it is filled with objects, and objects have specific properties, as w
ell as behaviors. We've been hardwired through millions of years of evolution to
perceive the world as filled with objects, and when we bring those objects into
our programming and create representations of their properties and behavior, we
greatly reduce the cognitive load involved in solving complex problems. The beg
inning of object-oriented programming is understanding classes and objects. You'

ve already seen that C# has types for numbers and strings. Classes allow you to
define new types, complex types. These types have fields, which are data, they h
ave properties, and we will discuss properties in great detail. Properties appea
r to the creator of the class to be methods, and they appear to the user of the
class to be fields. Methods are the behavior of the class. We draw a sharp disti
nction between the class, which is a type, and the instance, which we call an ob
ject. It is the distinction between dog as a type and my dog Charlie as an indiv
idual instance. Constructors are special methods that create instances or object
s. And initialization is a special feature that allows you to set the properties
of an object at creation time. Let's look at each of these in greater depth.
Properties and Fields
Let's create a new program and take a look at the creation of classes and object
s. The first thing to know is that we don't want to create our class inside of t
he class program so we're going to create it outside, and we do that with the ke
yword class, and then we give the class a name. Let's create an employee class.
Now that class might be used in any number of programs to represent employees in
a company. There are many fields and properties that a typical employee might h
ave, but let's talk about fields and properties for a moment and get that distin
ction clear, and then talk about how we use properties in modern C#. A field is
just a member and it can be private or public. Private means that the field can
only be seen by methods of the class itself. Public means it can be seen by any
method of any class. And we'll take a look at what the difference is there. Let'
s start simple and give the employee a public field of type int, which will be t
he employee's age. And we won't give anything else to that employee for now. Dow
n in main, we can make an instance of employee or an object. Those are synonyms,
an instance or an object. And what we're going to do with that employee is give
that employee a name, much as you would with a variable. In order to instantiat
e a new employee, that is make an instance of a new employee, we use the new key
word and then the type we want to create and two parens. That creates Dave as an
instance of a new employee. Now, we can do things like we can set Dave's age, a
nd we could, if we like, retrieve Dave's age and display it. And this program, a
s you expect, will display Dave's age. Control F5 to run that. Dave's age is 25.
That all works just fine, but age is part of the internal state of the employee
, and one of the key concepts in object-oriented programming, encapsulation and
data hiding, indicate that we should not have this data be public. It should not
be available to the function main, which is not a function of the employee clas
s. Rather, it should be private to the class employee, and access to that should
be mediated through a property. The reason for that, among others, is that you
may change the way you hold or store the employee age. You may decide at a later
time to get that from a database or to compute that from the employee's birthda
te and the current date. So, the more common way, and preferred way, to handle t
his is to make age private. We can now give employee a method to get the age, an
d that would certainly work. We could say int MyAge. That makes a method, and in
that method, we could return age. And then, in order to get the age or set the
age, we would have to, instead of going directly to the field, we would have to
say Dave.MyAge. That would return the age so we could assign that to an integer.
And, of course, if we wanted to set it, we would need another method, which we
might call SetAge, and that would take an age to be passed in. So, we could say
down here Dave.SetAge, and we need to make that public because right now it's pr
ivate by default. And you can see this is becoming a bit of a mess. So, we could
say Dave.SetAge, pass in the age, and then get it back out by saying Dave.MyAge
and going ahead and using that variable to print out the age. All of this would
work. However, the client down here is calling SetAge and MyAge and calling met
hods, and methods should represent behavior, and MyAge isn't a behavior. And eve
n setting the age really isn't a behavior of the employee. What we'd like is som
ething that looks like a field to this client, but acts like a method to this em
ployee object, and that's where properties come in. With a property, what we can
do is come along and say public int Age, and it's common in C# to have the priv
ate backing variable be lowercase and the public variable be initial uppercase.
Remember C# is case sensitive, so those are different. Public int Age. And then

within the braces, we create a getter and a setter. And the getter will just ret
urn the private variable age, and the setter will just set the private variable
age to value. And what's value? Value is a hidden parameter that is passed into
set. Let's look at how that works. The way the client works with Dave now is whe
n he wants to set the age he says Dave.Age using the property, the capital A, =
35. Notice that to the client this looks like you're working with a field. You s
imply set the age equal to 35. That calls the setter automatically and the 35 is
passed in as the value automatically, and the backing variable age is then set.
We can then get the age by saying Dave.Age, and here, in a place where it's not
being set, where it's being retrieved, the getter is automatically called. So,
a lot of that work is done for you. And now you have a private member age, which
you can change later to be computed or whatever you want, and a public getter a
nd setter that the user can use as if they were accessing a field directly, and
this works just as well as the previous. But it gets even better. Because this i
s such a common idiom to have a backing variable called age and another public v
ariable called capital age and a getter that just returns it and a setter that j
ust sets it, rather than having to type that again and again as we're doing here
with the name field and property, rather than doing that and having many of the
se all using the same format, there's a shortcut, an incredibly convenient short
cut. What you can do for all of this for age is replace it with this: public int
Age { get; set; }, and that one line is a signal to the complier that will tran
slate back as if you had typed all of this above. It's exactly the same and work
s exactly the same. Behind the scenes, a backing variable is created, yet effect
ively calls the getter that returns that backing variable, and set effectively p
asses the value in to that backing variable. So, age becomes tremendously simpli
fied, and we can do the same thing with name. And so you see that properties bec
ome very, very convenient. At any time, you can expand one of these properties a
nd put more into the getter or more into the setter, but if you need just the st
andard get and set and want to use properties instead of fields, this new short
syntax is tremendously useful. And notice that I have not had to change the body
of my program inside main. We still use Dave.Age to set and get the value, and,
in fact, when we run it, it continues to run.
Constructors and Initialization
Here I've created the new program Classes2. That is the departure point from Cla
sses1, our previous program. We have an employee class that has two properties.
Let's give it a few more. As you can see, I've added a salary, a starting date,
and a phone number. When we instantiated our employee Dave, we did so with a new
keyword and employee and empty parentheses. There are three ways to get data in
to that instance of Dave. We've seen one already where we simply assign that dat
a. A second way is called initialization. With initialization, at the time we cr
eate the employee, we also initialize one or more of the properties. To do that,
let's delete the assignment and the semicolon after new employee and create bra
ces for the initialization. Within those braces, I can initialize any or all of
the properties. And notice that IntelliSense in Visual Studio tries to help by s
howing me a list of each of the properties. So, we'll set age equal to 35, comma
, and we'll set name equal to. Now, we've called this employee Dave. That's the
name of the object. That's not necessarily the name of the employee, but for con
venience, let's call this person David Smith. In addition to name, we can set th
e salary, and we'll set that to 50000.00 because that's a double and can take a
fraction or can take cents. The StartingDate is a DateTime, and to set that, we'
re going to need a new DateTime object. Now, notice IntelliSense has popped up a
nd it has said there are 12 different ways to set a new DateTime. And you can cl
ick on those arrows or use your down arrows to scroll through the different ways
to set a DateTime. The one we want is this one where you pass in a year, a mont
h, and a day. So, we'll say that Dave started in 2012 in July on the 10th. And t
hen we have phone number, which we'll set to a string as it's called for. And th
en after the closing brace, we put a semicolon. And that initializes all of the
fields for this particular object. We can now go ahead and extract some of this
information in a WriteLine statement. So, here we're using substitution paramete
rs. Dave's age is parameter first, he started on parameter 1, and makes paramete

r 2. Parameter first or parameter 0 is Dave.Age, the starting date is Dave.Start


ingDate, and the salary is Dave.Salary. Let's run that. And sure enough, it says
Dave's age is 35, he started on 7/10/2012 at 12:00:00 AM. And we can modify the
display to show the date in the format we want. This is the default format. And
makes 50000. And, once again, we might want to modify the 50000 to put a dollar
sign and a comma. But for now, we can see that the data has been placed inside
the object. The third way to create or to add data to a new object is with a spe
cial method called a constructor. Now, we've only alluded to methods, but method
s are simply functions that are members of the class. And most methods are very
normal in that they have a return type or void, they take 0 or more parameters,
and there's a body to the method. So, for example, we might give the employee cl
ass a method called bonus. So, let's look at this method that we've added to our
employee class called bonus. Bonus does not return a value, so we have it retur
n void, it takes one argument of type double called bonusPercent, and what it do
es is it does is it adds to the salary, Salary * bonusPercent. We can come down
to our running program that we've been building and give Dave a bonus by calling
Dave.Bonus and passing in 5 percent. Now, let's take a look at what we get when
we write out his age, starting data, and salary after the bonus. So, we'll hit
Control F5, and it says now that he makes 52500. He's had a five percent raise.
So, that's a standard method of the class, but we we're talking about constructo
rs. Constructors are special methods of the class, and they are used to construc
t an instance. What's interesting about constructors is that they don't have a r
eturn type at all, not even void, and they must have the name of the class itsel
f, in this case, Employee. They do typically take parameters, and what is very c
ommon is for them to have a parameter for each of the properties of the class. S
o, they might have an int for age and a string for name and so on for each of th
e various properties. Then within the body of the body of the constructor, you c
an assign these passed in parameters to the property. And so you can say Age = a
ge and Name = name and so forth. Now, you have a way of constructing the object
by passing parameters into the constructor at the time you create the object. No
tice that our employee with a paren and nothing in it now has a red squiggly lin
e. Any constructor that has no parameters is called a default constructor, and,
in fact, if you don't create a constructor, you are given a default constructor
by default. That default constructor, which takes no parameters that you get by
default, does nothing, and that's why we had to do the initialization. However,
now that I've created a constructor, I no longer get my free default constructor
. Fortunately, we can do something called method overloading where we have two m
ethods with the same name, but different parameters, either different types or a
different number of parameters. In this case, it will be a very different numbe
r of parameters. We'll say public employee and have no parameters, and we'll hav
e our default constructor do nothing, and that will continue to do as it did bef
ore, but it will allow us to do this initialization. We now have a constructor.
We can construct an employee by passing in values. So, let's create a new employ
ee, Mary = new Employee, and this time we're going to use our second constructor
. Notice IntelliSense says there are two constructors. And if I hit the down arr
ow, it will show me the constructor that takes the various parameters. And it's
very easy to fill them in because IntelliSense takes you through them on-by-one.
So, the first one is Mary's age. We'll make her 25. The next one is her name. W
e'll make it Mary Jones. Next is her salary, and let's give her a salary of 6000
0 dollars. Her start date, which will be a new DateTime of, and let's flip throu
gh the DateTimes to find the one we want, year, month, day. So, she started in 2
010 on February 29th. Hit the comma, and it says you still need the phone number
as a string. (Typing) Now, we have created an employee, not by initializing it,
by passing in values to the constructor, and yet, we can once again add a Conso
le.WriteLine. And now let's run the program, and we've got Mary's age is 25, she
started on February 28th. You may have noticed that I had originally put in Feb
ruary 29th of 2010, but there's no such date and so I got an error. So, I fixed
that to February 28th of 2010, and makes 60000. Key here is we were able to set
all of the values in the employee object through the constructor that took those
arguments. We could, of course, have a constructor that takes some arguments an

d not others, and we can even use initialization when we have a constructor. So,
you can mix and match these various ways of putting data into your object.
Summary
In this module, we talked about classes and objects, and we saw how classes defi
ne a type and objects are instances of that type. Classes can have fields, which
are the data for the class, and they can have properties, which are the way tha
t other methods of other classes interact with the data of the class. Classes ca
n also have methods, which represent the behavior of the objects in that class.
An instance of a class is called an object, and classes exist to instantiate obj
ects, each of which has its own data. The constructor can be used to create an i
nstance of a class and to populate the data of that class. A constructor that ta
kes no arguments is called a default constructor, and if you don't create any co
nstructors for your class, you will receive a default constructor by default. We
also looked at initialization in which you can set the values of the members of
the class at the time you create it.
Object Oriented Programming
Introduction
In this module, we look at object-oriented programming, and specifically the rel
ationship among the various instances of the classes that we'll create.
5 Pillars of OOP
It has been said that object-oriented programing relies on five pillars: Encapsu
lation, the idea that all of the workings of a class are behind the walls of tha
t class; data hiding, a closely related idea that the data held by the class is
private to that class and not visible to methods outside that class; specializat
ion, which we will come to when we talk about inheritance; and polymorphism, whi
ch we will come to when we talk about inheritance. But let's begin with division
of responsibility. It is imaginable that the way Microsoft would work would be
that Steve Ballmer, president of the company, would take orders on the phone, an
d if an order for Microsoft Office were to come in, Steve would run down to the
warehouse, find Office on the shelf; rush over to packing, package up the order
for Microsoft Office, walk over to the mail room, find the correct postage, and
post the package in the next day's mail to the customer. He would then run back
to his office to take the next call. This would be, well the technical word is,
insane. This is not a way to organize a company, and nor is it a way to organize
a program. Instead, each area has its own division of responsibility. We might
create a warehouse class. That class would be tightly encapsulated. Everything h
aving to do with the warehouse would be inside the warehouse class, and all of t
he data for the warehouse such as units on hand and so forth would be hidden wit
hin the warehouse class. Orders would come into the warehouse class through an i
nterface, and responses would come out of the warehouse class through a well-def
ined interface. That response might go to another class such as a shipping class
. What's important is that the shipping class knows nothing of the inner working
s of the warehouse class, and the warehouse class is totally ignorant of the inn
er workings of the shipping class. All they know, with respect to each other, ar
e these narrowly defined interfaces that specify exactly what information travel
s between them. This simple diagram illustrates division of responsibilities, bu
t it also illustrates encapsulation. In addition, you can see here data hiding.
And finally, you can see that between the classes are narrow interfaces.
Object Oriented Programming
Let's take a look at how these five pillars might translate into code by creatin
g a new application. We'll begin by creating a class warehouse. Previously, we h
ad created our classes all in the same file, but it's much more common, and bett
er practice, to create them each in their own file. To do that, we come over to
the solution explorer window. In the solution explorer is both the solution and
the project. In this case, we're working only on a single project. Let's right-c
lick the project and choose Add and then Class. Our Add New Item menu will open,
and we can name our class and save it, and a new window will open with the clas
s ready to go. Class Warehouse is our class. The most important method in our wa
rehouse class if find and return an item. We can make that public because we kno
w it's part of the narrow public interface, and we'll have it return an object b

ecause we don't know what type of object will be requested, give it a name, Find
AndReturnItem, and we need to give it some kind of parameter. How will the calle
r of this method identify the item they want? Well, let's have it that they will
identify it with an itemID. Then we will do some sort of work to find and retur
n their item. Notice the red squiggly line. That's because we don't have a retur
n statement, and we've defined that we're going to return an object. We can, in
fact, improve this right away. We know we want to return an item, which is some
type of object, but it's more specialized than an object. It's a specific kind o
f object. And so let's say that we're going to declare a class called Item, and
we will return an item based on its itemID. Notice that in addition to a red squ
iggly line under Item, there is a small blue line. If you hover over that blue l
ine, a tab opens, and if you click on that, the options for how to fix the red s
quiggly line come up. And one is Generate class for 'Item.' Let's go ahead and d
o that. Interestingly, Visual Studio created a new file called Item.cs, and in t
hat file it created a class Item for us. We know that our item is going to have
an ID, so let's go ahead and put that in right away and save that class. Returni
ng to the warehouse class, we now know that we can create an item and find it an
d return it. And normally what we would do here would be to search through a dat
abase looking for an item that matches the itemID. For now, what we're going to
do is just make an item that matches the itemID. To do that, we declare an objec
t of type Item. Let's give it a name and say new Item. Now, at this point, we ei
ther need a constructor that's going to take the itemID or we need to initialize
the itemID. However, if we say returnItem., we don't see itemID. It's not in th
e public interface of Item. Let's go back to Item and fix that. Notice we did ad
d an ID, but the default visibility is private. If we want that to be public, we
must specifically mark it public. We don't want to make a field public, so what
we will do is make this be a property. Now that that's a public property, we ca
n go back to warehouse, we can set the ID in the initialization to whatever valu
e we think is correct. Let's set it to 101, and now we've initialized that new i
tem with an ID of 101. And to keep this incredibly simple, we can then just retu
rn our returnItem. And notice the red squiggly line goes away because now we hav
e fulfilled the contract of this class, which says that we're going to return an
item. We don't want to set the ID to 101, however. We want to set it to whateve
r ID was passed in. So, let's change this to itemID. Now this substitutes for se
arching through the database for a matching item and returning it. Let's go to o
ur item class. We know that it has an ID. What else might it have? Well, every i
tem has a name, so we can give it a name. Let's go back to our warehouse class.
What else might the warehouse have? Well, for one thing, it probably has an ID b
ecause there's probably more than one warehouse. And, once again, we want to mak
e that be a property. We can also give our warehouse a name. And you can imagine
a number of other properties. While we're here, let's give our warehouse a cons
tructor, and that constructor will take a name and an ID. We can assign the Ware
houseName to the name that was passed in, but notice that the public property ID
is all caps and the ID that was passed in is all caps. We need a way to differe
ntiate between them. In order to do so, we use the keyword this. This refers to
the current object. Every method, including the constructor, receives a hidden p
arameter, which is the this reference, the this keyword that is used to refer to
the current object. So, I can say this.ID = ID, and there's no ambiguity that s
ays assign to the ID of this object the ID that was passed in. Let's go back to
our main program and wire up a request to the warehouse for an item. The first t
hing we need to do is to create a new warehouse item. Notice that the constructo
r for warehouse wants a name and an ID. So, we can call it "Warehouse 1" and we
can give it the ID 101. We now have a warehouse, and we can request an item from
that warehouse simply by saying newWarehouse., and we look for the public metho
ds, one of which is FindAndReturnItem, open parentheses, and it says you need an
itemID. Let's pass in 101 for the itemID. What we're going to get back from new
Warehouse.FindAndReturnItem if we hover over it, we can see that we get back and
item. So, we're going to say var myItem = newWarehouse.FindAndReturnItem. And w
hat we'll get back in myItem is an item. We know that items have a couple proper
ties. They have an ID and a name. Let's go into Warehouse and see if we assigned

an ID and name to the item. No, we just so far assigned an ID. So, let's go ahe
ad and assign a name too. Name="Microsoft Office." So, now our item has a name a
nd an ID, and in our program we can say Console.WriteLine ("my new item is " + m
yItem.Name). So, understand the relationship here is that we're asking for a new
Warehouse, once we have that warehouse we're calling FindAndReturnItem(101), the
job of the warehouse is to return the item, but it doesn't know anything about
the item except which item to return, but we can ask the item for its name. Let'
s run the program. And it says my new item is Microsoft Office. So, here we see
three objects interacting with each other, each with its own responsibility, the
program acting as the main representative of the customer, the warehouse object
encapsulating its own ID and name and having a constructor and a method, FindAn
dReturnItem, and the item class having just two properties, ID and name. Of cour
se, in a real program we would flush these out and give each of them more proper
ties and methods consistent with their specific area of responsibility.
Inheritance and Polymorphism Introduction
A key goal of object-oriented programming is to help us work with very complex p
rojects, and to do that we need to reduce the cognitive load. The less that we h
ave to keep in our head at one time, the better. This allows us to focus on a sp
ecific problem without solving the entire problem at one time. There are a numbe
r of ways to approach that. One way is to reduce complexity by grouping items. M
ost important is to create programs that work the way we think. This can signifi
cantly reduce the amount of work we have to do to keep things straight in the pr
ogram. It's best when programming corresponds to the way we are hardwired to thi
nk, and we tend to like to organize. We put things into groups. Try this experim
ent at your next party. Have someone empty the contents of their pocket or their
pocketbook onto a table and instruct them to make two piles. Give them no furth
er instructions. In fact, if you really want to have fun, have three people do i
t at the same time. When they're done, they will have two piles. Now, ask them h
ow they decided what went into each pile. Most of the time they will have reason
s. It will not be random. The reasons will probably be different among the diffe
rent people, but we do like to organize. One way we like to organize is to categ
orize. All of the blue things over here. All of the tall things over there. We n
aturally think in terms of hierarchies. The most classic hierarchy is probably t
he one we use to organize animals, class, order, genus, species, etc. We tend to
think of a dog as a kind of mammal, and mammals as kinds of animals. We also te
nd to think in terms of is-a and has-a relationships. So, a dog is an animal, bu
t it has a pair of ears, it has eyes, it has a nose. A car is a vehicle, but it
has a steering wheel and it has tires. And we'll come back to the is-a and has-a
relationships in our code. We also tend to think in terms of generalization ver
sus specialization, and this relates back to our hierarchies where an animal is
a more general form and a dog is a more specialized form and a Chihuahua is an e
ven more specialized form of dog. C# implements the concept of generalization an
d specialization with inheritance, and we will look at inheritance in our code.
We will see that we can have classes such as dog that derive from more general c
lasses such as mammal, and that we say therefore that the mammal is a base class
of dog. That is, it is the more general form. We'll take a look at virtual meth
ods that allow us to implement polymorphism, one of the pillars of object-orient
ed programming.
Inheritance and Polymorphism
Let's return to our program of items in a warehouse. We said that the warehouse
contains items, and we haven't looked at collections yet so we haven't created a
collection of items, but the idea is that items would be held in the warehouse.
And we said that all items have an ID and a name. However, there are different
kinds of items. One division we might make is to distinguish software from hardw
are. We might do that because software has an ISBN and hardware has a serial num
ber. However, they're both items. We can represent that in C# through inheritanc
e. We create our class Software. Then we put a colon and the class name it deriv
es from. In this case, Item. What that says is that all software is a kind of it
em or is-a item, and that's the is-a relationship. Because we inherit from item,
all software automatically has an ID and has a name. We can then add the things

that are specialized to software such as the ISBN. We can do the same thing wit
h our hardware where hardware derives from item and has its specialized pieces.
Now, it turns out that our hardware can be further divided into computers and pe
ripherals, and so we see that computer derives from hardware, and peripheral als
o derives from hardware. Computer and peripheral are kinds of hardware, which ma
kes them kinds of items. And that means that a computer will have a CPU type and
disks, but it will also have a serial number because it is a kind of hardware,
and it will also have an ID and name because it's an item. I put all these class
es into a single file for simplicity and so that we can see them at the same tim
e, but normally I would create one file per class. Let's return to our program.
We can take out the previous logic, and let's make an instance of a computer. He
re we've made an instance of myComputer, and with myComputer, when I hit the dot
, IntelliSense offers me all of the properties of a computer, CPUType, disk, but
also ID, name, which it gets from Item. The ID and name, although inherited fro
m Item, are very much a part of myComputer. Notice here we have declared myCompu
ter using type var, but the actual type that's being assigned is computer. Becau
se a computer is an item, we can say Item mySecondComputer = new Computer. Now,
that's a slightly confusing syntax, so let's understand it. All computers are it
ems, and therefore we can assign a new computer to an item, but notice we only g
et the item part of the computer. So, if we say mySecondComputer and hit the dot
, we get the ID and the name, but we don't get the CPUType and so forth. If all
we need is the ID that may work out very well for us. For example, if we have a
collection of items, and we'll be looking at collections soon, we can put comput
ers and peripherals and software in there and retrieve them by ID. Because we kn
ow that mySecondComputer is in fact a computer, although we declared it to be an
item, we can cast it, change it back to being the type we know it is. One way t
o do that would be to create a new object variable, and let's call it mySecondCo
mputer2 = mySecondComputer as Computer. And as says take this and treat it as if
it were this other class. And we know in this case it is. One of two things wil
l be assigned to mySecondComputer2. If mySecondComputer is a computer, then that
will be assigned to mySecondComputer2. In that case, we're able with mySecondCo
mputer2 to access, for example, the CPUType, and we can assign that to a string.
(Typing) If, on the other hand, it had not been a computer, if we had tried to
use the as Computer on something that wasn't really a computer, it would've retu
rned null, and we would've assigned null to mySecondComputer2, in which case we
would not have been able to access the CPUType. We're going to return to all of
this when we deal with collections. Let's take a look at one other aspect, which
is methods and method inheritance, and let's give our item a virtual method. A
virtual method means I intend for this method to be overridden in the derived cl
asses. That is, I intend for the derived classes to make their own version of th
is method that is specialized to that class. So, I can say public virtual, that'
s the keyword, and then whatever my return type is. We'll make it void in this c
ase, and then whatever my method name is. Let's call it Purchase. My parameters.
Let's not have any to keep it simple. And then the body of my method. In this c
ase, the body will use a Console.WriteLine as a stand-in for doing the work. Now
, when I decide to implement that method in software, I can say to myself, well,
I'll just inherit that method and not implement it at all or I can override it
to specialize it for software. And that's true for hardware and that's true for
computer. Let's not override it first. Let's just see that it works by going bac
k to Program, and here I have mySecondComputer2, and I can call purchase on that
. And when we run this application, it says Purchasing. Well, there's no name. S
o, let's give that a name so that it has something to display. Okay, now I've to
ld mySecondComputer2 that its name is Jupiter, and we can run that and it says P
urchasing Jupiter. Now, notice this is a computer. Computer did not have that me
thod, but it inherited it from Item. It also has the right to override that or c
hange the way that method works in the computer class, and IntelliSense will hel
p us with that. If we put in the keyword override and hit space, it says which o
f the methods that this class inherits do you want to override. It turns out all
classes ultimately derive from object, and object has three methods that can be
overridden: Equals, GetHashCode, and ToString. That's where those are coming fr

om. Purchase is coming from the Item. Let's override purchase. When we hit enter
, Visual Studio creates the method for us, and the first thing it does is it cal
ls the base.Purchase method. That's going to call up to Item and call the purcha
se method of Item. That's just fine with us. We'll let it go ahead and do that,
and we'll add a little bit of additional functionality that says myCPUType is an
d fills in the CPUType. Now, let's go back to our program in Program.cs and set
the CPUType. We can now call Purchase on this computer, and instead of just call
ing up to the Item, it should call the overridden version for computers. Let's r
un that. Purchasing Jupiter. MyCPUType is i7. So, notice that because it was com
puter and we overrode the purchase method, that overridden method is what was ca
lled. Now, if we call Purchase on Software, notice here we've created a new inst
ance of Software, and we have set it's ISBN to 1234, and we've called Purchase.
When we run that, all we get is Purchasing blank. It has no name. Let's give it
a name, run it. Here's our earlier Purchasing the CPU and then Purchasing Foo, b
ut no ISBN, and that's because we have not overridden in the software. We can go
back to the Software and override the purchasing method. Once again, we say ove
rride. There's our purchase method. It's going to call the base method. And know
, by the way, that calling the base method is not required. We could take that o
ut and instead put in completely new logic. So, now we're not calling the base m
ethod anymore. Instead, we're calling our new logic that displays our ID and ISB
N. Go back to Program.cs. Here's where we want to see, and let's run the applica
tion. And first we get the computer, my CPU is 17, and then we get the override
on the software, My ID is 0 and my ISBN is 1234. The ID is 0 because we've not i
nitialized the ID for the software, and so it was assigned the default value for
an integer of 0. Let's fix that by saying mySoftware.ID = 101. And now we're go
ing to ge My ID is 101 and my ISBN is 1234. So, you see we can progressively wor
k on this, and each of these classes can override the purchase method. Now, we c
ould've overridden the purchase method in hardware as well, and then again in co
mputer. And depending on how we declare the object, as an item, as hardware, or
as computer, will decide which of those overridden methods is called.
Static Methods
Let's return to the program we've been working with, but remove all of the conte
nts from the main method. Let's assume that we want to be able to generate a ran
dom item object. The best place to do that is in the item class itself. We can a
dd a method to Item that returns an item. We'll call it GetItem. All we need to
do in GetItem is to create an item object and to initialize it. And we'll initia
lize it with virtually random data. We'll set the ID to 101, and we'll set the n
ame to MyItem. Then we'll return the newItem we just created. In order to use th
at in our program, we need to call that method, and to call that method, we need
an item to call it on. We can do that. We can make a local Item called someItem
and new that up, and then on someItem we can call GetItem, which will get our n
ewItem, and we can assign that newItem to an item object, which we'll call newIt
em. Then we can use a WriteLine in order to display the contents of the newItem.
Let's run that. And the new item ID is 101, and the name is MyItem, and that's
just right. Now, this is silly in a number of ways, but the way that really matt
ers is that we had to create someItem that is an instance of Item just to call g
etItem. SomeItem has no other function. We use it to call getItem, and then we t
oss it. That's wasteful and annoying code. The solution to that is to go back to
getItem and to mark it with the keyword static. The keyword static indicates th
is is not an instance method, but rather this is a class method, and so we don't
need an instance to call it. Let's go back to our program and get rid of that i
nstance, and instead of calling it on an instance, we call it on the item class
itself. The effect is the same. When we run it, we get the same results, but the
code makes a lot more sense. Now, what we're doing is calling getItem on the It
em class, assigning the item we get back to a local item, and displaying its val
ue.
Summary
In this module, we introduced and talked about a number of advanced object-orien
ted programming concepts. We saw that inheritance models specialization and gene
ralization, and that derived classes can act polymorphically, that the method of

doing so is to declare virtual methods, which are designed to be overridden in


derived classes. We talked some about encapsulation, the idea that a class shoul
d be self-contained with narrow interfaces to other classes, and as part of that
, that data should be hidden and be made available through properties. We talked
some about the division of responsibility, assigning responsibility to differen
t classes. And the key here is that each class should have one well-defined area
of responsibility. And then we talked about static methods, which are essential
ly methods on the class.
Arrays and Collections
Introduction
In this module, we look at Arrays and Collections. We start by exploring arrays,
which are built into the language. We'll look at retrieving from an array and a
dding to arrays, and we will look at iterating over the contents of arrays. We w
ill then turn our attention to generics. Generics are a way to create type safe
collections. The collections that we will look at include lists, queues, stacks,
and dictionaries. Let's get an idea of what these different collections are lik
e. You can think of an array as a series of boxes all in a row. Each array has a
n address, which is its offset from the beginning, and so that the first item in
the array is at offset 0. The second item in the array is at offset 1 and so fo
rth. An important implication is that while the array shown here has a length of
7, the address of the last mailbox is offset 6. And we show the offset using th
e index operator, that is, the square brackets. Lists are very much like arrays
except that they can grow as you use them. They are not fixed size. You grow in
a list by using the add keyword. Queues are modeled on the idea of people queuin
g up or lining up perhaps at a box office. The first person in the line is the f
irst person to receive service, and that's known as first-in, first-out. Stacks
are more like a stack of dishes or pancakes. The last pancake you put onto the s
tack is typically the first one you take off, and so they're known as last-in, f
irst-out. Dictionaries are modeled on typical dictionaries where there is a key.
In a typical dictionary, that would be the word. And then there is a value. In
a typical dictionary, that would be the definition. Key value pairs make up a di
ctionary, and dictionaries can be very powerful collections because you can sear
ch through and sort the keys and their values come with them. Let's take a look
at all of this in action in some example programs.
Arrays
Let's get started by looking at a simple array. The easiest way to declare an ar
ray is with the var keyword. We'll call it items, and then we can new-up an arra
y of five items. We say new, the type that we're going to contain in the array,
square brackets, and the size of the array. We now have a new array with five it
ems and nothing in it. For the purposes of this program, I have stripped down th
e Item class to just have an ID. And the constructor takes an ID and assigns tha
t ID. With our array of five items, we can populate those ID's. Let's introduce
a new idea, which is the Random class. Random can create pseudorandom numbers, a
nd they're called pseudorandom because they're not 100% scientifically random, b
ut they're more than random enough for our purposes. I'll create a for loop, whi
ch will iterate through every item in the array. And notice that for my test con
dition, I checked that I is less than items.Length, and that's a good safe way.
Rather than putting in a magic number here that might change if I change the siz
e of the array, this is guaranteed to work for whatever size array I'm working w
ith. I can then do an assignment to items I, whatever the offset is at the momen
t as we're iterating through the for loop, is equal to a new Item. And what we n
eed to pass in here is a random ID, and that's where our randomizer comes in. We
'll say r.Next, and r.Next passes back a random integer, which we'll use as an I
D. Now, one of the nice things about collections is that they're very easy to it
erate over. In fact, there is a new looping mechanism that we can introduce now
called foreach. First, let's put a prompt so we know what we're looking at, and
then we create the foreach. Now, we could write this with a for loop just as we
did here for int i = 0; i < items.Length; i++. But because we know we have a col
lection and we want to see each item in the collection, something that we do qui
te often, we can say foreach, and then we identify the type, and then we give it

a local variable name. We can call it Item for each item in, and then the name
of the collection, which is items. Now, the logic here is almost readable as Eng
lish. For each item in items, as you go through items for each item you find, we
want you to do this work. And the work that we want you to do is to display the
ItemID. Let's try that. And sure enough, we're able to display all of the rando
mized ItemID's for each item in the collection. And notice there are five as we
expected. You can access an individual ItemID using the index operator. So, if I
want to access the second item in the items collection, I would do that at offs
et 1, and I might assign the ID of that item or I might assign the item itself.
Remember, items contains not ID's, but item objects. So, I could say Item myItem
= items Let's run that again. We'll see the foreach loop, and then we'll see ID
of second item. And sure enough, that matches the ID of the second item. You do
want to be careful not to try to go past the end of the array. For example, thi
s next statement looks very safe, myOtherItem = items We know the length of the
array is 5. However, with an array whose length is 5, then the last item is at o
ffset 4. We're now asking for what's at offset 5, and that can be virtually anyt
hing. Fortunately, arrays have built into them a test for that very situation, a
nd they will throw an exception. We're going to talk about exceptions in coming
modules, but basically they're a way to say that you have an error. And when we
run this program, in fact, array stops working. And if we look at the output, we
can see that everything worked up to that point, and then we had an unhandled e
xception, IndexOutOfRangeException. Index was outside the boundary of the array.
So, it gives you quite a bit of information. It even tells you what line the er
ror occurred on. Interestingly, arrays have methods. For example, arrays have a
sort mechanism. Let's create a new array. Here I've created an array of strings
called authors, and I've populated it with five author names, which I hope I've
spelled correctly, and then I have a foreach loop that iterates through and disp
lays each in turn. We can now call sort by saying Array.Sort and pass in our arr
ay of authors. If we now display them again, which we can do by copying and past
ing the foreach loop, we should see it unsorted and then sorted. So, here's our
first author, Faulkner, Proust, Stephenson, Gibson, Melville. And then here we c
ome again, and this time they are in alphabetical order. Sort is a built-in meth
od of array. We can learn a great deal more about sort by hovering over it and p
ressing F1. And that will bring up the msdn help file on Array.Sort. We can lear
n quite a bit about Array.Sort. We get a quick summary, we get a list of all of
the overloads, and there are quite a few, and we get a See Also that gives us mo
re information that we can look up. Often times, this documentation will also ha
ve an example program that you can run. Note, that the See Also refers us to the
array class itself. And by clicking on that, we can go to the class, and we can
see how to create arrays, what the properties of an array are such as Length, w
hat the methods of an array are, and there are quite a few methods, Clear, Clone
, these can be very useful, Copy, Find to search for an element in your array, a
nd you can see there are a lot of methods in the array class. And then there's a
full documentation on the array class, on its limitations, and on how to use it
. And here we do see it followed by examples that you can copy and paste into yo
ur code. We got here, remember, just by putting our cursor on the keyword and pr
essing F1. And that's a feature of Visual Studio.
List
The classic problem with arrays is that you never know what size to make them. I
f you make them too small, then you run out of room. If you make them too large,
then you waste room. Let's take a look at the List class, which is designed to
overcome that problem. The List class is a generic collection. And notice that V
isual Studio has added the namespace using System.Collections.Generic. That's wh
ere the List class lives. It's generic in that it takes the type of object it wi
ll be holding in angle brackets. And so, the syntax for a list of int is List<in
t>. And we read that List of int. We give that a name as we would anything else,
and we new it up with a new statement, new, and notice IntelliSense can help us
here, List of int. When a list is born, it is empty. You add to the list by usi
ng the add method as you can see by clicking on List, pressing F1, and bringing
up the help file for List of T, where T stand for type. As we scroll down, we ca

n see that there are a number of properties such as the Count or Item, which get
s an item at a specified index, Add to add to the list, there's a Copy to copy t
hat list, Find as we saw on array, quite a number of methods including Remove to
remove an item from the list either by passing in the item or RemoveAt, passing
in the index at which you want to remove the item. There's also Sort, and there
is a ToArray method, which lets you turn your list into a fixed size array. We
can add to our list of integers using a for loop. Here we've added a random obje
ct at the top, and so we can add random numbers to our list, and we will add 10
by iterating through it. Once we have our list, we can operate on it such as cal
ling sort. And notice here we call sort on the instance of the list, and then we
can display the contents of the list using a foreach loop. Let's run our applic
ation. And sure enough, we have a list of randomized integers, and that list is
in alphabetical order. Notice that the earlier numbers that are shorter come fir
st, and the longer numbers come after that. Lists are very handy and may well be
the collection that you use most often. If we return to the classes we were wor
king with earlier, item, program, and warehouse, we now can create a more ration
al GetItems method. Previously, we were getting a single item. Now, we can write
this method so that we get a list of items. The first change is that we change
the return type from Item to list of item, and let's change the name from GetIte
m to GetItems. Here's the logic of our new GetItems method. It takes a number to
get how many items do we want. We start with a randomizer, we create a new list
locally, we define a newItem, and then in a for loop, up to however many we're
supposed to get, we assign newItem to a new Item providing a random number for t
he ID, and setting the Name to MyItem + whatever the value of I is. So, MyItem 1
, 2, 3, 4. We then add that new item to our list, and it iterates with a for loo
p again. When we complete the for loop, we return the newList. Thus, GetItems re
turns a list of items. We can now turn to Program.cs, and we can change our code
here and call GetItems. Remember GetItems is static so we call it on the class.
Now, we have 20 items, not just 1, so we're going to want to iterate through th
at list using a foreach loop. And so we move Console.WriteLine inside a foreach
loop, and the logic of the foreach loop is for each item in myItems we're going
to display item.Id and item.Name. Let's run the application. And sure enough, we
get 20 new items, each with a random number for the ID, and each name increment
ed MyItem0 through MyItem19.
Queue
While lists are by far the most popular collection type, the queue has a great d
eal to offer when you need to ensure that items are added and removed in a first
-in, first-out manner. A classic example of this is the canonical recording, you
're call is important to us, and it will be answered in the order in which it wa
s received. You declare a queue very similarly to how you declare a list, and le
t's get those parentheses in there. Once you have a queue, you add to the queue
with the Enqueue keyword. You can remove from the queue with the Dequeue keyword
. And here we can see enqueuing the value 100, and then dequeuing into a tempora
ry variable named val. And when we run this, sure enough, we get the value back
out. Here we use a for loop to enqueue 50 values and a foreach loop to iterate o
ver the queue, examining its values. Let's run the application. And sure enough,
we find the 50 values are in the queue. Since we didn't use dequeue, they're st
ill in the queue, and it's worth asking yourself if I dequeue a value at this po
int, what will be the value that will be dequeued? Let's run that and find the a
nswer. The dequeued value is 0 because a queue is a first-in, first-out list, an
d 0 was the first value added to the queue. If we dequeue a second value, then t
he value that will come off of the queue will be the second value that was added
to the queue. And so we see that the first dequeued value was 0 and the second
dequeued value is 1.
Stack
The stack is so close to the queue that we're going to create our stack demonstr
ation program by going back to the queue collection and renaming it StackCollect
ion. Now all we have to do is change the queue to a Stack, rename myQueue to myS
tack, change the Enqueue to Push and the Dequeue to Pop. Now we have virtually t
he same program except we're using a stack instead of a queue. You want to antic

ipate what values are going to be popped down here. Let's run the application an
d see if you're right. The first thing we see is a value of 100. We then see the
values added, 49, 48, 47, 46, 45. Notice they're in reverse order because they'
re pushed in on the stack. The first one is pushed in at 0, then 1, then 2 is pu
shed in, then 3. When we pop, we pop that last value that was pushed in, 49. And
when we pop again, we pop the next to last value, 48. So, a stack is a last-in,
first-out collection.
Dictionary
The last collection that we'll look at is among the most used, and that's the di
ctionary. The dictionary allows you to associate a key, which most often is not
an integer with a value. Let's say you want to create a collection of the capita
ls of all 50 states. You could create an array of 50 strings, but remember that
within an array you have to index using an integer. And so if you want to find t
he capital of Arizona, you would have to say state capitals offset 2. That's not
so difficult, but there's no easy way to remember that Massachusetts is the 21s
t state alphabetically. It would be much more convenient to store the capital wi
th the state name, and a dictionary allows you to do just that. Here I've declar
ed a dictionary. Inside the angle brackets, I need to put the type for the key a
nd the type for the value. In this case, they're both stings, although they cert
ainly don't have to be. I've named my dictionary capitals, and I've newed-up the
dictionary of string, string. In order to add to the dictionary, I call the Add
method, and I pass in two values. The first value is the key. The second value
is the value. In this case, the key is the name of the state, and the value is t
he capital of that state. Notice that I got lazy around Arizona and just dropped
in a couple more states. To extract the value from the dictionary, I use the in
dex operator, the square brackets. But rather than putting in an integer, I put
in the key that I'm looking for. What I get back is a value, and I can display t
hat value as you'll see when we run this application. And sure enough, I get bac
k the value Boston by passing in the key Massachusetts. In the typical use of a
dictionary, the key would be short, but the value might be fairly complex. Let's
create a class and make a dictionary of objects. To do that, we'll go to our pr
oject and Add a new Class. We'll call the class State. Let's make the class publ
ic, and give that class a couple properties. Here we have a class State that has
three properties, the Capital, which is a string, the Population, which is an i
nteger, and Size, we'll use an integer for size as square miles, and we have a c
onstructor. Let's add a static method to our state that will get back a collecti
on of states. Here we've created a GetStates method that returns a dictionary of
string, State. That means that the key will be a string and the value will be a
state object. To get started in this method, I create a temporary variable call
ed states, which is a dictionary of the type we need. That is, it takes a sting
as its key and a state as its value. I then instantiate a state, new State, pass
ing in the capital, the population, which obviously I've made up, and the size i
n square miles. Again, I've made that up. I then add to the dictionary a key, in
this case Alabama, and theState I just created. Let's create another state to a
dd. My second state has Juneau as the capital and a population and size, and I a
dd that to the dictionary under the keyword Alaska. We'll go with just two state
s for now to keep this simple so the method will return that dictionary. Back in
our program, let's take out what we have already in here, and we'll just commen
t that out for now. We can declare a variable called theStates and set that equa
l to, and now we can call the static method on State, which is GetStates. GetSta
tes will return that dictionary where the key is a string and the value is a sta
te. Because we used the keyword var, the compiler will determine the correct typ
e for theStates, and as you can see, it has determined that it's a dictionary wi
th a key and value. And it has also determined that the key is of type string an
d the value is of type state defined in DictionaryDemo, which is this applicatio
n. So, var very powerful, gives you great flexibility, and still keeps that type
safety. Once again, we can retrieve one of our states by using the index for th
e key. What I wanted to retrieve is the sting the capitalOfAlaska. Remember theS
tates returns as its value, not a string anymore, but a state. So, when I say th
eStates index Alaska, I get back a state object. I can then use dot notation to

retrieve the capital from that object. And when we run this, we should see that
the capital of Alaska is Juneau. And sure enough, we do. I could instead of retr
ieving the string, I could've chosen to retrieve the state and then used that st
ate to populate a WriteLine with the population and the size. So, now we use a v
ariable, theState, which is whatever we get back from theStates giving the key A
laska. That will be of type State. We can then call a WriteLine and say the capi
tal of Alaska is first substitution parameter, its population is substitution pa
rameter, and it is substitution parameter square miles, and use theState to acce
ss the capital, population, and size. Let's run that. And sure enough, we get th
e results that we had put into the dictionary.
Summary
In this module, we discussed collections beginning with arrays. Arrays can be th
ought of as boxes all lined up starting at offset 0. Arrays are a fixed size. To
solve that, one of the most popular generic collections is the list. Generic co
llections are type safe, and in defining the collection, you state what type of
objects the collection will hold. We also looked at queues, which are first-in,
first-out collections, and stacks, which are last-in, first-out collections. Fin
ally, we looked at dictionaries, which allow you to pair a key with a value.
Exceptions
Introduction
In this brief module, we will discuss Exceptions. Exceptions are thrown when the
program can no longer proceed because it has run into an error. We talk about c
atching exceptions when we handle the exception. Because there may be code that
should run whether or not an exception is caught, you can also add a finally blo
ck as we'll see in just a moment. And then we'll take a look at custom exception
s.
Exceptions
The best way to see how exceptions are thrown and caught, of course, is with a d
emonstration program. Let's create a new program, and let's start by looking at
what happens if an exception is thrown and not caught. Here we have a very simpl
e program that prints out "First line of the program", sets X to 0, calls Y, and
divides 12 by X, which is a divide by 0 and an instant exception. We then follo
w that with a line that says "After the division." Let's run this program. The e
xception is thrown, and we get a good bit of information about the exception. He
re's First line of the program. Here's the Unhandled Exception. It tells you wha
t the exception is, Attempted to divide by zero. It tells you where it is in Pro
gram.cs on line 15. And notice that the follow on line, the line that was suppos
ed to appear after the division, never shows. When an exception is thrown, all p
rocessing in the current function stops. Now, we've been working with single fun
ctions. Let's take a look at what happens when functions call functions and exce
ptions are not handled. Here I've created a new class called Tester with Methods
1, 2, and 3. Each method begins by announcing that it's beginning, and then Met
hod1 calls Method2, Method2 announces its beginning and calls Method3, and Metho
d3 announces its beginning, and each announces its end as well. Let's comment ou
t the code that's going to throw the exception. Down in our main program, we mak
e an instance of a new tester. We need parentheses there. And then we call t.Met
hod1, which kicks off this chain of method calls. If we run this, we see Method
1 begins, Method 2 begins, Method 3 begins, and then 3 ends, 2 ends, 1 ends just
as we would expect. Now, let's put in the code that throws an exception in Meth
od3 and run the code. There's the exception thrown. And we see Method 1 begins,
2 begins, 3 begins, but then there's an exception in 3. And what's very importan
t here, in addition to telling us that it has attempted to divide by zero, and i
t tells us that happened in Method3, it then goes back and tells us that it wasn
't handled in Method2 and it wasn't handled in Method1. What it's doing is unwin
ding the stack. We have put on the stack 1, and then it has put on the stack 2,
and then it has put on the stack 3, and it's being unwound all the way back to t
he main program. And since none of these methods handle the exception, the excep
tion is propagated all the way up to the default exception handler, which just c
rashes the program. Now, our goal is to have our program not crash. Ideally, we
would handle the exception and continue on, but if not, we would at least like t

o end the program appropriately with what's called a soft landing rather than a
crash. One way to accomplish that is to surround code that might throw an except
ion with a try block. Here we've surrounded the dangerous code with a try block.
That's a keyword try, and then we the block in braces. And we follow that immed
iately with a catch block. The catch identifies the exception that it's catching
, and it can identify that with the more general Exception keyword or with the s
pecific exception that it's anticipating. And that allows you to have multiple c
atch blocks, some with very specific exceptions and others with the more general
. In any case, the catch block handles it however it's going to. In this case, i
t's just going to print out Caught exception, and then display the exception mes
sage. The exception message is a property of the exception itself. Let's run thi
s and see what happens. First of all, our program does not crash. That's the fir
st thing to note. Second thing to note is that we have 1, 2, 3 begins, then we h
ave our catch block running, and then 3 continues, 3 ends, 2 ends, 1 ends. And s
o in Method 3, the exception is handled, and Method 3 is able to continue on aft
erwards. It is possible to put the catch block higher up in the calling stack. I
t may be that rather than putting the try block around this dangerous code, we r
ecognize that Method3 itself is dangerous. In that case, we might choose to put
the try block around the call to Method3. Anticipate what will happen now. Metho
d3 will run, the exception will be thrown right here, the stack will unwind to M
ethod2 where it will be caught, and Method2 will be able to continue on, althoug
h Method3 will not. Let's run that. And we see 1, 2, 3 begins, we see the caught
exception, and notice 2 ends. We don't get 3 ends because 3 had the exception t
hrown and was unable to continue. And then 1 ends.
Finally
There are times that you have code that must be run whether or not an exception
is thrown. Let's say that in this application you open up a file. Rather than pu
tting in the code for opening the file, we'll substitute with just a line that s
ays "File opened..." At the end of the method, you need to close that file. We c
ould put "File closed... into the catch block, and then it would be reached if a
n exception was thrown, but not if an exception wasn't. We could copy it to both
places, but programmers hate to have the same code in two places, and with good
reason. When you have code that is identical in two places, inevitably one of t
hem changes and the other doesn't. The answer to this is to create a finally blo
ck. A finally block is guaranteed to run even if there is an exception, and it w
ill also run if there is no exception. And here we see File opened..., Caught ex
ception, File closed..., and we continue on.
Custom Exceptions
Ninety-nine percent of the time, you'll be able to use the exceptions that come
with the framework library. However, there are times that you need to create a c
ustom exception if only to provide your own message and your own information in
that exception. Here I've created a custom exception that derives from exception
. My first method in MyCustomException is the constructor, which receives a mess
age. I follow that with a colon to indicate that I want to pass to the base its
parameters. The base receives a message as its parameter, and so this constructo
r is going to pass that message directly to the base class. What's nice about ha
ving a custom exception is that I can use that to differentiate from the system
exceptions. In my public class Tester, I have a public method DoDivide. You pass
in two doubles and you get back a double, and it returns one by the other. It c
hecks to see if Y is 0. If Y is 0, it throws an existing exception, the DivideBy
ZeroException. However, in our case we don't want dividends that are 0 either, s
o we test to see if the dividend is 0, x == 0. And if it is, there's no system e
xception to throw, but we throw MyCustomException, passing in the message "Divid
end can't be zero!" In our program, we create a try block, we make a Tester obje
ct, and we say DoDivide 12 and 4. And that should work fine, and so we print the
answer out with a WriteLine. We then call DoDivide with 0 and 4. There are two
catch blocks. One for the DivideByZeroException, and one for the CustomException
. Let's run this. The first DoDivide 12, 4 is equal to 3. The second one raises
the custom exception, Dividend can't be zero! And notice that's coming out of he
re, MyCustomException, and we know that's the custom exception because up here w

e say throw MyCustomException with "Dividend can't be zero!" It's unusual to cre
ate your own exceptions, but it's very easy to do. Simply derive from system exc
eption.
Summary
In this module, we looked at how errors can cause your program to throw exceptio
ns and how you can manage that using try and catch blocks. We looked at how you
can use the finally block to ensure that a line of code is called whether or not
an exception occurs. And finally, we looked at creating custom exceptions.
Advanced Topics
Introduction
In this final module, we will cover a few topics that are important to fully rou
nding out your understanding of C#. The advanced topics that we'll cover are int
erfaces, abstract base classes, and delegates.
Interface
The best way to understand interfaces and to understand what they're for is to s
ee them in a demo program. Let's begin by creating a custom interface. To do so,
we go over to the project and right-click and choose Add New Item. In the New I
tem list, we'll call Interface and we're going to call our interface Storable. T
hat creates an interface in a file called Storable.cs. An interface is a contrac
t. As such, you define the methods and the properties that any implementing clas
s must provide. You do not and cannot provide access modifiers on the methods or
properties. They're public by their nature. We're going to decide that our inte
rface has two methods and one property. The first method is Write, and the secon
d method is Read. For our property, we're going to want to use an enumerated con
stant, which we'll call ReturnStatus. That allows us to write ReturnStatus and c
all our property Status, and all we put in is the get and the set, but, again, n
o implementation. That's our complete interface. That's the contract. If you wan
t to be a storable object, then you must implement Write as a method that return
s void and takes an object, Read as a method that returns string, and Status as
a property that gets and sets a ReturnStatus enumeration. Note that it's typical
and very much the convention to begin all interfaces with a capital I, and so t
his would be IStorable. But many of us are moving away from that convention as a
last vestige of Hungarian notation. Hungarian notation was a way to implicitly
state the type in a variable name, and it has been deprecated by Microsoft. So,
we'll call our interface Storable. Now that we have an interface, we can create
a couple objects that implement the interface. Let's go back to the project and
say Add Class. And the first class that we'll add with be Note. We'll mark our N
ote class public, and then we want to indicate that it implements Storable. We d
o that with the same notation we use for inheritance, that is a colon and then t
he keyword Storable. There are a couple important things to note here. First of
all, if Note derived from another class, that base class would be listed first a
nd Storable would be listed second. So, it would be myBase, Storable. It is not
legal to implement for more than one base class, but it is legal to implement as
many interfaces as you want. Also, note the blue line under Storable. The compi
ler knows what it takes for an object to be storable. It knows what the contract
is. And so if we click on that blue line and open up the tab, one of our choice
s is to implement the interface Storable. We can click on that and the compiler
does, or more accurately, Visual Studio does a lot of work for us in creating th
e necessary methods and property. All we need to do now is take out the exceptio
n statements and put in the logic of each of these methods. For the property, I'
m going to create a backing property using ReturnStatus, that's our enumeration,
and I'll call it status, and then the getter can return the backing property an
d the setter can set the backing property. Note that our Note class is a normal
class, and it can have other methods and other properties as well. The interface
acts as a contract and says you must have these two methods and this property,
but you can also have anything else in your class that you would normally put in
a class. That's our Note class. We can create a second class that also implemen
ts Storable, but does so quite differently. Let's go over to the project and add
another class, which we'll call DBEntry. Once again, we're going to make that c
lass public, and we're going to have it implement the Storable interface. Let's

let it set up the stubs for us. But here, the Write works quite different. With
DBEntry, we're reading and writing from a database. Now, of course, we're not ac
tually doing that work, we're just stubbing that out with WriteLines, but you ca
n imagine that the logic would be entirely different. So, what have we gained? W
hen we go to our program, if we know that we have a Note or we know that we have
a DBEntry, we haven't gained much. But what if what we have is a collection of
storableObjects? Now, we can treat all of the objects in that collection as stor
ables rather than as whatever type they actually are. Specifically, I can create
a new Note and then add it to that collection. I can then go ahead and create a
DBEntry object, and I can add that to storableObjects as well. Now those are tw
o entirely different types of objects, but what we're doing is treating them as
storables because they implement the Storable interface. From within that collec
tion when we extract them, they will be storables. That means that the Note won'
t have access to the other methods of Note, but it will have access to all the S
torable methods of Note, and the same holds for DBEntry. Let's add a few more to
the collection. So, now we have a nice collection with some Notes and some DBEn
try objects, and because we have a collection called list, we can iterate over t
hat collection list using a foreach loop. It turns out, by the way, that the rea
son you can do that is that list implements an interface called IEnumerable, and
foreach can be used on any collection that implements IEnumerable. But returnin
g to the story at hand, we have our list of storables called storableObjects. Le
t's iterate over that list. Make sure you're comfortable with and understand thi
s foreach statement, foreach Storable, variable name storable, in storableObject
s. So, for every Storable type, which we will temporarily call storable in stora
bleObjects, we're going to take a certain action. Well, the first thing we can d
o is we can say storable.Write and write that to where? Well, it turns out that
the Note will write it to the disk and the DBEntry will write it to the database
. Now, I have a red squiggly line because write takes a parameter. I don't want
to pass in a parameter, it expects some sort of object, and so I'm going to pass
in null. Wherever you expect an object, you can pass null instead indicating th
at there's no object to be passed. Now, if it depended on having some property o
f that object, I'd be in trouble. But it doesn't, and so null is just fine. And
then I'm going to say Console.WriteLine and pass in storable.Read. And we'll do
that for each entry in that collection. Let's run that. And so we see writing ob
ject to disk, and reading note from disk, and writing object to database, and re
ading entry from database, and writing object to database, and reading entry fro
m database. And essentially what's going on here is that each type, whether it's
a note or a DBEntry, is doing the right thing. It's acting polymorphically beca
use we've used this interface to handle designating how it handles read and writ
e.
Abstract Class
There are times that you want to move data or methods up into a base class, but
you have no intention of instantiating that base class. That's called an abstrac
t class. Let's take a look at where you might run into such an idea. For example
, you might have in your program a representation for workers and for managers.
Workers and managers are both employees, and there are any number of properties
and methods that belong in that base class even though you will never instantiat
e an employee class per se. In order to create such a class, you create a new cl
ass, mark it public, and then mark it abstract. And that says it is not legal to
instantiate an employee. You must instantiate something that derives from emplo
yee. Abstract base classes are similar in some ways to interfaces in that they d
ictate what the derive classes must implement. They're quite different from inte
rfaces in other ways. For example, abstract base classes can have properties and
can also have methods that do have implementations. Let's give our Employee cla
ss two properties, a Name and a Salary, as well as a private member or field cal
led HireDate of type DateTime. We can then give our Employee class a public virt
ual method that can be overridden in derive classes called Hire. Notice that der
ive classes are not required to override the Hire method. They can inherit it an
d use it exactly as is. We can also give our abstract class an abstract method.
Notice that method has no body, no implementation. Any derive class must overrid

e the abstract methods or it too is abstract. Let's implement a couple derive cl


asses that will derive from Employee. The first that we'll implement will be the
Worker class. As usual, we mark that it derives from Employee by putting in a c
olon and then the name of the base class. Remember that in order to make this a
concrete, that is not abstract class, we must override GiveRaise. (Typing) When
we type override, IntelliSense is able to show us all of the methods that we mig
ht want to override. We can override Hire, which is in the base class Employee o
r Equals, GetHashCode or ToString, which is in the most base class, that is obje
ct, but we must override GiveRaise if we're going to implement a worker. We'll h
ave GiveRaise give a 3% raise to workers. Let's create another derive class. Thi
s one we'll call Manager. It too must override the GiveRaise method, and we'll h
ave it do the same thing, give a raise, but we'll have that raise be 5%. Let's t
urn now to our program, and in the body of our program, we can create a few obje
cts that are derived from Employee. For example, we might create a new Worker. W
e can then set the inherited properties, Name and Salary. So, our worker makes 5
0000. Let's create a second object derived from Employee, and that'll be a new M
anager. And then let's create a second Manager. Because all three of these objec
ts inherit from Employee, we can put them into a list of employees. That's perfe
ctly safe to do because they all are employees as long as the only methods or pr
operties that we call on them are methods or properties of the Employee class, n
ot methods or properties that were added in the derive classes. Let's iterate th
rough our collection of employees, displaying their salaries, and then calling G
iveRaise on all three of them and displaying their new salaries. You can see tha
t this foreach loop will iterate through the employees collection, write to the
console, substitution parameter, salary was, second substitution parameter, and
we'll put in the Name and the Salary. Then we'll call GiveRaise on the employee.
Now, that method is overridden differently in the Manager than in the Worker. S
o, we expect the Manager to get a 5% raise while the Worker gets a 3% raise. Let
's try that. So, David, who is a worker, went from 50000 to 51500, a 3% raise. R
achel, who is a manager, went from 100000 to 105000, a 5% raise, and we see the
same thing with Zach going from 120000 to 126000. Abstract base classes can be v
ery, very powerful, but remember that you can only inherit from one class while
you can implement as many interfaces as you want.
Delegates
Delegates are often thought of as one of the trickiest parts of C#. But really,
all a delegate is is a reference to a method. It's a way of passing a method as
an argument to another method. This allows you to decide which method to call at
runtime from a series of similar methods. In this case, methods are similar if
they have the same return type and arguments. Let's take a look at this from a p
ractical viewpoint. We're going to create a MediaTester class. So, we'll Add a N
ew Class to our project and call it MediaTester. MediaTester wants to be able to
run a test using any method of any class that takes no arguments and returns an
integer where 0 is success and 1 is failure. We can declare a public delegate o
f that class, and then we show the return type, the name of our delegate, which
we'll call TestMedia, and the argument list for the method, which in this case i
s empty. Understand the syntax here. This declares TestMedia to be a delegate th
at returns int and takes no arguments. We can now create a method of this class,
which we'll call RunTest that takes an instance of a TestMedia that is of one o
f those delegates. We'll call it testDelegate. Within the body of our RunTest, w
e can call the method that's encapsulated inside this delegate by saying testDel
egate and parens. And we know what we get back will be an integer result, so we
can assign that to a local variable. We can then do whatever we think is appropr
iate with that local variable. In this case, if we get a result of 0, we will de
signate that was successful. Otherwise, we have a failure. We can now create com
pletely separate classes to be tested by the RunTest. For example, let's create
a class called MP3Player. This class can have any number of properties and metho
ds, but the method that we care about is the method that matches that delegate.
In order to match the delegate, it must be return an int, we'll give it a name,
and it must take no properties. Presumably, here we would actually play the MP3
file, and if it played successfully, we would return the success code, which in

this case is 0. We can create another class called MP4Player. Once again, MP4Pla
yer could have any number of methods, but presumably, it would have one that mat
ches the delegate, and in this case we'll have it fail. We'll have it return 1.
We now have everything we need to use the delegate to test MP3Player and MP4Play
er. Let's turn to our program, and in our program, let's create instances of the
MediaTester, the MP3Player, and the MP4Player. Now, we need to create instances
of the delegate. The first one I'm going to call mp3Delegate, and I'm going to
new it up, and what I'm newing, of course, is the TestMedia delegate in MediaTes
ter. So, I need to say where it is, MediaTester, and there's the TestMedia deleg
ate, and I need to pass to it a method that meets the return type and parameters
. And we have such a method in mp3. That method is PlayMP3File. I can also make
a delegate for my mp4, and I do very much the same thing, TestMedia, and I look
for what mp4 has, and it has a matching method, PlayMP4File. I'm now in a positi
on to run those tests. Remember tester is my instance of MediaTester. So, I can
say tester.RunTest and pass in the mp3Delegate. I can say tester.RunTest and pas
s in the mp4Delegate. And what's going to happen when this runs is that tester i
s going to run the RunTest method and that is going to call through the mp3Deleg
ate to the PlayMP3File and get the results and mark them accordingly. Let's look
at that. Here's tester RunTest, takes a delegate, it's going to use that delega
te to call/invoke that method, and then display the results according to what it
gets back. We can run this program. And sure enough, it says playing MP3 file,
which it gets through the delegate, and it gets back a result of 0, and so it di
splays it works. Then it says playing MP4 file, that's from the MP4 player, and
gets back the result of 1, and so it says it failed. So, you can see that delega
tes can be very powerful for deciding which method of all of the possible matchi
ng methods to run at runtime.
Summary
In this module, we looked at a number of advanced topics including interfaces, a
bstract base classes, and delegates.

You might also like