For programmers who have coded in any other language, enums are not a new concept. An enum is a list of integer values represented by friendly names. They are similar to structures, but only integers can be stored in an enum values.
Once you learn enums, we then move on to understanding the debug process. You must debug your code, which is a part of testing. When you test your code, you'll probably find bugs that you need to fix. No code is perfectly created the first time with no errors or issues. Bugs are nothing to be ashamed of, but it's better to catch them before they are pushed to production code. We'll show you how to test and debug your code for better results and reliability.
Enums
Enums (short for enumerators) are a more friendly way to represent numeric values. For instance, suppose you have an application that deals with days of the week. You want to store each day of the week as a numeric value to be more efficient in your code. You could use something like the following to create variables for each day of the week.
public static void Main()
{
int Sunday = 0;
int Monday = 1;
int Tuesday = 2;
int Wednesday = 3;
int Thursday = 4;
int Friday = 5;
int Saturday = 6;
System.Console.WriteLine(Sunday);
System.Console.WriteLine(Monday);
System.Console.WriteLine(Tuesday);
System.Console.WriteLine(Wednesday);
System.Console.WriteLine(Thursday);
System.Console.WriteLine(Friday);
System.Console.WriteLine(Saturday);
}
In the above code, we added a Main function and created a list of variables for each day of the week. We then assigned our own numeric integer value for each variable. This is legitimate code, and the result is that each day of the week prints each corresponding integer value. However, if you remember from previous chapters, these variables are local to the Main variable. If you want to use variables again in other parts of your code, you again must make these variables and assign them appropriate values. If you ever decide to change the value for any day of the week, you would then need to edit the value in every variable throughout your code. This is not only inefficient, but it's an easy way to introduce bugs in your code when you change a value and miss an instance in a certain part of your code.
The better way to handle variables that require the same value across all parts of your code is to use enums. Enums are just as name-friendly as a regular variable. You can give the enum any name you want, and it can represent any standard part of your code. In this example, we want the enum structure to represent the names of the week.
Let's see what an enum looks like.
enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
Now we have a nice representation of the days of the week instead of a set of variables for multiple functions and classes.
The first question is what values do these variables contain? Enums automatically start the values at 0. Remember that anything in coding starts with a value of 0, and enums are no different. Arrays start with a 0 value index for the first variable, and so do enums.
Let's print the enum values to verify the values.
enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
public static void Main()
{
System.Console.WriteLine((int)DaysOfWeek.Sunday);
System.Console.WriteLine((int)DaysOfWeek.Monday);
System.Console.WriteLine((int)DaysOfWeek.Tuesday);
System.Console.WriteLine((int)DaysOfWeek.Wednesday);
System.Console.WriteLine((int)DaysOfWeek.Thursday);
System.Console.WriteLine((int)DaysOfWeek.Friday);
System.Console.WriteLine((int)DaysOfWeek.Saturday);
}
The output for this program is the following.
0
1
2
3
4
5
6
Notice that the way we use an enum is much different than the way we printed the regular variables. We didn't need to instantiate the enum structure before we were able to use it. We can use enum variables in the same way we use static classes and member variables. As long as the enum is available to the calling function, you can use its values.
Also notice that the output is a list of integers from 0 to 6. The enum structure automatically gives values to the variables in the order in which they appear. This means the first variable always contains the value of 0, the second variable always contains the value of 1, and the third variable always contains the value of 2. As more variables are added, each additional variable is given the next integer in succession.
To get these values, we need to convert the enum variable to an integer. We haven't seen conversions yet, but you can convert variables in two ways. The first way is using the static class named Convert. This class has several functions that let you convert your variables to different data types. We used the second explicit conversion. This conversion is the common C-style conversion that tells the compiler to convert the enum variables to their corresponding integer value.
You can also use the enums variable name. Variable names are one advantage of using enums over standard variables. Instead of just identifying and manipulating integer values, you can also view and compare enum variable names in the code. Let's see what happens when we remove the (int) conversion statement and just print the enum variables.
enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
public static void Main()
{
System.Console.WriteLine(DaysOfWeek.Sunday);
System.Console.WriteLine(DaysOfWeek.Monday);
System.Console.WriteLine(DaysOfWeek.Tuesday);
System.Console.WriteLine(DaysOfWeek.Wednesday);
System.Console.WriteLine(DaysOfWeek.Thursday);
System.Console.WriteLine(DaysOfWeek.Friday);
System.Console.WriteLine(DaysOfWeek.Saturday);
}
The output for this program is the following.
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
The above output is one reason why using enums is better than standard integer variables. If we wanted to represent weekdays in a string and integer output, we'd need two variables for each day of the week. This makes enums much more efficient and easier to use.
One disadvantage of enums is that you can only use them with integer values. You can't use decimals, Boolean, or strings for an enum. Most developers turn their enums into a structure when they want to use another data type. Enums are only meant for variables that need a standard integer stored.
You also can't inherit or derive from an enum. Enums are considered sealed classes. If you recall from previous chapters, we used the sealed modifier to block child classes from inheriting and overriding certain member methods. The entire enum structure is considered sealed, so you cannot inherit from it. If you attempt to inherit from an enum, the C# compiler will give you an error and the code won't compile.
You aren't limited to values that start with the number 0. You can have the enumerator structure start at any integer. As long as the integer is not to large, the enum structure will take the initial value and increment from it to define your other variables. Let's take a look at the code to illustrate.
enum DaysOfWeek
{
Sunday = 50,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
public static void Main()
{
System.Console.WriteLine((int)DaysOfWeek.Sunday);
System.Console.WriteLine((int)DaysOfWeek.Monday);
System.Console.WriteLine((int)DaysOfWeek.Tuesday);
System.Console.WriteLine((int)DaysOfWeek.Wednesday);
System.Console.WriteLine((int)DaysOfWeek.Thursday);
System.Console.WriteLine((int)DaysOfWeek.Friday);
System.Console.WriteLine((int)DaysOfWeek.Saturday);
}
The output for this program is the following.
50
51
52
53
54
55
56
We changed the first day of the week, Sunday, to equal the value of 50. This is the starting value for the enum variables. The next variable takes the value of 51, the following contains 52, and each subsequent variable contains an integer incremented by 1. You can see this list of values in the above output.
You don't have to start the alternative values at the first variable. You can also change the values in the center or even the end of the enum structure. Let's take a look at the code to see how this change works.
enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday = 10,
Thursday,
Friday,
Saturday
}
public static void Main()
{
System.Console.WriteLine((int)DaysOfWeek.Sunday);
System.Console.WriteLine((int)DaysOfWeek.Monday);
System.Console.WriteLine((int)DaysOfWeek.Tuesday);
System.Console.WriteLine((int)DaysOfWeek.Wednesday);
System.Console.WriteLine((int)DaysOfWeek.Thursday);
System.Console.WriteLine((int)DaysOfWeek.Friday);
System.Console.WriteLine((int)DaysOfWeek.Saturday);
}
The output for this program is the following.
0
1
2
10
11
12
13
In the above code, we changed the alternative values to start at the variable Wednesday. Notice that the enum starts with the value of 0 until it reaches that Wednesday variable manually set to the value of 10. It then increments from 10 until it reaches the end of variable list.
Enums let you assign a different or even the same value to all of your variables. You can assign multiple variables the same value or give them a custom value that overrides the default. The following is an example.
enum DaysOfWeek
{
Sunday = 10,
Monday = 12,
Tuesday = 14,
Wednesday = 16,
Thursday = 18,
Friday = 20,
Saturday = 22
}
public static void Main()
{
System.Console.WriteLine((int)DaysOfWeek.Sunday);
System.Console.WriteLine((int)DaysOfWeek.Monday);
System.Console.WriteLine((int)DaysOfWeek.Tuesday);
System.Console.WriteLine((int)DaysOfWeek.Wednesday);
System.Console.WriteLine((int)DaysOfWeek.Thursday);
System.Console.WriteLine((int)DaysOfWeek.Friday);
System.Console.WriteLine((int)DaysOfWeek.Saturday);
}
The output for this program is the following.
10
12
14
16
18
20
22
The above code shows you how you can give your enums their own values without relying on the system to auto-generate values. This is especially useful when you have a system already coded to store specific values. Instead of globally changing values in the existing system, you can set your enums to contain your current values for each variable.
Debugging Your Code
No coder creates perfect code free from bugs and without the need to debug. Debugging lets you identify issues with your code, and fix them using the Visual Studio interface. Debugging lets you step through the code line-by-line, so you can identify any errors and view the actions that cause the errors to surface.
There are two main types of errors: syntax errors and logic errors. Debugging helps you find the latter.
Syntax errors are the coding errors you make when you mistype something or use the wrong syntax. With syntax errors, the compiler catches them and won't compile your code until you fix the errors. This is one advantage of using a compiled language rather than an interpreted language like PHP or Java. Interpreted languages let you run code even with errors and they aren't found until the syntax error is executed. The code fails in production, and you have an error in your live site or application. With C#, any syntax errors stop the compiling process. Visual Studio gives you a list of syntax errors at the bottom of the IDE in the output section.
Logic errors are much more difficult to find, and they also cause the worst hazards for your application. We covered if statements in previous chapters. What happens when you use the wrong relational or comparison operator? Your logic would fail, but the application still compiles even with the incorrect operator. You don't realize the bug is in your code until the output or storage results are seen during production.
Instead of allowing your code to go into production with errors, you can test the application yourself on the local development computer and use the Visual Studio debugger to fix any errors.
First, let's use a simple application named Hello to see how the Visual Studio debugger works. Copy and paste the following code into the Visual Studio IDE.
public class Hello
{
public static void Main()
{
System.Console.WriteLine("Hello, World!");
}
}
At the top of the Visual Studio IDE, you'll see a green arrow button. This button compiles your code and runs it in the debugger. Note that the code compiled creates an EXE, but it's set in debugger mode and not suitable for production. You can see that the code compiles fine and Hello World is shown in the console. Of course, this represents a small program and finding errors is easy.
Let's introduce a syntax error into the code.
public class Hello
{
public static void Main()
{
int mystring = "Hello, World!"
System.Console.WriteLine(mystring);
}
}
We have two errors in this code. If you don't notice them and click the green start button, the compiler shows you the errors in the bottom panel. They are shown with a red stop sign, and the errors tell you that they are critical and the code cannot be compiled.
The debugger gives you hints to why there are errors. Sometimes, the error messages tell you exactly. In this example, the error messages tell you that a string cannot be assigned to an integer variable, and you're missing a semicolon at the end of the first statement.
Let's fix the syntax error, so the code will compile, but now let's introduce a logic error.
public class Hello
{
public static void Main()
{
string mystring = "Hello, World!";
if (mystring == "Hello World")
{
System.Console.WriteLine(mystring);
}
}
}
Assume that we want to print the mystring variable if it equals the value of "Hello, World." Notice that we forgot to add the comma in the if statement's comparison condition, so it will return false. The result is that nothing prints to the console. You see this is the wrong output, and you need to figure out why the output is not what's expected.
You can step through your code and stop execution by setting a breakpoint on the if statement. Highlight the if statement, right-click it, and then choose Breakpoint > Insert Breakpoint. Notice a red circle is placed in front of the if statement.
Click the start button again and watch as the code stops execution at the if statement. Highlight the cursor over the mystring variable in the if statement. Visual Studio's IDE shows you a popup that contains the value of mystring. You can now see what it contains in real-time to compare what you thought it should be while you run your code.
You'll see that mystring contains "Hello, World" but your if condition looks for "Hello World." Just one missing comma causes you to have logic errors in your code, and it does not execute properly. While it seems minor in this code, the result is that nothing prints to the screen. In larger applications, the result could be that the wrong value gets stored in an accounting application, or the user is given the wrong information. Several issues can occur with logic errors, which is why they are so troublesome for your code and the application as a whole.
Since we were able to find the error using the debugger, we can now stop the debugger. Visual Studio has a red stop button next to the green start button in the top menu that lets you stop the debugger before the code is finished executing. Click the button and change the code to the following.
public class Hello
{
public static void Main()
{
string mystring = "Hello, World!";
if (mystring == "Hello, World")
{
System.Console.WriteLine(mystring);
}
}
}
With the above code fixed, the code now compiles and runs exactly the way it was designed.
We covered enumerators (enums) in this chapter to show you how to represent friendly variable structures without using cumbersome standard variables. We then covered the practical use of debugging. While enums won't always be a part of your development, you will use the Visual Studio debugger often as you code your application.