What is C#

C# is a somewhat new language on the scene considering the first compilers widely known like Fortran in the fifties with a possible even older but less well known one by Konrad Zuse in the forties. But it is a very mature language with several versions. The first version came out in 2002, and now the current version is 7, so it has been rapidly advancing with wonderful features.

A compiler at its heart is a language translator. It converts in a series of steps for instance C code to something the machine can understand. For C#, it translates it into an intermediate form called intermediate language that is meant to be able to run on several platforms unlike a compiler that goes from a high-level language like C++ to machine code or assembly which is just above machine code. Assembly is mostly just text mnemonics for the different instructions a processor understands, so it is still platform dependent.

You need a compiler for serious projects because it gives you high level constructs to work with and ways of grouping functionality that make it easier to program. Each language, even machine language, gives you a set of features that allow you to control your machine. The higher the level, the more you get done with less code, and thus often it is easier. The tradeoff is that lower level allows more fine-tuned to control.

The ideal is for the programmer to use the highest-level ways first, and only go down to low level when absolutely necessary. Security and other anti-malware is such an area where known assembly and hardware architecture are going to come more into play than say making a word processor.

History

These won’t be clear at first to the beginner, but each chapter will introduce new concepts and reference back to this list.

  • Introduced generics which is better for type safety and is more efficient when you don’t have to cast all over the place.
  • Introduced LINQ which adds SQL like syntax and methods to the keywords and library. It can shorten your code and make it more readable as it gets rid of a lot of nasty long and horrendously nested loops and if statements. The reader will be given some parallel examples of old and new ways and when one or the other is more appropriate.
  • Introduced named arguments. This feature is helpful since it can make API (Application Programming Interface) calls more readable since you know what is being passed in and why. With a large library out of the box and many more you can tap into with Nu Get, all the libraries will start to be confusing, so any syntax that helps you remember and quickly see what is a tool you should use.
  • The .NET parallel library also adds several features and even added parallel extensions to LINQ.
  • Introduced syntax for asynchronous programming. It’s far more efficient than plain old linear programming when you can have the computer do tasks that don’t depend on each other to operate independently.
  • Index initializers which allow you to use less and better looking code to make better generic collections.
  • Better tuple support.

All these aren’t the only ones, but as each feature is elucidated in the chapter, you’ll get a feel for when it was introduced. This can be important because legacy code may come your way, and you’ll want to know why someone may have done something you wouldn’t do now with current features. Being able to maintain legacy code is lucrative. There are still jobs for people who know how to do sixties mainframe COBOL to show you how extreme it can be.

Audience

The audience for this book is beginner to intermediate. Everything will be explained in detail for the beginner, and if the intermediate student needs a refresher, these examples and explanations should be most welcome.

You first program Example

Go ahead and open visual studio if you have it. If you don’t go ahead and download it from Microsoft. They have free versions which will be used in all examples in this text. Also, don’t worry if you theme looks different than mine, the main thing is to focus on the relevant menus and syntax. The rest is just look and feel.

Here’s where you might make a new project by clicking new project under the Start Listing:

Here is giving it a name. it doesn’t really matter what you call you’re just as long as you’re consistent with the examples I’m giving unless you feel a little daring. I don’t want to discourage experimentation, but if you get frustrated, come back to square one and restart. That’s approximately how Sir Isaac Newton taught himself mathematics.

From here on out I will be posting the examples as text rather than screen shots so you can copy and post (don’t do that at first since typing it will keep you engaged and help you remember), and it’s also easier to read.

Modify what is given to you to the following

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication1
{
classProgram
{
staticvoid Main(string[] args)
{
Console.WriteLine(“What’s all this then?”);
Console.ReadLine();
}
}
}

Don’t worry too much if you don’t understand all. It will become clear in a few Chrono’s (smallest theoretical unit or particle of time). The two lines are my adaption to the Hello World you find in almost every beginner’s example.

The Console is what you use to communicate with your operating system’s terminal or terminal emulator from old DOS days or current Linux distro. Yes, you can use a type of C# in non-windows environments. That is beyond the scope of this book, but check for new publications from the seller, and you might get later on fined tutorials specific to Linux.

You can write all kinds of data to the console, and if there is a line at the end of the method, which WriteLine is indeed a method (sort of an all-encompassing term for functions and subroutines if you are familiar), there will be a newline character added to the text equivalent to enter. Your platform will determine the sequence, but for now, when you want to add it in a string in windows, just use “\n”.

The ReadLine will read input from the console. In this case, we’re just using it to keep the terminal that comes up from blipping. Go ahead and click the start or debugging button or right click on your project and click start debugging and something like this should show up:

Before we move onto variables, a word on some of the parts I have yet to explain.

First, there is the Main. It is a method that marks the start of your program. All execution will start from there. You won’t worry about it as much when you do graphics, but any time you do a console based app, you must have your program flow begin there in some way. A method is just a way to encompass some functionality as a unit. For instance, instead of having to rewrite the functionality of computing the sine of some number each time, it’s best to have a method to call it whenever you need it. The Main is special in that the operating system calls it.

Next inside its parenthesis is an array of strings. You know it’s an array by the [] next to the string variable declaration. Being inside the method’s parenthesis also means that it is an argument to the method meaning that’s how you put information into it. In this case, it’s only going to be your operating system or calling program or you giving it arguments from the command line. If you’ve ever had to work in the command line and had to give it arguments via a dash or slash, that’s why args is for. Each argument passed into the program if there are any will be an entry in the array.

The using statements up the top are how you tell it to use bits of libraries via their namespace. Libraries are bits of code and functionality already made for you by someone else so you don’t have to solve a certain task and can focus on the particulars of your problem. You are using Console from System. You can see there is a namespace for your program given by the IDE. You can change it if you want.

Finally, in C#, everything is done in a class, even the beginning Main method. We’ll get more into classes later, but just note for now, that they are a wonderful way to group data and behavior. In this case, right now you have behavior that can have data passed into it. Data and behavior are the essence of a program. Languages just structure how you communicate those things to the computer even machine language, but that’s a story for another day when you wish to be elite like Zero Cool and Acid Burn from the movie Hackers.

Variables and Data Types

Variables are how a program references data. At the core, your computer just has a bunch of chips with addresses for some type of flip flop (a circuit that stores a bit). An address can get to several bits at a time based on how the chips are wired. Further details would be for an electronics course which I’d recommend.

In a high-level language like C#, you don’t have to worry about numerical addresses for the most part. You just have to have a variable name such as PersonName that is of some type that you can put information into and get it later.

There are several types of variables for different types of data, there is lifetime to your data, scope, which means where and how it is accessed, and later on we will get into some of the new ways you can declare variables such as using dynamic which is very flexible and more like JavaScript’s variables.
For now, we will just focus on different types, so we are going to stay in the Main method for examples of declaration. Later examples when we talk about the other constructs will show you scope.

At its core, variables are just the programmer telling the computer they want to allocate some space in memory to store values. The type of the variable gives an indication as to how much and what types of values can be stored.

Here’s an example with some of the primitive data types. Once you get more of C# programming under your belt, you will learn how to make your own and learn how to use those from all the wonderful libraries available to you.

Here are some examples you can use to see how to declare in initialize the variables with data. Declaration is always the type and name, and initializing and assignment are done with the equals operator.

staticvoid Main(string[] args)
{
/*character. In C#, can put UTF-16 characters.
This is a multiline comment*/
char firstNameStartLetter =‘S’;
//string of characters. In C# always denoted by double quotes
string britishStyleQuestion = ““What’s all this then?”;
//32 bit signed integer
int howManyCatsIHave = 2;
//64 bit signed integer with scientific
//notation that has been casted to a long
//since it normally is a double
long microbeCount = (long)10e12;
//unsgined integer types
ulong volts = 12;
uint pressure = 99;
//8 bit unsigned inititalized with hex (base 16) for 15
byte level = 0xF;
//signed byte with octal (base 8)
sbyte signedLevel = -3;
//true and false
bool arePotatoesGood = true;
//64 bit floating point
double piSlices = 3.9;
//32 bit floating point
//f at the end makes it float rather than double
float sandwiches = 2.5f;
//128 bit high precision decimal good for money
//The M at the end is necessary to tell the compiler
//that the value is a decimal rather than a double
decimal billGatesMoney = 50000000000.001M;
Console.WriteLine(firstNameStartLetter);
Console.WriteLine(billGatesMoney);
//printout whatever you want.
//The WriteLine will get the string of it
Console.ReadLine();
}

This is an updated Main method where you can play with values and see examples of literal values you can put in. The basic pattern here a type for the variable and a name, followed by some initialization. You can however split up the declaration and initialization like so:

double applePounds;
applePounds = 9;
Console.WriteLine($”You bought {applePounds} pounds of apples” );

Also, in this example, I’ve shown you how to substitute a value in a variable into a string. For that to work, the dollar sign at the front is important. More on that later.
The main thing to remember is that you have to have values to be able to work with.
Also, important, the keywords of C# cannot be used as variable names. Variable names cannot begin with numbers, but they can begin with an underscore or letter. The only characters allowed are letters, numbers, and underscores.

A nice exception is that if you begin with an at symbol, you can get around using the character sequence that is the same as some keyword. It can be useful if you programming domain, the task at hand, has words the same as some keyword. An example that comes to mind is where Biology’s classification types have Domain, Kingdom, Phylum, Class and so on. Since class is a keyword, and if you need that with the same capitalization use @class = “Mammalia” for instance if you are say programming about cats, humans, or a sci-fi creature like a thundercat.

As a side note, as a programmer, your job will not only be to know programming, but it will be to know what you are programming towards. We call this a domain. You will often talk with a domain expert to get a description of what you need. Programming is a job that can push you towards the Renaissance ideal if you let it. As a programmer, you should be a voracious reader. That’s the soapbox for the day.

Operators

You are given several operators in C# that allow you to concisely express many arithmetic and logic functions. Operators like plus, take operands. How many they take varies, but most of them take two, so they are called binary. Unary is for describing one operand, and three is ternary.

For binary operators, such as plus, lhs (left hand side) and rhs (right hand side) will be used for brevity throughout this text. Some take only one operand like not.

Here are some examples of arithmetic and Boolean expressions:

//Arithmetic
int addWork = 7 + 9;
double minusWork = Math.PI – Math.E;
double timesWork = minusWork * 9001;
double divideWork = 10e7 / 0.01;
//this will be 2 and is only valid for integers
int remainder = 10 % 8;
//putting it together using parens for order
double result = (7 + 9 * minusWork) / (divideWork – remainder);
//Comparison and boolean
//Comparison
/*Here I’m setting bools equal
to what’s returned from some operator
but if course the sinle equals is setting
and not comparison
*/

bool isEqual = (9 == 9);
bool isNotEqal = (10 != 9);
bool greater = 10 > 9;
bool less = 9 < 10;
bool geaterOrEqual = 10 >= 0;
bool lessOrEqual = -5 <= -5;//Boolean arithmetic
bool andOp = true&&true;
bool orOp = true || false;
bool noOp = !isEqual;
//xor is same bitwise as well as logical
bool xorOp = andOp ^ orOp;
//boolean bitwise
int a = 5 & 8;
int b = a | 9;
//not is same for logical and bitwise

Later you will learn how to make operators work for your own types.

The first are basic arithmetic operators that follow the same order of operations including with using parenthesis. Any other math operations such as trig and powers are in the Math library which will be a later topic.

Comparison operators is used to test for equality or inequality and less than or greater than. Any nots in any of these is done with the exclamation mark also known as the bang.

Boolean arithmetic is used to deal with true and false as strict types. Some languages such as C and C++ don’t really have a separate bool type but use integers and a few other arcane rules. C# breaks with this. If you want to do bitwise operations on types that aren’t strict bools (everything is a string of ones and zeros at the lowest programming layer) you use single ampersand and single pipe.

Double ampersand and double pipe are for strict bools and add the optimization where they are short circuited to not evaluate one side of the expression if the lhs evaluates to a value where further evaluation will not change the outcome. Case in point, with and, both have to be inputs must be true in order to have an output of true, so if the lhs is false, there is no need to evaluate the rhs since the entire expression will be false.

Here’s the differences between a bitwise vs a logical operator. The first only applies to “AND” and “OR”, is that logical ones are double so && vs &. The rest can be used in both cases. The second is in how they are applied to types. A bool is a simple true or false, while other types are arrays of true/false, ones and zeros. So let’s say you had 2 nibbles (4 bit field). I.e.

1001 & 1101 = 1001 and 1001 | 1101 = 1101

Not and exclusive or don’t really have this property, so for both bitwise and Boolean you use the bang and carrot respectively on both bool types and integers.

Control Statements

In this chapter, you will look at flow control statements. These are constructs in C# that allow you to change the direction of the flow of your program. There are a handful of ways in which you can code them, but at their heart, there are two ways you change the flow.

The first is called branching. It allows the programmer to tell the machine how to make decisions. Such as if a customer likes geology books, then recommend to him or her titles from a database on geology.
The second is looping. There will be many times when you need to do the same action over and over based on some condition like getting a total of how much money all subsidiaries of a pizza joint you own made. A loop will go through some data and add it up.

The first to be examined is branching.

if-else statements

The first and most common way to handle branching is the if-else statement. In this text, to display branching operations, after a few examples showing the combinations, to put it all together, we will use a scenario to build the example around eligibility of holding offices in the United States which is a good example of using domain knowledge to program towards a desired result. After the chapter is over, it is left to the student an exercise to incorporate the rules of other countries to develop a more general and international program. This exercise will help the student get used to researching a domain and learning to be as general as possible in their approach to produce maximally useful products.

All of these code samples can be run in the main method, so to save space, only theif statements will be in the examples.

In this first example, let’s say you wanted to compare an incoming score with a highest score. If the incoming one was indeed higher, you should print it out.

int highestScore = 10000;
int incommingscore = 10;
if (incommingscore > highestScore)
{
Console.WriteLine(“You beat the highest score”);
}
Console.ReadLine();

For now, we are using hardcoded examples, but the data could come from anywhere, but most of what the industry calls business logic would be the same. Business logic is all about the rules of the domain rather than how items are displayed or stored.

For this first example, there is a lone if. That is the bare minimum in terms of having if and else. Notice there is code between curly braces. Anything in the curly braces is executed only if the Boolean condition in the if’s parenthesis evaluates to true. As you learned in the last chapter, comparison operators evaluate to a Boolean.

In this example, the condition is false, and nothing will be printed to your console. However, if you change either of those values to something that would evaluate to true and rerun the program, you will see “You beat the highest score” on the console.

This is what flow control does. It allows you to conditionally execute pieces of code. Those pieces of code are grouped in the curly braces. The only exception is that you can omit the curly braces if you have just one line. Some people do this and some don’t but it’s important to know if you come across it. All examples here will keep the curly braces for consistency.
Next, we need to be able to provide alternatives to the condition.

int highestScore = 10000;
int incommingscore = 10;
if (incommingscore > highestScore)
{
Console.WriteLine(“You beat the highest score.”);
}
elseif (incommingscore == highestScore)
{
Console.WriteLine(“You matched the highest score. Try harder.”);
}
else
{
Console.WriteLine(“You fell short of the highest score.”);
}
Console.ReadLine();

If you example the indentation you can see why if, else if, and else statements are called branching. The first branch is always an if. The last if there is more than one branch is either and else or an else if. If there is an else, it must be last. It’s what happens if none of the other conditions are true. It gets no conditional. Any conditionals between if and else are all else if. Any deviation from this syntax is a compiler error. There can be no lone else statements, no else if without a first if, and no else if after the last if.

It’s important to remember that only one branch can execute. You have to be careful when designing your conditions. A good way to test your ability in this is the fizzbuzz problem which will be introduced later in the chapter since it also needs a loop. The main thing that trips up people is putting conditionals that branch in one direction when another direction would be been correct.

In the U.S. office scenario, I’ll point out this possible pitfall and where it can go wrong. When running the code, remember that we aren’t error checking just yet. That is for another chapter, so it is important to be careful to input only valid values so the program doesn’t crash. For instance, the age is a signed integer of 32 bits, so the string you input for age into the console must be something that can be parsed into an int.

Problem at hand: Determine if a person is eligible to be president of the United States, can run for Senate, and the House of Representatives.
Here we will only focus on the age and the citizenship requirements.

Presidency is at least 35 years of age and being born in the U.S. Senate is 30 years of age, and the house of Representatives is 25. Neither of which require being born in the U.S.

string countryOfBirth;
int age;
Console.WriteLine(“Where were you born?”);
countryOfBirth = Console.ReadLine();
Console.WriteLine(“How old are you?”);
age = int.Parse(Console.ReadLine());
if (age >= 35)
{
if (countryOfBirth == “United States”)
{
Console.WriteLine(“Congratulations. You can be the”);
Console.WriteLine(“President of the United States as well as serve in”);
Console.WriteLine(“both Houses.”);
}
else
{
Console.WriteLine(“No presidency for you.”);
Console.WriteLine(“But you can be in the House or Senate.”);
}
}
elseif (age >= 30)
{
Console.WriteLine(“No presidency for you.”);
Console.WriteLine(“But you can be in the House or Senate.”);
}
elseif (age >= 25)
{
Console.WriteLine(“You can be a Representative”);
}
else
{
Consolee.WriteLine(“No congress or presidency for you!”);
}
Console.ReadLine();

There are two things not yet introduced. The first is using the ReadLine() method from the console. This allows you to read a line of text typed into the console. It will output the text which can then be assigned to a variable as seen with countryOfBirth. It can also be passed into another method, in this case int.Parse(). That method is used to turn text into an integer and will be useful for practicing if and else statements. There is a corresponding Parse method for many of the types introduced in the first chapter and is left as an exercise to the aspiring student.

As can be seen here, you can nest if else statements. There can be branches within branches based upon the decisions that need to be made. In this case, a person can be old enough to be the United States president, but unless an amendment is made, their being born say in Austria or Indonesia will disqualify them.

As with most programming languages, in C#, there is more than one tackle a task. In this case, an alternative approach is to use a more complex Boolean expression like the following:

if (age >= 35 && countryOfBirth == “United States”)
{
Console.WriteLine(“Congratulations. You can be the”);
Console.WriteLine(“President of the United States as well”);
Console.WriteLine(” as serve in both Houses”);
}

How you handle if else statements is really going to be a matter of the domain requirements. This is why it’s always good to practice. Come up with several practical scenarios as an exercise or at least make an international version of this and test the results.

The two biggest pitfalls of if else statements are putting the conditions from different ifs and else ifs out of order, and the second is logic errors in the conditionals themselves. A full course in Boolean logic is beyond the scope of this text, but knowing what you know from the first chapter is enough to get started.

The first problem centers on a conditional that may catch something it wasn’t meant to. In this example, if age >= 25 had been put first and then age >= 35 second, then the lines congratulating for presidency wouldn’t have been reached since the conditional for the Senate would evaluate to true first.
For you to learn Boolean algebra, look to the publications for further information. Also, again, practicing with different scenarios is the best way to really learn the topic at hand.

Switch Statements

Another way to use branching is to use a switch statement. Switch statements allow you to streamline branch comparisons by only using one, and that is equality and only for a very limited set of types like the numerical types and strings. This is useful in menu selections as will be shown.

string sauceSelection = “Apple”
;
switch
(sauceSelection)
{
case“Apple”:
Console.WriteLine(“Adding Apple Sauce”);
break;
case“Tomato”:
Console.WriteLine(“Adding Tomato Sauce”);
break;
case“Alfredo”:
Console.WriteLine(“Adding Alfredo Sauce”);
break;
default:
Console.WriteLine(“Unknown Sauce”);
break;
}

The switch statement has a switch, and inside the parenthesis is some value. Here we have Alfredo, but it could come from a textbox in an ASP.NET web page.
Then there are case statements inside curly braces. These are always constant values such as a string or numerical literal followed by a colon. The standard is to then put a tab before the code following and the break keyword.

The default is what happens when the value inside the switch’s parenthesis isn’t not given a case.
The break keyword is a bit different here than in the proceeding sections. If left off on a case, then the code in the next case will execute. This is sometimes intended such as if two menu selections will need the same code to execute. For instance, if you leave off the break in the Tomato case, then the console will print “Adding Tomato Sauce” and then it will print Adding Alfredo Sauce.”

For loop

The next bit of syntax that allows the programmer to control the flow of the program is the loop. Loops allow you to do the same operation a number of times. This example below uses a hard-coded value, but in later examples you will see that it often comes from values that are grouped together as in the chapter on arrays and the chapter on collections where several pieces of data are grouped together.

For loop

The next bit of syntax that allows the programmer to control the flow of the program is the loop. Loops allow you to do the same operation a number of times. This example below uses a hard-coded value, but in later examples you will see that it often comes from values that are grouped together as in the chapter on arrays and the chapter on collections where several pieces of data are grouped together.

int howManyBooks = 10;
for (int i = 0; i < howManyBooks; i++)
{
Console.WriteLine($”Prining book number {i}
);
}

The syntax is simple. You will always have a for keyword followed by three arguments in the parenthesis. The first only ever happens once, that being a variable initialization. The second will execute each go around. It’s a Boolean expression, but it’s most commonly going to be a numerical comparison. You’ll see this later when we get into arrays and collections where the variable counter is compared to the length of some non-scalar (taken from math where a vector is a structure much like a complex or hyper complex and often has more than one numerical component. So, an int is a scalar.)

Lastly, there is a bit of code to update the counter. This is most commonly going to be the post fix incrementor discussed in chapter one. In this case as i keeps increasing by one, it gets closer and closer to the value of howManyBooks. Once i is 10, then i < howManyBooks is false and then the flow of execution jumps to after the for loop’s curly braces.

Of note, the counter updater and the right Boolean expression can count backwards or count by twos, or even use a trig expression if the domain is right. In addition, all the bits of code between the semi colons can be omitted in any combination and be put elsewhere in the program. This can be useful for instance say the counter is defined elsewhere because of information being available in the code above. You can also just set the variable to some number while declaring it elsewhere.

There are also times when updating the counter needs more than one line and can be done inside the for loop. The flexibility is endless.
Finally, if you omit it all together like this:

for (;;)
{
Console.WriteLine(“This line will be printed until the program is closed”);
}

What you will get is an infinite loop unless you break out of it. That will be discussed below on the section about the break keyword.

While loop

The next loop to consider is the while loop. While a counter can be added to it, its main purposes is to use a Boolean expression rather than keep up with a numerical value in order to determine if its body is to execute.

An example usage for what you have learned so far is to loop until a user inputs a correct value into the console.

bool keepPrompting = true;
while (keepPrompting)
{
Console.WriteLine(“Are we there papa?”);
if (Console.ReadLine() == “yes”)
{
keepPrompting = false
;
}
}

Here, the kid keeps asking his father if they have arrived at their intended destination. If the answer from the console is yes,then keepPromting is set to false, and the condition in the while keeps it from asking again. Any other answer will keep the condition true, and the code inside the while loop will keep executing.

bool keepPrompting = true;
while (keepPrompting)
{
Console.WriteLine(“Are we there papa?”);
keepPrompting =!(Console.ReadLine() == “yes”);
}

Also of note here is that you can nest all the things you learn in this chapter inside each other to fine tune the flow control. How it’s been done here though can be streamlined as shown below:

This example shows you some more Boolean algebra and how to use it to make short work of your problem. Even better would to use the not equals operator, but this was just to show the beginning student nesting, parenthesis and operator calls all in one. Flexibility is one of C# many strong points.

Do while loop

The next loop to consider is the while loop. While a counter can be added to it, its main purposes is to use a Boolean expression rather than keep up with a numerical value in order to determine if its body is to execute.

An example usage for what you have learned so far is to loop until a user inputs a correct value into the console.

bool keepPrompting = true
;
while
(keepPrompting)
{
Console.WriteLine(“Are we there papa?”);
if (Console.ReadLine() == “yes”)
{
keepPrompting = false;
}
}

Here, the kid keeps asking his father if they have arrived at their intended destination. If the answer from the console is yes, then keepPromting is set to false, and the condition in the while keeps it from asking again. Any other answer will keep the condition true, and the code inside the while loop will keep executing.

bool keepPrompting = true;
while (keepPrompting)
{
Console.WriteLine(“Are we there papa?”);
keepPrompting =!(Console.ReadLine() == “yes”);
}

Break

There are times during a loop when continuing in the loop shouldn’t happen at all. That is where the break keyword comes in.

In addition, as discussed above, it manipulates how the selection the switches. Except for switches, breaks should be used sparingly. Breaks should only be used in loops when there is no other way to use the condition in the loop to get out of the loop. Here is an example:

As you see here, the input is compared to a string literal of “stop” first. If it is stop, then it breaks out of the infinite loop, else it will attempt to parse the string into an integer. Assuming no bad input, which will be covered in the topic on try catches, then this will keep adding the integer to the sum.
Again, the rule of thumb is to not use them, but as always, the problem domain will dictate what practices should be followed and how closely.

Continue

Like break, the continue is another keyword that allows some manipulation of the flow inside a loop, but instead of exiting the loop entirely, it simply skips any of the loop body code beneath and continues execution the next stage of the loop.

int sum = 0;
while (true)
{
Console.WriteLine(“Type in a number to add.”);
Console.WriteLine(“Type stop to stop and see the sum”);
string input = Console.ReadLine();
if (input == “stop”)
{
break;
}
elseif (input == “oops”)
{
continue;
}
sum += int.Parse(input);
}
Console.WriteLine(($”The sum is {sum});

This example modifies the previous. The “oops” option simulates making a mistake and then tells the loop to continue looping and asking the same question until stop is entered into the console. This example also shows how these different statements can be mixed together to get the desired result.

This example could be written without continue and break by introducing a Boolean expression that is manipulated inside some if else statements. It is left to the student as a practice exercise.

An example with the for loop:

for (int i = 0; i < 10; i++)
{
Console.WriteLine($”{i});
if (i % 3 == 0)
{
continue;
}
Console.WriteLine($”{i});
}

In this example, numbers 0 to 9 are printed twice except numbers that are divisible by 3 which are printed only once.

Now that you have branching and loops in your toolkit, you should be able to tackle the fizzbuzz problem. The goal is to go through numbers 1 to 100 and use divisibility to print out fizz if a given number in the range is divisible by 3, buzz if divisible by 5, and then fizzbuzz if it is divisible by 3 and 5. Note that only one of those three should be printed if one of those conditions is true. Use the console to printout either fizz, buzz, fizzbuzz, or the number, but never all four or any combination. This exercise comes up often in job interviews, so it’s best to go ahead and try it.

Goto

Rarely if ever usedis thegoto statement. This is included for completeness, but just know that it is very frowned upon as one of the worst programming practices. The goto keyword allows a jump to a place with a label as seen in the example:

int sum = 0;
while (true)
{
Console.WriteLine(“Type in a number to add.”);
Console.WriteLine(“Type stop to stop and see the sum”);
string input = Console.ReadLine();
if (input == “stop”)
{
goto StopLabel;
}
sum += int.Parse(input);
}
StopLabel:
Console.WriteLine($”The sum is {sum});

Once again, never do this. Most of the time, using if else, loops, and the right method calls (covered later) should cover almost all the cases needed for controlling the flow of the program.

In this example, the label is StopLabel followed by the colon. When goto is reached, the label is a reference in where to go.

Comments

The compiler takes some very English like statements that are very ridged in their syntax, but sometimes, an explanation for why the programmer wrote what they did is needed. That’s where comments come in.

Comments aren’t read by the compiler. Nothing about them makes it into the machine language or as with C# the intermediate language. Comments are optional, but they should still be used in all but the simplest programs since very often programs can become long, and even with the best coding practices that make code clear, an explanation is still welcome especially if you have to make corrections to it at four in the morning. Comments are clues to yourself and other programmers.

As a side note, comments can be written in whatever language your team is most comfortable as long as Visual Studio can understand the character set. So, if your team has people from Spain, Mexico, and Argentina, the comments can be in Spanish. If it’s just your own work, use whatever works for you. Just know that if you plan to release it later to the public, use English since it’s spoken by a wide audience and has a large technical vocabulary just as centuries ago Latin was used as an international and academic language and not that long ago it was very common to need to learn German and French to read academic writing. Proficiency in English will open a wide world.

There are three types of comments in C#. The first two are comments that are for any place in the code that needs clarification. The last one allows documentation that can be used by a library that will help Visual Studio give helpful hints with intellisense which is what allows Visual Studio to autocomplete code and make helpful suggestions.

The first type is a single line. It is always delimited by two forward slashes. The example below will contain some Unicode characters to demonstrate its ability to handle many character sets. This example has an Egyptian hieroglyph, the umlaut over the u, some Chinese and some Hebrew characters just to show it can be done. It even changes from left to right to right to left when characters from a language like Hebrew or Arabic are used.

//Single line comment 𓆐 Ü大家אש

The next is a multi-line comment. While the single line can be repeated for a multiline can suffice, if something like a paragraph needs to be written. It’s any text between a /* and a */ as shown below:


/*
This is a multiline comment
about how useful the modulus
operator is in some problems.
*/

The last type will be covered in detail for the features it makes since with. Anytime you put three forward slashes into visual studio over some of the features that will be covered in the coming chapters, it will help you generate what are called xml comments. As stated these are documentation of code rather like the other two which aren’t always as structured and could be likened to an internal memo and are used anywhere there is code. As each feature is gone over in the subsequent chapters, if an xml comment is appropriate, and example will be given.

Arrays

Arrays are types where instead of a single value such as an int a = 3, you can group several of the same types of values together. An example would be the grades of a class room. It would be unwieldy to make a new variable for each grade. It would also be award to try to reference all of them. For the first example, assume for brevity a class with at most five students.

double[] grades = newdouble[5];
grades[0] = 100;
grades[1] = 67;
grades[2] = 110.01;
grades[3] = 90.8;
grades[4] = 77.2;
double gradeFour = grades[4];

In this example notice that the type is declared in a similar way to the types you were introduced to in chapter 1, but now to make it an array type, square brackets are added. Also, now that when declaring a new array, how many elements of the array is declared inside the second set of square brackets.

The brackets also allow access into the array’s data. If it is on the lhs, then it is assignment, and on the rhs, access in the data. Also most important to note is that counting elements in an array begins at zero. This is because an array under the hood is an memory location with an offset. Let’s say the zeroth grade is at memory location 10. Then the first one would be at grade 10 + 8 since a double takes 8 bytes. Then the next one would be location 10 + 2 * 8. Starting with zero makes the algorithm for getting to any location simpler.
If you try to go outside of the bounds of the array either by a negative number or by in this case trying grades[5], you will get in IndexOutOfBoundsExeption.

The above isn’t to terribly useful. Often, a loop as discussed in the previous chapter is used to go through an array and do something useful with it. Having to average numbers in is very common, so try this code out:

double sum = 0;
double[] grades = newdouble[5];
grades[0] = 100;
grades[1] = 67;
grades[2] = 110.01;
grades[3] = 90.8;
grades[4] = 77.2;
for (int i = 0; i < grades.Length; i++) {
sum += grades[i];
}
double average = sum / (double)grades.Length;
Console.WriteLine($”Average = {average});

Here, once again, we are using hardcoded values for the input. In production code though, you will most likely get this from a database, a file, or some user input. The main lesson from this though is accessing via variable. In this case, it’s a counter. It starts at zero and then ends when i is equal to 5. Once that is true, the condition i < grades.Length is false and the body of the loop will no longer execute.

Arrays to Functions

Earlier, you went over methods. Methods can take zero or more parameters including arrays or any type. There is a keyword, params, that allows arrays to be passed without making an array and passing it in. Rather, when an array in the method signature follows the params keyword, when calling the method, all that is needed is the values separted by commas as if you had a method with several different signatures.

Console.WriteLine() and string.Format() are two methods from System that can take unlimited arguments.

There are two caveats. One is that a params parameter has to be the last, and two is that it can be the only one. Here is an example of the average function that takes a person’s name and gives a personalized result:

publicstaticvoid GivePersonAverage(string name, paramsdouble[] data)
{
double sum = 0;
for (int i = 0; i < data.Length; i++)
{
sum += data[i];
}
double average = sum / data.Length;
Console.WriteLine($”{name}, your average is {average});
}

Then, inside main add this:

GivePersonAverage(“Gunter”, newdouble[] { 100, 110, 99, 86 });
GivePersonAverage(“Alina”, 200, 200, 0, 45);
Console.ReadLine();

`If you run this, you should get this :

The only difference of note here is that the array argument is modified by a params and that when calling the method, you can but don’t have to use the array syntax, and how many values you can put in there is limited by memory.

Multidimensional arrays

Multidimensional arrays are arrays of arrays. These can be useful when you need an array of several arrays that are the same size. A two-dimensional array for instance could hold several classes worth of grades. They can also be used in mathematical structures such as matrices. Here is an example of a two-dimensional array followed by a three dimensional one. Further dimensions are possible, but it can soon become unwieldy.

The following example shows how to initialize the 2D using the newer array litteral, and the 3D one shows how you can initialize it the old way using brackets. Under each initialization is a set of nested for loops showing how to access the values by printing them.

int[,] twoDIntArray = newint[,] {
{20, 9 },
{2, 5 },
{-9, 0 }
};
for (int i = 0; i < twoDIntArray.GetLength(0); i++)
{
for (int j = 0; j < twoDIntArray.GetLength(1); j++)
{
Console.WriteLine($”Potition ({i},{j}) is {twoDIntArray[i,j]});
}
}double[,,] threeDDoubleArray = newdouble[2, 2, 3];threeDDoubleArray[0, 1, 1] = 55.6;
//rest are automatically initialized to zero for brevityfor (int i = 0; i < threeDDoubleArray.GetLength(0); i++)
{
for (int j = 0; j < threeDDoubleArray.GetLength(1); j++)
{
for (int k = 0; k < threeDDoubleArray.GetLength(2); k++)
{
Console.WriteLine(($”Potition ({i},{j},{k}) is {threeDDoubleArray[i,j,k]}”);
}
}
}
Console.ReadLine();

Note that for a multidimensional array, you have the size of each dimension inside the square brackets as before but separated by commas. Each new comma and then integer represents a new dimension.

If you run this, this is what you see:

Each loop will go through a dimension, and the loop inside will loop through another dimension while inside the one before. As you can see with the three-dimensional array, it stayed in dimension zero while looping through number one which didn’t change until dimension two was finished.

Also, note that again accessing is much like defining. You use the square brackets and specify numbers like they are coordinates. Like with one dimensional arrays, going beyond how many elements there are in any of the dimensions will result in an exception being thrown. Exceptions will be discussed in a later chapter, but for now, know that they are errors that if not handled will crash your program.

The last thing to take note of is the change in how the GetLength method is used. With one dimensional arrays, it can be understood that you are referring to dimension zero (since most things in C# start with zero). When you have two or more dimensions, it needs to be specified which dimension you want the length of.

As an addendum, here is a common convention that came from mathematics when dealing with complex numbers and vectors. It’s common to see dimension one, two, and three labeled as i, j, and k respectively in the loops. However, if this doesn’t make sense and the dimension has a specific purpose, use that to name your counter variable.

Jagged Arrays

Jagged Arrays are a type of multidimensional array where each internal array can be a different length. You can think of for instance a two-dimensional jagged array as being a matrix where the rows don’t have to be the same length. The same will hold true for any higher dimension.

In the third dimension, you could visualize a regular three-dimensional array as a cuboid version of the Death Start from Star Wars in a finished state, and a jagged version as the unfinished version where chunks are missing.

Here is an example of a jagged array, initializing it, and then accessing its values:

int[][] jagged2DIntArray = newint[][] { newint[] {2, 3, 4 }, newint[] {4, 5 } };
for (int i = 0; i < jagged2DIntArray.Length; i++)
{
for (int j = 0; j < jagged2DIntArray[i].Length; j++)
{
Console.WriteLine($”Jagged array at {i},{j} is {jagged2DIntArray[i][j]});
}
}
Console.ReadLine();

You can see that instead of commas that separate dimensions, you have a series of square brackets next to each other. The same is true of accessing.

Here is what you should get as output:

Objects and Classes

In this chapter, you will learn the main paradigm that C# uses. Paradigm is really just a fancy way of saying way of thought. Each language you learn will shape the way you think about a problem because the all have different ways of expressing intent either to the computer or person. Most languages have ways of expressing more than one paradigm, but how easy it is to express can vary wildly. JavaScript for example has a less than pleasing object oriented system while C#’s object oriented programming is first rate.

For C#, the first paradigm to master is object oriented programming. This is where data is grouped together as a type and can be given behavior in the form of methods. Even the very basic types in C# like chars, bools, and the numeric types are objects. This is unlike other languages like Java where the primitive value types don’t behave as objects. C#’s take allows for consistent programming. Later, you will learn about classes inheriting from each other for code reuse. For now, know that everything ultimately inherits from object.

For the first example, we’ll consider a class about candy. First, right click on the project Console Application1, then select the Add > Class.

After you click on class, the following dialog will pop up allowing you to add a new class:

Type in Candy.cs as shown in the picture above. Once you click the Add button, it will give you a new class. The code below is how it is to be modified for the example :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication1
{
publicclassCandy
{
publicstring candyName;
publicdecimal costPerGram;
publicdouble gramsBought;
privatebool isOnReorder;publicdecimal CalculateTotalCost()
{
return (decimal)gramsBought * costPerGram;
}publicoverridestring ToString()
{
returnbase.ToString();
}
}
}

Here is some code from the main method in order to show that data and methods being used:

Candy candy = newCandy();
Candy.candyName = “Good stuff”;
candy.costPerGram = 20;
candy.gramsBought = 10;
Console.WriteLine($”{candy.candyName} total paid {candy.CalculateTotalCost()});

Here is the output:

In this example, there is some data that describes the candy. Then there are methods to give it behavior. The data members are how a class can keep a state about what it is modeling. The methods are how actions can be performed by the object instantiated.

The next thing to note is that the class keyword is modified by what is called an accessor. In this case, it is public which means anything anywhere that is using ConsoleApplication1 or in the same namespace can use it. Access modifiers also apply to data inside the class and its behavior.

Here’s a table of the accessor modifier.

Some of these will be explained in Chapter 6 when inheritance is covered. For now, just know that classes can be made and extended other classes, and the access modifiers simply allow the programmer to specify what’s available to what is using the class.

It’s important also to note that a class can only be private if it’s inside another class. Classes can be nested indefinitely, and it often makes sense to have a class use some other internal data structure that cannot be used elsewhere. You simply access say a private nested class by calling the dot operator on the containing class just like when accessing a static function from the math class.

Here’s an example of instantiating a couple of candy objects and using the class in the main method to change data members and call methods on a candy object.

Candy chocolate = newCandy();
chocolate.candyName = “chocolate”;
chocolate.costPerGram = 0.05M;
chocolate.gramsBought = Math.PI;
Candy creamCheeseTort = newCandy();
creamCheeseTort.candyName = “Cream Choose Goodness”;
creamCheeseTort.costPerGram = 10;
creamCheeseTort.gramsBought = 22;
Console.WriteLine($”{chocolate.CalculateTotalCost():C});
Console.WriteLine($”{creamCheeseTort.CalculateTotalCost():C});
Console.ReadLine();

Here is what should be printed when you execute this in the main method:

As you see we use the class name followed by a variable name, followed by an initialization. Only then can the data members be used by assigning data and accessing them from the object. You won’t get to formatting of strings until the chapter on strings, but just know that the colon followed by an upper-case C formatted the value to currency. On this machine, that’s United States dollars, but it will vary by the locality set on the executing machine.

In short main concept to remember about object oriented programming is that the object is an instance of a class. A class defines what types of data and what can be called in terms of methods, but each object you make has its own state, just like you can have some idea of what a piece of pie is, but each slice can have its own state like how much has been eaten, its flavor, and if the customer enjoyed it. Later you will learn about static classes and members where state can be shared across all objects. Which you use will depend upon the problem at hand.

Constructors

A constructor is a type of method, but it has no specified return type since it constructs the object and therefore is just returning itself.

So far, when you’ve made an object with the syntax of someVariable = new SomeType(), every time you used those ending parenthesis, you’ve called a default constructor which the compiler gives you out of the box. There are times however when you want to give some initial data to the object. Here, the example will be one constructor with no arguments, and two with varying arguments. This is called overloading. In chapter 7, you will see the same technique applied to methods.

publicclassCandy {
publicstring candyName;
publicdecimal costPerGram;
publicdouble gramsBought;
privatebool isOnReorder;public Candy() {
candyName = “Candy”“;
isOnReorder = true;
}public Candy(string candyName) {
this.candyName = candyName;
}public Candy(string candyName, decimal costPerGram, double gramsBought) {
this.candyName = candyName;
this.costPerGram = costPerGram;
this.gramsBought = gramsBought;
}publicdecimal CalculateTotalCost() {
return (decimal)gramsBought * costPerGram;
}publicoverridestring ToString() {
return$”Name: {candyName}, Cost/Gram: ${costPerGram}, Grams Bought: {gramsBought}g”;
}
}

In this example, ignore the this keyword for now until the section where it will be further explained Just know that whenever you have an argument in an constructor or method the same as the class variables, the way reference the member variables is the this keyword.

For now, notice the access modifier. For most of our examples, it will be public, but it can be different in order to control what can instantiate a class. Often the constructor or constructors will all be private and the class will provide a class level method (explained below in the static section) that makes the new object.

Now in the main method, here is an example of creating the three objects, but each one will call a different constructor.

Candy candyA = newCandy();
Console.WriteLine(candyA.candyName);
Candy candyB = newCandy(“Strawberry Tort”);
Console.WriteLine(candyB.candyName);
Candy candyC = newCandy(candyName: “Pasta Berry”,
costPerGram: 0.7M, gramsBought: 100);
Console.WriteLine($”{candyC.candyName} costs {candyC.CalculateTotalCost()});
Console.ReadLine();

Here is the output:

In the last example, named parameters were used. As with methods, there is the option of adding in the names of the parameters being passed in to make the code clearer.

Once all these objects are instantiated, values that are passed in and any values added to the data members by the constructors will have those values and be ready for use by other bits of code you make that may need such as a restaurant. A restaurant could have an array of candy for its patrons to choose from.

The main thing to remember about constructors is that for a particular object, it’s the first code to run. It’s how you give the object a useable state including default behavior.

Destructors

The destructor is the opposite of a constructor. A constructor is the first bit of code that runs when you make a new object. A destructor runs at the end. This feature isn’t used very often. For the most part, you will be using other types of code to clean up if it’s needed at all.

The reason for code cleanup necessary is because everything that the computer uses is a resource that is finite in its amount. Case in point is memory. In the computer profession, memory is the same thing as RAM. Lay people often confuse it with the hard disk. The hard disk and the files it contains are also another resource. Connections to a remote machine say on the internet or even on your local network are resources, and if you don’t clean up after using them, they will be used up which can slow your machine or at least the program you are writing to a halt.

Memory is taken care of by what’s called the garbage collector. Its internal workings are beyond the scope of this book, but just know that it is used in freeing RAM when no longer being used by the program’s variables. Many languages don’t do this at all and are called unmanaged. Java is entirely managed while C++ and C are not. C# is usually managed unless you choose to do otherwise, and this should be rare.

It’s not quite the same as C++, but the syntax is the same:

~Candy(){
Console.WriteLine(“Candy is no more”);
}

There is no access modifier, just a tilde and the class name followed by the logic to free unmanaged resources. Unmanaged resources are beyond the scope of this book and should be a rare event.

It’s not really that easy to control when this happens, but your best bet to is to call the garbage collector as shown below in the main code.

Candy chocolateCandy = newCandy();
chocolateCandy = null;
GC.Collect();]

As you can see, first the object has to be set to null in order for the garbage collection to happen to it.

This

A very useful keyword when making classes is the this keyword. It’s most helpful when accessing a data member of the class that has the same variable name as shown above when you had constructor parameters that were the same as variables. The same holds true for methods and later when you use properties.

Another use of the this keyword is when reusing constructors in a way that is called chaining constructors. An example will show:

public Candy(): this(“Candy”)
{
isOnReorder = true;
}
public Candy(string candyName)
{
this.candyName = candyName;
}public Candy(string candyName, decimal costPerGram, double gramsBought): this(candyName)
{
this.costPerGram = costPerGram;
this.gramsBought = gramsBought;
}

The test code is the same as before, and here you see the output the same as before:

While this may not seem like a significant code savings, in cases where there may be complex checking and initialization logic, it can be a time saver, and industry practice is also to never have the same logic in more than one place because you may have to change it in one area later on and forget to change it in another place.

Static

The keyword static modifies most any class construct we have covered. In this section, we will go over static variables, properties, and methods, and the next two sections will finish the discussion on using the static keyword.

While C# is primarily about creating and using objects made from classes, there are many times when it makes no sense to create a class to use some data or a method. Case in point is the System.Math class. You can obtain the mathematical constant pi from Math.PI and can access several methods from trigonometry. None of these need a new class to be created.

Static as a modifier will make code like a method or datamember what is called class level. This means that it can be called from the class and it is the same across any objects made if they are made at all (see below).

Here are some examples. The first is a static data member, the next a static property, and the last a static method.

publicclassPie
{
//non static members here
privatestaticbool isOnOrder;
publicstaticbool IsOnOrder {
get
{
return isOnOrder;
}
set
{
isOnOrder = value;
}
}publicstaticvoid PrintOrderStatus()
{
Console.WriteLine($”Order status: {isOnOrder});
}
}

And now here is an example of using them in the main method.

Pie.IsOnOrder = true;
Pie.PrintOrderStatus();
Console.ReadLine();

As you can see, the Pie class can be called without needing to make an object in the main method.

Here is what running the main method will yield:

A final point about static members is that since they are shared by all objects, then any object level code can use them. The reverse is not true, since a static cannot know what class it would be dealing with. So any Pie object can know if it is on order, but the PrintOrderStatus method cannot access members specific to an object such as a cost per gram that is specific to an instance.

Static classes

There are some instances where nothing in a class is ever needed to make an object. Usually these will be utility classes. The best example is the Math class. It has a few constants like Math.E and Maht.PI and some methods for power and trigonometric functions, but none of these ever need an object.

If there is no reason to ever instantiate a class, then you can use the static keyword to modify a class to make it a compiler error to do so.

Here’s a simple static class with a method and data member:

using System;
usingstatic System.Math;namespace ConsoleApplication2
{
publicstaticclassStaticMathUtil
{
publicstaticdouble PiSquared = Math.Pow(Math.PI, 2);publicstaticdouble Tangent(double theta)
{
return Sin(theta) / Cos(theta);
}
}
}

As you can see, the class is marked static, as is the method for calculating the tangent of an angle named theta and the data member PiSquared. A new feature is to put static in the using statement followed by a fully qualified class. This allows calling Sin and Cos without specifying Math as was done on Pow and PI. This can shorten code that has to make lot of calls to static methods as might be common in a highly mathematical program.

Here’s a way to test it in the main method followed by the output:

Console.WriteLine($”Pi^2 {StaticMathUtil.PiSquared});
Console.WriteLine($”Tan(9) = {StaticMathUtil.Tangent(9)});
Console.ReadLine();

Here’s an exercise of a hypothetical math extension Fraction and Complex classes with only method signatures and a fractional Pi for brevity:

publicstaticclassExtendedMath {
publicstaticFraction Pi = … ;
public staticFraction Sin {…}
public staticFraction Cos {…}
}

In this ExtendedMath class, you can see the static keyword placed between the access modifier and class keyword. A completion of this example is left to the reader as an exercise. This exercise will involve researching math. First, make a Fraction class with a numerator and denominator as data members.

Then, research how the sine and cosine functions work, and complete the ExtendedMath class by filling in the method bodies using the mathematical operators you are familiar with, and any of the methods in the Math class except for the trigonometric functions. You may only use those to check your answers, but to use them outright for the method bodies is cheating.

Static constructor

The static constructor is a new feature that adds constructor functionality to a class, but for static members only. It will run only once, and that is when a class is first used. An access modifier is never used.

An example would in the Candy class. Here, we’ll assume that there is a known favorite flavor of Candy that should be accessed statically. It could come from a database, but in this example, we’ll just hardcode it. Ignore the enum for now as that will be explained below.

publicenumCandyTypeEnum { Chocolate, Vanilla, Mint, ButterScotch }
publicstaticCandyTypeEnum FavoriteType;static Candy() {
FavoriteType = CandyTypeEnum.Chocolate;
}

The syntax is simple. Instead of an access modifier, always use static, and of course the class name since it is a constructor. You need never call this in anyway since as stated above, it’s the first bit of code that can ever run if the class is used in anyway.

Now, whenever Candy is used, there will be a known value inside FavoriteType for use across any object.

Here is the code in the main method and an output:

Candy.FavoriteType = Candy.CandyTypeEnum.Chocolate;
Console.WriteLine($”Favorite Flavor: {Candy.FavoriteType});
Console.ReadLine();

Enum

Enums are a type of class useful for defining options, but in what a way that is termed type safe. By this it is meant that instead of an option with some string that could be misspelled and a number can go out of range. Error checking for these types is also often unwieldy.

The enum type solves this by being a list of options which when selected in the code will be popped up by intellisense and keep the options within the intended range. An example will make this clear.

We’ll use the candy example again, but this time, we’ll restrict the types of candy via an enum, use a variable that is of a type of this enum, and then use it when creating a new candy object in order to select the type.

Here’s part of the new class:

publicclassCandy {
publicenumCandyTypeEnum { Chocolate, Vanilla, Mint, ButterScotch }publicstring candyName;
publicdecimal costPerGram;
publicdouble gramsBought;
privatebool isOnReorder;
publiCandyTypeEnum CandyType;

Here’s an example of using it in the main method:
Candy chocolateCandy = newCandy();
chocolateCandy.CandyType = Candy.CandyTypeEnum.Chocolate;
Console.WriteLine($”Favorite Flavor: {chocolateCandy.CandyType}”);
Console.ReadLine();

Here’s an example of using it in the main method:

Candy chocolateCandy = newCandy();
chocolateCandy.CandyType = Candy.CandyTypeEnum.Chocolate;
Console.WriteLine($”Favorite Flavor: {chocolateCandy.CandyType});
Console.ReadLine();

As you can see, enum is a keyword. It looks like you are making a new type, but you’re really making a specialized class. As such, it can be declared outside the Candy class and used without calling the dot operator on Candy to access it; however, convention is to keep it inside the class that it is an option for.

You can now see how this is useful. If a string were used, then it could be easily misspelled, and the compiler wouldn’t catch it. Even if spelling were correct, then there is case to code for. An integer could be used, but then a filter for invalid integers has to be added, and on top of that, and integer is arbitrary for an option.

Enums will pop up in several places such as in graphics where a color is selected and in network programming where an option such as why type of protocol is to be used.

Enums have an additional feature that make them flexible. They can be bitwise ORed in order to produce a hybrid option. Instead of making a MintChocolate option and all the other exponential options, you can set the data this way:

chocolateCandy.CandyType = Candy.CandyTypeEnum.Chocolate | Candy.CandyTypeEnum.Mint;

Then, it can be checked with the familiar syntax this way:

if (CandyType == (CandyTypeEnum.Chocolate | CandyTypeEnum.Mint)) {
Console.WriteLine(“Cholcate and Mint is good together.”);
}

Properties

As often stated, a program is about data and behavior. In many languages, you are given variables that can be data members and then there are methods that can take and return data. In Java, in order to protect data members from getting just any value without checking, methods are used to be getters and setters. This is fine as far as it goes, but C# adds what the industry calls syntactic sugar.

Syntactic sugar is when a construct is added that isn’t strictly necessary, but makes the use of the language more natural. Properties as well as the enums you learned before are syntactic sugar.

Properties are a combination of getter and setter methods with the data type. You use them like a variable in that if you call goodCandy.Weight = 7, but they act like a couple of methods in one in that they can check data coming in and going out.
In this example, you can see that we still have a data type that is referenced by the property. You can also see that that the key words get and set are used, and inside the set, the value keyword is used.
The get section is how you check what is going out. It uses the return key word to send out the value.

The set section is how you filter out what’s going in. What goes in is checked via the value keyword. Its type is whatever type you make the getter setter.
You can omit one or the other of these. If you omit the set, you produce a read-only property. This is useful when for instance you want a value to be set internally, but cannot be set by other code. For example, a student could have a final grade that is set by an internal method and can be read, but shouldn’t be set by code outside.

You can also make a write only property, but this isn’t a common need. As always, choose what’s right for the scenario.

Here is a version of Weight as a property from the candy class along with the data member it is modifying. The first has a getter and a setter, the second is read only, the third is write only .

publicdecimal Weight
{
get
{
if (isOnReorder)
{
return -1;
}
returnthis.weight;
}
set
{
if (value>gt; 0)
{
this.weight = value;
}
}
}
privatedecimal weight;
privatedecimal Weight
{
get
{
returnthis.weight;
}
}
publicdecimal Weight
{
set
{
this.weight = value;
}
}

Here’s an example of using it with both get and set followed by the output:

Candy chocolateCandy = newCandy();
chocolateCandy.Weight = 10;
decimal w = chocolateCandy.Weight;
Console.WriteLine($”Candy Weight: {w});
Console.ReadLine();

As you can see with each example, they all look like methods except they take no parameters. A new keyword, value, is introduced here. The keyword value is how you access what the property is being set to if it can be set. If it is being ready, then the get will return a value in line with its return type.

And of course get and set are also keywords. Each one acts a separate method where you can add some sort of logic to check the values going in and out. This can be useful for security concerns and keeping data consistent with the domain. In this case, for setting the value of weight, it makes no sense to sell a negative or even zero amount of candy.

The other two omit much of the logic for the sake of brevity and just to show that it can be done. The last thing to note is of course the data member bring private. It could be others such as protected to let other classes that inherit (later on that) use it, but if a data member is public, there is nothing to be gained from a property.

Now here is a property without any visible data member:

publicdecimal Weight
{
get; set;
}

This one is a newer feature where if you have only a get and set with no logic in their curly braces and just ended with a semi colon. With this one, you don’t have to come up with a data member since the compiler makes one in the background for you. This is very common in some patterns where you are making a data model with no behavior. Programming patterns are beyond the scope of this text. Here is a code sample.

Inheritance

As far as it goes, what you’ve learned in object oriented programming is very useful, but it’s limited in how you can reuse what you’ve made.

The examples in chapter 4 and extended in chapter 5 showed how the has-a relationship works. Each complex type has some more primitive type as part of its composition. Inheritance on the other hand introduces the is-a relationship.

With inheritance, you have a base class which is also called a parent class, and then a derived or child class. You’ll see in the next chapter why this can be useful in terms of consuming multiple types under one umbrella parent type and being able to fine tune how each type operates.

For now, we’ll have four classes all in the same code file for brevity and to show it can be done. One will be the parent while two are children, and the last is a grandchild.

Always remember that if nothing else, everything ultimately inherits from object. You do this directly, but there is no need. If no base class is specified, the compiler assumes object and acts accordingly.

With these classes, you will see a screen shot of Visual Studio’s intellisense showing members from inherited classes. First the code, then the screen shot.

using System;publicclassFood
{
publicstring foodName;
}publicclassMainEntre : Food
{
publicDateTime timeServed;
}publicclassDessert : Food
{
publicbool hasPeanuts;
publicbool ShouldBeServe(bool hasPeanutAllergies)
{
return hasPeanutAllergies && hasPeanutAllergies;
}
}publicclassCandy : Dessert
{
publicstring candyName;
publicdecimal costPerGram;
publicdouble gramsBought;
privatebool isOnReorder;publicdecimal Weight
{
get; set;
}public Candy(): this(“Candy”)
{
isOnReorder = true;
}public Candy(string candyName)
{
this.candyName = candyName;
}public Candy(string candyName, decimal costPerGram, double gramsBought): this(candyName)
{
this.costPerGram = costPerGram;
this.gramsBought = gramsBought;
}publicdecimal CalculateTotalCost()
{
return (decimal)gramsBought * costPerGram;
}

publicoverridestring ToString()
{
return$”Name: {candyName}, Cost/Gram: ${costPerGram}, Grams Bought: {gramsBought}g”;
}

}

Now here is a screen shot showing that Candy has members from its parent classes:

With object oriented programming, you are free to compose classes out of other ones or inherit from them. This allows for code reuse and for modeling the problem domain to be natural.

Method overloading

Method overloading is another piece of syntactic sugar that programming a lot more natural. With method overloading, you get to have multiple methods with the same name in the same class.

How the compiler tells them apart is by having different arguments. For instance, let’s say you are working on a math library, and each type needs to have an associated sine function as seen here:

publicclassMathUtil
{
publicclassFraction { }
publicclassHyperComplex { }
publicFraction
Sin(Fraction a) { }
publicHyperComplex Sin(HyperComplex a) { }
}

It is left as an exercise on how you might implement a fraction class and hypercomplex, but the main thing to notice in the methods is that they have the same name, but they take different arguments. Based on what you pass in when you are calling MathUtil.Sin is which method will be called. The return type can be the same or different.

Here’s a simple example of it using the basic types you learned in chapter one, but again, do the exercise above as it will teach you the process of problem solving as a whole to do research:

publicstaticint Add(int a, int b)
{
return a + b;
}publicstaticdouble Add(double a, double b)
{
return a + b;
}

Here’s the code to execute in the main method:

Console.WriteLine($”2 + 3 = {Add(2, 3)});
Console.WriteLine($”3.1 + 3.5 = {Add(2.1, 3.5)});
Console.ReadLine();

Here’s the result

Method overriding

Method overriding is different from overloading. With overloading, you are in effect making several methods, just with a different signature, and they could come from both inside the current class or from an inherited class.

Method overriding is when you define in a child class a method with the exact same signature as one of the bases classes. This can be useful since at times a child class needs the same semantics such as method arguments and to output the same type, but still have control over how that method works.

Here’s an example of ToString for the Candy class.

Base

With inheritance comes being able to both use as well as discard old items from the base class. Sometimes doing both is helpful. The example will be the ToString() method and using the classes from the inheritance section.

A derived class may need to make its own ToString, but it might also be useful to call the ToString of the base class to gain its functionality so as to not rewrite code but still also write the custom functionality the derived class needs. That’s where the base keyword comes in. It’s somewhat like the this keyword, but for the base class. Whenever you call the dot operator on base, you will see in visual studio methods, properties, and data members only from the base class.

Here’s the code for the Dessert class:

publicoverridestring ToString()
{
return$”Has Peanuts: {hasPeanuts};
}

Here’s the code from the Candy class.

publicoverridestring ToString()
{
var stringRep = $”Name: {candyName}, Cost/Gram: “ +
$” ${costPerGram}, Grams Bought: {gramsBought}g, {base.ToString()};
return stringRep;
}

Here’s the code from the main method:

Dessert desert1 = newDessert();
Candy candy1 = newCandy();
candy1.candyName = “Butter Studel Tart”;
candy1.costPerGram = 22.89M;
candy1.gramsBought = 1000;
desert1.hasPeanuts = false;
candy1.hasPeanuts = true;
Console.WriteLine(desert1.ToString());
Console.WriteLine(candy1.ToString());
Console.ReadLine();

As you can see, calling base.ToString() called the method from the parent class and was used to add it’s functionality to the child class.

There is one caveat that disappoints many students. You cannot call base on the base class to get to the grandparent class.

Polymorphism

Polymorphism literally means many forms. With polymorphism, you are able to assign objects of a derived type to a variable declared of a parent type. Then, when you call a method that they share, such as ToString on the object, the correct method will be called based upon what the type really is as you can see in the code here:

Dessert desert1 = newDessert();
Candy candy1 = newCandy();
Dessert desert2 = candy1;
candy1.candyName = “Butter Studel Tart”;
candy1.costPerGram = 22.89M;
candy1.gramsBought = 1000;
desert1.hasPeanuts = false;
candy1.hasPeanuts = true;
Console.WriteLine(desert1.ToString());
Console.WriteLine(desert2.ToString());
Console.ReadLine();

This example changed only that there is now a desert2 object that points to an instance of Candy and now the ToString is being called on the desert2. The result will be the same as in the section on method overriding.

This feature is especially useful when you have arrays or lists (arrays that can grow) of some base type that have similar functionality, but one or more of them have overridden the method and all need to be called, but with the correct results.

An example would be a person class that is the base class to several types of people in a company. They each have a method for collecting pay checks, but how that gets done will be different. An array of People objects could loop and call the same method, but the right method would get called upon what the derived type is. Same as with the Candy and Dessert types. Method overriding and Polymorphism go hand in hand.

Sealed

A sealed class is one that doesn’t allow others to inherit from it. This can be useful if you don’t want a developer to abuse your class by taking its functionality, or if it makes no sense to further take functionality to another child class. Consider our example with the food classes.

If you have a really specific class like ChocolatePie that needs no further types derived from it, all you have to do is mark it sealed like this:

Abstract classes

Abstract classes are classes that have functionality, but aren’t meant to be used but only inherited. Taking just the dessert and candy class for example, it makes sense to get a chocolate pie, but if you asked a waiter for just dessert in general, he would be stumped by the vague request.

There are many times when some data and behavior can be had in common, but without further specification make little to no sense as an object. Marking a class as abstract in the class signature will ensure that it cannot be instantiated. This may seem pointless at first, but the key here is that an abstract class is supposed to be inherited. In this case, you can’t make a dessert object, but you can make a pie object, and the class definition of pie inherit from the dessert, thereby reusing the code.

publicabstractclassDessert {
publicstring name;
}publicclassPie : Dessert {
publicdouble radius;
public Pie() {
base.name = “Pie”;
}
}

The syntax for inheritance is the same as before. You can add methods, properties, etc. The difference is that between the access modifier and the class keywords is the abstract keyword.

Now, when you try to make a Dessert class in the main method, you will get an error. As before with polymorphism, you can make a Pie object and assign it to a variable of type Dessert, but a Dessert by itself cannot be instantiated. It is just for code inheritance and polymorphism.

Interfaces

Interfaces are even more abstract in that they define behavior, but not how it is implemented. They are a type of class with nothing but method signatures and the methods aren’t given access modifiers.

Interfaces also allow a way around the limitation of single inheritance. A few languages like C++ allow multiple inheritance. A class can inherit from only one class abstract or concreate, but can inherit from multiple interfaces. This limitation is very common and is usually put in place by the compiler writers to avoid the messes that multiple inheritance can cause when conflicting methods come about.

But, with interfaces, you can inherit several of them and have the same polymorphic effect as is had say with single inheritance. For now, we’ll go back to just the candy, but this time, we’ll have two interfaces that it inherits from. For brevity, they will be in the same codefile, but you can put them all into different files.

Here is the Candy class derived from Dessert, but constructors taken out of the listing for brevity, but they are still there in Visual Studio for the example to run.

publicclassCandy : Dessert, ICandyCalculator, ICandyReviewer
{
publicstring candyName;
publicdecimal costPerGram;
publicdouble gramsBought;
privatebool isOnReorder;publicdecimal Weight
{
get; set;
}publicdecimal CalculateTotalCost()
{
return (decimal)gramsBought * costPerGram;
}publicoverridestring ToString()
{
var stringRep = $”Name: {candyName}, Cost/Gram: “ +
$” ${costPerGram}, Grams Bought: {gramsBought}g, {base.ToString()};
return stringRep;
}publicvoid WriteGoodReview(int timesToWrite)
{
for (int i = 0; i < timesToWrite; i++)
{
Console.WriteLine($”{candyName} taste’s great!”);
}
}
}

Notice that the interfaces use the interface keyword rather than the class keyword. When you go to make a new class, interface is one of the options. Also, note that the industry standard is to begin an interface name with ‘I’ sans the quote marks of course. This is to let other coders know that an interface is being used rather than a syntactic rule.

The syntax rule for inheritance is after the colon, if there is a mixture of interfaces and classes, the class must come first and then the interfaces. All of them are separated by commas. Each interface you add will force the class to implement the functionality the interface has a signature for; otherwise, the code won’t compile.

Here is the code in the main method to test it out followed by the results in the console:

ICandyReviewer candy1 = newCandy();
candy1.WriteGoodReview(3);
Candy candy2 = newCandy();
ICandyCalculator candyCal = candy2;
candy2.candyName = “Butter Studel Tart”;
candy2.costPerGram = 22.89M;
candy2.gramsBought = 1000;
candy2.hasPeanuts = false;
candy2.hasPeanuts = true;
Console.WriteLine(candyCal.CalculateTotalCost());
Console.WriteLine(candyCal.ToString());
Console.ReadLine();

Above is a polymorphic example in the main method to show using the interfaces with the ToString method. Notice that in the result no matter which interface variable ToString is called on, the correct one is called. This behavior is useful when groping in arrays and lists by interface types based on some desired common behavior.

Also note that the data and methods specific to a class have to be called on a variable that is declared of that type and not some base class or interface. Often then you will need to fill in data beforehand and then set a variable of the interface to an instance of the child class.

Namespaces

As you may have noted in some of the examples where all the code was posted, there was a namespace keyword. It had a name and some curly braces that surrounded the class. While not necessary to have, you will almost always have a namespace on everything. Namespaces allow you to add a friendly qualifier under which to place your code. In other words, it allows you to put extra naming and grouping to your code.

Make a new project. For this one, we’re just going with the default name which is ConsoleApplication3 since it’s the third used for all these examples. You will need to add a folder:

Here’s a screen shot of how to add a folder after right clicking on the project:

When the dialog comes up, call it GeometryUtils Now add another one called TrigonometryUtils. Here are a couple of classes. One of them is Trigonometry and the other is Geometry. They are added by right clicking on the folder instead of the project and adding a new class as before:

using System;
usingstatic System.Math;
namespace ConsoleApplication3.GeometryUtils
{
publicstaticclassGeometry
{
publicstaticdouble Distance(double x1, double y1, double x2, double y2)
{
return Sqrt(Pow(x2 – x1, 2) + Pow(y2 – y1, 2));
}
}
}using System;
usingstatic System.Math;
namespace ConsoleApplication3.TrigonometryUtils
{
publicstaticclassTrigonometry
{
publicstaticdouble HaverSine(double thetaRadians)
{
return (1 – Cos(thetaRadians)) / 2;
}
}
}

And to make sure, your project with the folders should end up looking like this:

Here’s Program.cs in order to use them followed by the output:

using System;
usingstatic ConsoleApplication3.GeometryUtils.Geometry;
using ConsoleApplication3.TrigonometryUtils;
namespace ConsoleApplication3
{
classProgram
{
staticvoid Main(string[] args)
{
Console.WriteLine($”Distance between (1,2) and (3,6) is {Distance(1,2,3,6)});
Console.WriteLine($”Haversine of 20 is {Trigonometry.HaverSine(20)});
Console.ReadLine();
}
}
}

As you can see, you’ve made the beginnings of a math library where classes are split up by namespace. As will be shown in reflection later in this text, the namespace is part of a type’s name. Namespaces don’t have to follow what folders they are in. That’s just how visual studio automatically names them when you create a new class inside some folder.

If you nest folders, visual studio will extend the namespace with more dots. You can take those away or even add more dots to further the namespace.

Strings

You saw strings several times in the examples. As you know well know, a string literal is defined by text inside double quotes, and you saw string interpolation.

Strings can use the plus and the plus equals operator:

string aString = “int max” + $”{int.MaxValue};
aString += $” double max: {double.MaxValue};
Console.WriteLine(aString);
Console.ReadLine();

As you can see, the plus and the plus equals do what is called string concatenation which means it adds strings together to form bigger strings. There is a problem though. Doing string manipulation like this, especially if there are several string operations, there is a massive performance hit.

This is because strings are immutable which means that their values cannot be altered. What this means in practice is that once you put data inside a string variable, it points to some location that’s allocated in memory for that string. Once you dump more data into it, it doesn’t just append new data, the computer has to allocate a new place in memory for the whole new string.

There is a way around this. If you have to heavily edit a string, use the StringBuilder class as shown here, but first make sure you are using System.Text where StringBuilder lives:

StringBuilder stringBuilder = newStringBuilder();
for (int i = 1; i < 11; i++)
{
if (i % 2 == 0)
{
stringBuilder.AppendLine($” {i});
}
else
{
stringBuilder.Append(i);
}
}
Console.WriteLine(stringBuilder.ToString());
Console.ReadLine();

Here’s the output:

The object has a couple of methods called on it to append and to append a line, and then finally you can get the string out of it by calling ToString. It’s the best way in the .NET libraries to buffer string data.

Exception Handling

Try/Catch

In the examples you’ve tried in the book, you may have made mistakes when entering in numbers. If you did or didn’t, try this simple example, but instead of entering in a valid integer use some non-inter number or some letters and see what happens:

Console.WriteLine(“Put an int in me.”);
int anInt = int.Parse(Console.ReadLine());
Console.ReadLine();

Here’s what happened in Visual Studio when the string “craznoglitch” was put in it:

This is fine when debugging and then you realize to put a try catch as below, but had this been in production the program would just crash and never say anything to the user who most likely isn’t running it in debug mode with Visual Studio.

Now, here’s what should have been done in order to try an operation and then catch a possible error and the graceful output:

As you can see, the program didn’t crash, and it outputs what’s in the particular catch for the exception. You can have as many catch statements as you need. It will depend on what you are doing that will throw the exception. As discussed below, exceptions are classes, so they follow a hierarchy. You can think of Exception as being analogous to object in that it is the base to them all, but isn’t too terribly useful in and of itself except to be a catch all.

Finally, remember that only one catch will execute if an exception is thrown. As such, it is important to deal with the more specific to the least specific in terms of the object hierarchy.

Finally

Speaking of finally, while a try and catch allows you to attempt an operation and then catch an error, but sometimes you want something to execute regardless if there is an exception thrown or not.

You’ll learn more about streams below, but just know that finally blocks as you’ll see them are very good for streams and any other unmanaged resource that requires you to close and often flush data from. Closing especially since any such resource not closed even if there is an exception will leak computer resources and slow your system. If enough resources are taken up, you can slow the system to a halt or crash that cannot be caught. This is considered rude to your users, so try to avoid it.

In this example, we’ll just use a modification of the above code and then see how it executes under both correct and incorrect input, so there will be two output screens, the first with an actual integer the second not:

try
{
Console.WriteLine(“Put an int in me.”);
int anInt = int.Parse(Console.ReadLine());
}
catch (FormatException ex)
{
Console.WriteLine(“Cannot parse input to int.”);
}
finally
{
Console.WriteLine(“Thanks come again!”);
}
Console.ReadLine();

As you can see, the catch only executed when non integer data was put in in this case, “Super hero sandwich”. The important thing for this example though is that the finally block executed each time no matter what.
As a final note on try catch finally structure before showing you how to make your own exception, the bare minimum is to have a single try, and a single catch. There can be more than one catch, but the try and finally only have one. That being said, like with any of the other constructs you can of course have another try catch following one or more, and you can nest them if it’s necessary.

Custom Exception

Exceptions are classes just like any other except that they are thrown. As classes, they can be inherited and thus extended.

Sometimes you need to make a custom exception that alerts the code of exceptional circumstances that apply only to that domain. Again they are just classes, and like with inheritance and the fact that things need to be caught the most particular to the least particular, it can be a good idea to make your own exception class.

In this example, an algorithm to calculate pi will be used. Now let’s say we don’t want the algorithm to use up too much processor power, so in this example, if too much precision is asked since it is an implementation of a possibly infinite summation, a PiException will be thrown.

Below is the main method using the method below it and below that PiException inheriting from ArgumentException:

staticvoid Main(string[] args)
{
try
{
double pi1000 = GregoryLeibnizPi(1000);
Console.WriteLine(pi1000);
double piMax = GregoryLeibnizPi(int.MaxValue);
Console.WriteLine(piMax);
}
catch (PiExeption ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
Console.WriteLine(“Have a nice day!”);
}
Console.ReadLine();
}publicstaticdouble GregoryLeibnizPi(int iterations)
{
if (iterations == int.MaxValue)
{
thrownewPiExeption();
}
double sum = 0;
for (double k = 1; k < iterations; k++)
{
sum += (Pow(-1.0, k + 1.0)/ ((2.0 * k) – 1.0));
}
return sum * 4;
}classPiExeption : ArgumentException
{
publicoverridestring Message
{
get
{
return“To Much Pi!”;
}
}
}

As you can see, the Gregory Leibniz algorithm was used. The first time the loop went 1000 times to get a few decent digits, and the second time, it threw the PiException in order to keep from overloading the computer. That particular algorithm was looked up on Wolfram’s mathworld which is a good site to read up on math if it’s the domain you are using even if briefly.

The last thing to focus on is the use of the throw keyword. The main difference when dealing with exceptions even though they are just classes is the throwing and catching. You still use the new keyword like with any class and call a constructor if needed and can add any number of other methods and properties that can give the object in the catch more information if the need ever arrises.

File IO

The .NET libraries have several classes that can help you work with files. In this, we are going to be working in the main method, make sure to at the top put a using statement for the namespace System.IO. This will give you access to several libraries for making, reading, and writing files as well as directories.

The first piece of code will show how to get information from directories. In this example, we’ll use a folder on the C drive called test. For your own practice you can put whatever you want in it. It doesn’t really matter which ones or what kind. The ones on this development machine will show up in the listing and if it is a file or a directory:

var files = Directory.GetFiles(@”C:\test”);
var directories = Directory.GetDirectories(@”C:\test”);
foreach (var file in files)
{
Console.WriteLine($”File Name: {file});
}
foreach (var directory in directories)
{
Console.WriteLine($”Directory Name: {directory});
}
Console.ReadLine();

Here’s a picture of the folder with some things in it:

Here’s what the program will output:

As you can see, these API calls will give you the name and path files and directories from any given location.

Now, we’ll use the File class in order to write some text into text info.txt:

File.WriteAllText(@”C:\test\some text.txt”, “This will overwrite any text in some text.txt”);
Console.ReadLine();

Here’s the file opened:

As you can see, the WriteAllText not only created the file that wasn’t there, it also write the data in the string. If you want to avoid overwriting file, then use the methods that begin with Append. Both Write and Append methods exist to give you ways to write text or write several lines of text, depending on your situation.

This is good as far as it goes, but more advanced file handling occurs through the use of streams. This chapter will only cover file streams, but remember that streams are a useful concept as they allow interfacing to be uniform. Case in point is the memory stream. You can read and write data to a block of memory with similar API calls to writing to a stream for text and binary data. The same is true for reading and writing to the network. Some specialized streams exist for certain file types like Xml.

Here are some examples of using streams. The first section writes text. The second will write binary data. This is a confusing term as it is true that all data in a computer is binary, even the text. In the context of working with data and files, what is meant by binary data is that it is information not meant to be read directly by a plain text editor. It will have special directives that are meant for certain programs to use and will often look like nonsense if opened up in notepad or notepad++. Case in point is an image file. Only programs that understand the formatting are going to be able to make sense.

FileStream

While the File object is good as far as it goes, it’s a one off sort of operation and mostly for text. Here we’ll see about reading and writing some text, but this time in byte form. It’s more low level, but it offers you fine tuned control.

using (FileStream fs = File.OpenRead(@“C:\test\some text.txt”))
{
byte[] data = newbyte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
UTF8Encoding encoding = newUTF8Encoding();
Console.WriteLine(encoding.GetString(data));
}
Console.ReadLine();

The file from the last example was used to show reading text. Also, when you read data in, you have the length of the bytes and of course can read in as many bytes as there are or fewer.

In order to interpret them as strings, you could write your own function for that, but it’s easier to use one of the Encoding classes and then simply pass the data from the array to the Encoder’s GetString method. The different types of encoding are about how the bytes are grouped to be either 1 byte ASCII text or multibyte Unicode.

This also a new use of using that you haven’t yet seen. Before, they were just used to import stuff from a library’s many namespaces. Here they have the second function of adding some management to what is an unmanaged resource. That is to say, the stream is unmanaged. You can’t rely on garbage collection to clean up streams for you, but using makes it so you don’t have to. Once the code goes out of scope denoted by the using’s curly braces, it will call the Dispose method. You can do this manually but probably shouldn’t.

Next, we’ll write some data to the same file. This time, a try catch will be added as you should always with streams in case something like a disk or network failure or a path not existing. It won’t be in other examples just to keep them short, but just know that IO operations are places where try catch should be used liberally.

using (FileStream fs = File.OpenWrite(@”C:\test\other.txt”))
{
try
{
UTF8Encoding encoding = newUTF8Encoding();
byte[] data = encoding.GetBytes(“\nThar be tresure!”);
fs.Write(data, 0, data.Length);
fs.Flush();
}
catch (Exception ex)
{
Console.WriteLine(“Disk Operation Failed”);
}
}
Console.ReadLine();

The thing to remember about writing is that you should always call the Flush method. Streams have the habit of acting like buffers. This is for speeding up operations since saving to RAM is about a million times faster than writing to disk, so it’s common to write to the stream several times in some scenario and then only at certain intervals or even at the very end to flush the contents to the disk or network.

StreamWriter

StreamWriter and its counterpart below, StreamREader, is higher level than the FileStream in that it doesn’t make you work with bytes but rather blocks of text. As such, unless you need to manipulate at the byte level, then these two are the preferred method.

using (StreamWriter sw = newStreamWriter(@”C:\test\other1.txt”))
{
sw.WriteLine(“Books are fun.”);
sw.Write(“Movies are “);
sw.Write(“fun”);
sw.Flush();
}
Console.ReadLine();

As you can see, you can write text and you can also write them in lines. If ever you need to make your own text editor, this would probably be part of it. It’s also an easy way to store records in an ad hoc way rather than using a database.

StreamReader

StreamReader is the reading analog of StreamWriter. As such, for this example, you’ll simply read in what you write to other1.txt.

using (StreamReader fs = newStreamReader($@”C:\test\other1.txt”))
{
Console.WriteLine(fs.ReadToEnd());
}
Console.ReadLine();

As you can see, the console reproduced what was in the file.

Serialization

Serialization is all about persisting the state of a program to disk. You’ll use things when serializing. A stream to write the data, and a formatter that formats and then uses the stream to format the object. We’ll use a DateTime object to be serialized and show its text. The next section will deserialize it and print it to the console.

You will create a file by setting the mode to Create, and Serialize will take the the stream as well as the object to be written to the disk.

using System;
using System.Threading;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace ConsoleApplication3
{
classProgram
{staticvoid Main(string[] args)
{
using (Stream fs = newFileStream(@”C:\test\dat.dat”, FileMode.Create))
{
BinaryFormatter formatter = newBinaryFormatter();
formatter.Serialize(fs, DateTime);
fs.Flush();
}
Console.ReadLine();
}
}
}

As you can see, to human readers, this looks like garbage, but remember what was stated about binary formats. The whole file was posted to show the using statement needed to get to the formatting class.

Deserialization

Deserialization is about going from the disk back to a program for the same reasons as mentioned above. This time the FileStream’s FileMode is going to be Open, and when you call Deserialize, you need only pass it the stream. It gives an object back, you so must cast to use the result.

using (Stream fs = newFileStream
(@”C:\test\dat.dat”, FileMode.Open))
{
BinaryFormatter formatter = newBinaryFormatter();
DateTime data = (DateTime)formatter.Deserialize(fs);
Console.WriteLine(data);
}
Console.ReadLine();

The time will vary depending on when you ran the serializer, but as you can see it is indeed a date.

Collections

Collections are ways of holding several pieces of data in the same structure, much like an array, but they can grow and often support different types of adding or taking away elements as well as what types of elements and some specialized operations such as how HashSet as discussed below supports operations that are like those of the mathematical set.

List

List is like an array and can be used in a similar way, but it can grow and shrink. The collections shown here are generic, which means that they all take a type as an argument inside angle brackets after the generic class itself. This means that you are working with strongly typed objects.

Here are some examples of adding, removing, and printing out items in the list:

List<int> listOfInts = newList<int>();
listOfInts.Add(10);
listOfInts.Add(30);
listOfInts.AddRange(newint[] { 20, 16 });
listOfInts.Remove(10);
listOfInts.RemoveAt(0);
foreach (var item in listOfInts)
{
Console.WriteLine(item);
}
Console.WriteLine($”Length: {listOfInts.Count});
Console.ReadLine();

As you can see, you can add items, and you can even add them en mass if you have another collection or an array. You can also get the count of the items which is updated anytime you add or remove items.

Uses lists for any time you need an array that can grow. You can also go back and forth between arrays and lists with ToList and ToArray methods.

HashSet

A HashSet is a collection that can grow like an array, but unlike an array, it will not keep up with duplicates and is therefore more like the set you may be familiar with in the mathematical topic known as set theory. They aren’t sorted, and their operations are about unioning, intersection as shown below:

HashSet<int> hashSet = newHashSet<int>();
hashSet.Add(10);
hashSet.Add(10);
hashSet.Add(1);
HashSet<int> unionedHashSet = newHashSet<int>();
unionedHashSet.UnionWith(hashSet);
unionedHashSet.Add(10);
unionedHashSet.Add(20);
unionedHashSet.Add(30);
HashSet<int> intersected = newHashSet<int>();
intersected.Add(10);
intersected.IntersectWith(hashSet);
Console.WriteLine(“hashSet vals”);
foreach (var item in hashSet)
{
Console.WriteLine(item);
}
Console.WriteLine(“unionedHashSet vals”);
foreach (var item in unionedHashSet)
{
Console.WriteLine(item);
}
Console.WriteLine(“intersected vals”);
foreach (var item in intersected)
{
Console.WriteLine(item);
}
Console.ReadLine();

As you can see, the operations supported by HashSet mimic those of a set from math. You can’t add duplicates, and you can do operations on them like the ones you might be familiar with.

SortedSet

Sorted sets offer the same operations as HashSets, but the difference is that they are sorted. In set theory, sets aren’t sorted, but the .NET base class library offers this little bit of extra functionality. It will still get rid of duplicates as shown below, but no matter what you add, the items will be sorted.

SortedSet<int> sortedSet = newSortedSet<int>();
sortedSet.Add(10);
sortedSet.Add(10);
sortedSet.Add(1);
sortedSet.Add(20);
Console.WriteLine(“sorted set vals”);
foreach (var item in sortedSet)
{
Console.WriteLine(item);
}
Console.ReadLine();

Stack

A stack is a structure that is termed a LIFO which is short for last in first out. It’s useful when you need to model items or operations that need to occur with that kind of ordering. An instance is plates at a restaurant. Plates are added to the stack, and the first one to go in is the last one to come out because more plates can be stacked.

In this example, we’ll just have some integers being added and taken away and then finally printed:

As you can see, the order of what’s popped is the opposite of what’s pushed. You can get the count to check how many there are so you don’t go trying to pop items that don’t exist.Also, note that you can peek at the next value without popping it.

Queue

A queue is a little bit like a stack in that’s it’s not meant for random access like a list but rather to go in a certain direction. The direction of a queue is more like a line in a grocery store than like a stack of plates and is thus a FIFO or first in first out.

It supports Peek, but instead of Push an Pop, you Enqueue and DeQueue as shown here:

Queue<int>
queue = newQueue<int>();
queue.Enqueue(4);
queue.Enqueue(7);
queue.Enqueue(9);
queue.Enqueue(20);
Console.WriteLine($”Dequeue is {queue.Dequeue()});
Console.WriteLine($”Peek next val: {queue.Peek()});
while (queue.Count > 0)
{
Console.WriteLine(queue.Dequeue());
}
Consolee.ReadLine();

As always, choose which data structure and it’s supported algorithms best fit your situation.

LinkedList

A LinkedList is yet another item that isn’t meant to be indexed directly. This class from the .NET’s libraries is what’s termed a doubly linked list. You get to items called nodes which is what it’s made up of (like the key value pair in Dictionary) that you get to by going to the next one or the one before.

As you can see in the photo above, when you access a certain node, you can get at its value, the linked list it is from via List, and get to the Next and Previous LinkedListNode unless they don’t exist in which case you’ll get a null.
The linked list is useful in that it is faster if you don’t need direct access, but simply need to get from one thing to the next much like traversing a series of rooms. If you need random access to things by numerical index however, do use a List.

Here’s the complete code for it being traversed followed by the output:

LinkedList<string> linkedList = newLinkedList<string>();
linkedList.AddFirst(“C#”);
var cNode = linkedList.AddAfter(linkedList.First, “C”);
linkedList.AddBefore(cNode, “C++”);
var currentNode = linkedList.First;
Console.WriteLine(“Going forwards”);
while (currentNode != null)
{
Console.WriteLine(currentNode.Value);
currentNode = currentNode.Next;
}
Console.WriteLine(“Going backwards”);
currentNode = linkedList.Last;
while (currentNode != null)
{
Console.WriteLine(currentNode.Value);
currentNode = currentNode.Previous;
}
Console.ReadLine();

As you can see, you can keep references to a particular node and traverse from it as well as used the linked list to start from one end or the other. And with a node reference, you can use the linked list to put a node before or after it.

Dictionary

A Dictionary is much like it sounds. It has data for looking up and data to be looked up. These are known as the Key and Value, and as such, this is an example of a generic that takes two data type arguments, one for the key and one for the value.

Here is an example of using the dictionary to keep up with how much money each person has:

Dictionary<string, decimal> personsMoney = newDictionary<string, decimal>();
personsMoney.Add(“Shanequa”, 1000300.65M);
personsMoney.Add(“Mario”, 50234.92M);
personsMoney.Add(“Johann Kepler”, 100034.7M);
personsMoney.Add(“Srinivasa Ramanujan”, 8932323.888M);
foreach (var item in personsMoney)
{
Console.WriteLine($”{item.Key} has {item.Value} in USD”);
}
var itsAMeMario = personsMoney[“Mario”];
Console.WriteLine(Math.Sin((double)itsAMeMario));
Console.ReadLine();

As you can see, the two types in the collection were separated by commas. Also note how with the dictionary, you can index it much like an array, but instead of being limited to numbers, you index it by the same type as the key, so for instance, Mario’s money was index by his name as a string and caste to a double for some math work.

Also, whenever you iterate through a dictionary, you get a key value pair as the item’s type with the same arguments passed into the dictionary type. You could use that instead of var, but it isn’t necessary. If you want to know about the type of some variable, just hover over it in Visual Studio and it will give you useful information as shown below:

The same will be true when you access the Key and Value objects from item. Just hover over them or when selecting from intellisense you should get useful information.

SortedDictionary

A SortedDictionary supports the same kind of operations that a Dictionary does, but will internally sort the items by key when items are added or removed.

Here’s a modified example to show that the items while out of alphabetical order when added, will be printed in alphabetical order to the console:

SortedDictionary<string, decimal> personsMoney = newSortedDictionary<string, decimal>();
personsMoney.Add(“Shanequa”, 1000300.65M);
personsMoney.Add(“Mario”, 50234.92M);
personsMoney.Add(“Johann Kepler”, 100034.7M);
personsMoney.Add(“Antoniao”, 98358934.8M);
personsMoney.Add(“Srinivasa Ramanujan”, 8932323.888M);
foreach (var item in personsMoney)
{
Console.WriteLine($”{item.Key} has {item.Value} in USD”);
}
Console.ReadLine();

SortedList

A SortedListisn’t an analog to the List. In terms of how to use it, it’s exactly like SortedDictionary. While an indepth study of algorithms is beyond the scope of this book, it is important to touch on their importance in terms of use of resources and the fact that trade offs are the name of the game very often when selecting which algorithm to use even if the output in terms of what you see on the console or a GUI is the same.

The differences is that SortedList will take up less ram, while SortedDictionary is faster at sorting when unsorted data is put into it. For a few items, this won’t be noticeable, but this trade off could matter if you are using millions of objects.

As it is the same interface, the example will just be an adaption of the SortedDictionary and the output:

SortedList<string, decimal> personsMoney = newSortedList<string, decimal>();
personsMoney.Add(“Shanequa”, 1000300.65M);
personsMoney.Add(“Mario”, 50234.92M);
personsMoney.Add(“Johann Kepler”, 100034.7M);
personsMoney.Add(“Zoey”, -1000);
personsMoney.Add(“Antoniao”, 98358934.8M);
personsMoney.Add(“Srinivasa Ramanujan”, 8932323.888M);
foreach (var item in personsMoney)
{
Console.WriteLine($”{item.Key} has {item.Value} in USD”);
}
Console.ReadLine();

Delegates

Delagates are one of OOP in C#’s answers to treating functions as objects or if you are coming from a C or C++ background, they are like pointers to functions.

Here’s a basic show of what they can do and the output:

publicdelegatedoubleTrigDelegate(double input);
staticvoid Main(string[] args)
{TrigDelegate tan = newTrigDelegate(tangent); TrigDelegate cot = newTrigDelegate(cotangent);
Console.WriteLine($”tan(10) = {tan(10)});
Console.WriteLine($”cot(10) = {cot(10)});
Console.ReadLine();
}publicstaticdouble tangent(double theta)
{
return Sin(theta) / Cos(theta);
}

publicstaticdouble cotangent(double theta)
{
return Cos(theta) / Sin(theta);
}

In this example, you passed in a method that had a similar signature except that the delegate keyword is added. With delegates, you can now pass around methods that are to be executed, and as long as they have the same signature, they can be executed. This is useful when you need to be able to change out which algorithm you need but keep the same type of input and output.

Reflection

Reflection is about getting information about code. It’s code that can return metadata about code. Metadata is just a fancy way of saying data about data. Though it isn’t always the case, often in English, the prefix meta means that it is something about something. Metafiction then is fiction about fiction.

In programming, metadata is useful because it gives you runtime information about the types such as what methods and properties it has. Visual Studio for instance uses it to give you intellisense.

One of the basic types you get in reflection is the Type type. It’s what you get when you use the typeof keyword as you’ll see below, and when you call GetType on any object. A good bit of the reflection classes like Assembly and MethodAttributes are beyond the scope of this text, but just know that there are reflection classes for every programming concept C# has.
In order to use reflection, at the top, add a using statement for System.Reflection.Here are some examples of using reflection to get information at runtime about a type:

using System;
using System.Reflection;namespace ConsoleApplication2
{
classProgram
{
staticvoid Main(string[] args)
{
Type typeOfInt = typeof(int);
Console.WriteLine($”{typeOfInt.FullName});
Console.WriteLine($”{typeOfInt.GetMethods()[0].Name});
MethodInfo addMethod = typeof(Program).GetMethod(“Add”);
object data = addMethod.Invoke(null, newobject[] { 4, 10 });
Console.WriteLine($”Add invoked is {data});
Console.ReadLine();
}publicstaticdouble Add(int a, int b)
{
return a + b;
}
}
}

This is just the beginning of what can be done. System.Reflection contains types that represent many constructs and elements of programming. You can inspect types and their methods, properties, data members and if they are public, private, static, etc.

The two main uses for reflection are for programming tools and making extensibility features which is far beyond the scope of a beginner text, but just note this in your more advanced studies.

Multithreading

Up until now, you’ve written instructions in C# that execute sequentially. This is good so far as it goes, but it can be useful to be able to concurrently execute some work.

This is especially true when you are doing long running operations inside a GUI. GUIs are beyond the scope of this book, but imagine if you call a method inside a click event of a button that takes five minutes to computer some sort of financial calculation, and then the rest of the interface freezes up. This will greatly annoy your users. They won’t want to buy your software anymore.

In this example, we’ll stick to the console and simulate long work by a long loop. It will be called a few times by a couple of new threads, add all the numbers up and report the results and also show that faster code running after the invocation of the thread will run before the longer threads are finished to demonstrate that threads are indeed independent bits of code execution .

using System;
using System.Threading;
namespace ConsoleApplication3
{
classProgram
{
staticvoid Main(string[] args)
{
Console.WriteLine(“Starting some threads”);
Thread t1 = newThread(newThreadStart(SomeMath));
t1.Name = “High Priority Math”;
t1.Priority = ThreadPriority.AboveNormal;
t1.Start();
Thread t2 = newThread(newParameterizedThreadStart
(Add));
t2.Start(newint[] { 4, 6 });
Thread t3 = newThread(newParameterizedThreadStart(MoreMaht));
t3.Start(int.MaxValue);
Console.WriteLine(“End of Main”);
Console.ReadLine();
}publicstaticvoid MoreMaht(object iterations) {
int loopCount = (int)iterations;
for (int i = 0; i < loopCount; i++) {
if (i > 5) {//too much work on the thread
Thread.CurrentThread.Abort();
}
Console.WriteLine($”sin({i} is {Math.Sin(i)}));
}
}publicstaticvoid SomeMath()
{
double sum = 0;
for (int i = 0; i < 100000; i++)
{
sum += i / 1000.0;
}
Console.WriteLine($”Output {sum});
}publicstaticvoid Add(object input)
{
Thread.Sleep(3000);//sleep for three seconds

int[] data = (int[])input;
Console.WriteLine(data[0] + data[1]);
Console.WriteLine(Thread.CurrentThread.ThreadState);
}
}
}

As you can see, you have to use System.Threading to use the Thread and the two different types of thread starts. Also of interest is that a line after the start methods were called is that the end was printed before the math was done.

Using the Sleep method, you are able to delay execution of a thread for some time. This has to be called as a static method on the Thread class, but it only affects the current thread. For other methods such as Abort you access via Thread.CurrentThread. Finally, a thread has a state such as Running, Stopped, or Aborted.

The mechanics of how threads work is beyond the scope of the text, but just know that if you have a single processor with a single core, you might get the same result, but what’s really happening is time slicing which the processor is going back and forth on threads by completing a little work at a time. Only with multicore and/or multiprocessor architecture systems are multiple threads really running at the same time.

Pointers

In this chapter, you’ll take a look at a unoften used set of features that C# has. You can go a little low level with it since it supports pointers like C and C++. First of course you have to set it up so that it can use the unsafe keyword. If you don’t follow the steps below, you won’t be able to compile code with unsafe statements in it.

Follow these steps in order to allow unsafe code via visual studio:

After you click Properties, you will see a new tab. Click build on the left and the screen will look like this:

After that, you will need to check All unsafe code. Save the changes and close out the tab. Now, you’ll be able to unsafe code.

Once that is done, enter the following code and run it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
classProgram
{
staticvoid Main(string[] args)
{
Console.WriteLine(“Hello World”);
int a = 10;
Console.WriteLine(“Safe section”);
unsafe
{
int* pointerToA = &a;
int aVal = *pointerToA;
Console.WriteLine($”Memory Location of a {(IntPtr)pointerToA});
Console.WriteLine($”aVal is {aVal});
}
Console.ReadLine();
}
}
}

There really isn’t much here. It isn’t as versatile as C and C++. You can’t really make pointers to most types like strings. Just note that any of the syntax you use like that must be inside the scope of an unsafe declarative.

If you do run across code that needs pointers, you will see how it works in general. A pointer is declared much like a type, except there is a start at the end of the type showing that it is a pointer. Next it needs to point to something. That is where the single ampersand comes in. It Jagged Arraysgets the location of some data such as that of an int.

If you decide to print out the location, you have to cast to an IntPtr, and you will get something like on the screen which is some place in the computer’s ram. Finally, to get at the data, you use the star again, but this time, you are dereferencing it if you use it on the rhs of the expression.