|
C# Errors & Exceptions: Introduction to Errors
and Debugging |
|
|
Apparently no matter how careful and meticulous you are,
there will be errors in your program. When, not if, they occur, you should
be able to address the issue. In most cases, both C# and Microsoft Visual C#
can assist you.
The errors your program will encounter can be classified
in three categories: runtime, syntax, and logic errors. We will study
runtime errors in the next two lessons about exception handling.
|
Application:
Introducing Errors
|
|
- Start Microsoft Visual Studio
- To create a new application, on the main menu, click File -> New
Project...
- In the middle list, click Empty Project
- Change the Name to WattsALoan1
and click OK
- To create a file, on the main menu, click Project -> Add New Item...
- In the middle list, click Code File
- Change the Name to LoanEvaluation
- Click Add
A syntax error is due to a misuse of the C# language in
your code. For example, in Lesson 2, we saw that, on one hand C# is
case-sensitive and, on the other C# has a set of keywords that you should
(must) not use to name your variable. The first rule can be difficult to
observe if you come from a case-insensitive language like Pascal or Visual
Basic. It can also happen through distraction. The second rule is easy to
observe if you have used another C-based language such as C++ or Java. Both
rules are easy to violate if you write your code using a normal text editor
like Notepad.
Fortunately, the built-in Code Editor of Microsoft
Visual Studio makes it extremely easy to be aware of syntax errors as soon
as they occur:
- When you start typing code, the IntelliSense starts building a list
of words that match the first characters and those that include the
characters already typed:
If you see a word you need and it is highlighted, you can press
Enter to select it. You can also double-click the word from the list. If
the list is long and the word does not appear yet, you can keep typing
(adding characters) until the word you want comes up
- If you mistype a word or a keyword, the Code Editor would indicate
the error by underlining the word. If you place the mouse on it, a
message would display the reason for the error:
- If you declare a variable, or once you have declared a variable,
whenever you want to use it, as soon as you start typing its name, the
IntelliSense would display a list that includes that variable
- C# is a strongly-typed language. One of the characteristics of such
languages is that you cannot use a variable that has not yet been
declared. Therefore, if you try using an undeclared variable, the Code
Editor would underline it. If you position the mouse on the word, an
error message would display:
- C# is equipped with many operators and each operator has rules. If
you misuse an operator, the section of your code would be underlined.
You can position the mouse on it to see the resulting error message:
As you can see, if you create your application in
Microsoft Visual Studio, the Code Editor is fully equipped with tools to
assist you to detect and correct syntax errors. If you still violate a
syntax rule, when you build your project, the compiler would detect the
error and point out the line, the section, and the file name where the error
occurred. Here is an example:
Application:
Introducing Syntax Errors
|
|
- In the document, type the following:
using System;
public class LoanEvaluation
{
public static int Main()
{
double principal = 0.00d;
Console.Title = "Watts A Loan?";
Console.WriteLine("============================");
Console.WriteLine("Loan Summary");
Console.WriteLine("=--------------------------=");
Console.WriteLine("Principal: {0:F}", principal);
Console.WriteLine("============================");
System.Console.ReadKey();
return 0;
}
}
A logic error occurs when the program (the code) is
written fine but the result it produces is not reliable. With a logic error,
the Code Editor does not see anything wrong in the document and therefore
cannot point out a problem. One of the worse types of logic errors is one
that makes a computer crash sometimes, regularly, or unpredictably, while
there is nothing obviously wrong in the code.
Logic errors are, or can be, difficult to spot because
you will have to know for sure that the result is wrong and why (and
sometimes worse, you will have to agree or accept that it is your program
that is causing a problem in the computer: a bitter pill to swallow; imagine
a user reports that her computer crashes every time she starts the
application you created). Because you or the user of your program would know
with certainty that the result is questionable, you would have to use some
means of correcting it. One of the techniques you can use is referred to as
debugging.
A logic error is called a bug. Debugging is the process
of examining code to look for bugs or to identify problems. Debugging is the
ability to monitor the behavior of a variable, a class, or its members
throughout a program. Microsoft Visual C# provides many features to perform
debugging operations.
The debugger is the program you use to debug your code.
The code or application that you are debugging is called the debuggee.
Probably the most fundamental way of examining code is
to read every word and every line, with your eyes, using your experience as
a programmer. This can work for short code written in one file and in one
class. If the code to examine covers many pages or many files, it could be
aweful and tiresome to examine code with your eyes line by line.
Fortunately, to assist you with this operation, Microsoft Visual Basic
provides various tools and windows that you use, one window or a combination
of objects. One of the tools you can use is the Standard toolbar that is
equipped with various debugging buttons:
Starting and Continuing With Debugging
|
|
There are different ways you can launch the debugging
process:
- On the main menu, you can click Debug -> Start Debugging
- On the Standard toolbar, you can click the Start Debugging button
- In the Solution Explorer, you can right-click the name of the
project, position the mouse on Debug, and click Step Into New Instance
- You can press F5
In later sections, we will see other ways of starting or
proceeding with debugging. In some cases, we will see how you can suspend
debugging. When this has happened, to resume debugging:
- On the main menu, you can click Debug -> Continue
- On the Standard toolbar, you can click the Continue button
- You can press F5
We will see other ways of continuing with debugging.
As we will see in later sections, there are various
debugging approaches available in Microsoft Visual Studio. Sometimes you
will want to suspend or stop debugging.
To end debugging at any time:
- On the main menu, click Debug -> Stop Debugging
- On the Standard toolbar, click the Stop Debugging button
One of the primary pieces of information you want to get
is the value that a variable is holding. A window named Locals is used to
show that value. Normally, when you start debugging, the Locals window shows
automatically. During debugging, if the Locals window is hidden, to display
it:
- On the main menu, click Debug -> Windows -> Locals
- Press Ctrl + Alt + V, release, then press L
As its name indicates, the Locals window shows the
values of local variables as they are changed. If there is more than one
variable, the Locals window displays their names and gives a row to each
variable. The Locals window organizes its information in a table or grid:
The Name column shows the name of each variable declared
in the method or the section that is being debugged. If the variable is a
class, a + button appears to its left, indicating that it has fields (member
variables):
In this case, to show the variables, that is, to expand
the node, click the + button. This would show the fields under the variable
name and the name of the class between curly brackets under the Value
column:
The Value columns shows the value of each variable. When
debugging starts, each variable shows its default or initial value. As
debugging progresses, when a variable acquires a new value, the Locals
window updates it in the Value column. In some cases, instead of the
debugger changing the value, you can manually select and change it in the
Locals window and press Enter.
The Type column shows the data type of the variable. If
the variable is a class, the name of the class shows in the Type column.
Executing One Statement at a Time
|
|
Just as done when reading code with your eyes, the most
basic way to monitor code is to execute one line at a time and see the
results displayed before your eyes. To support this operation, the debugger
provides what is referred to as stepping into.
To execute code one line at a time, while the file that
contains it is displaying:
- On the main menu, click Debug -> Step Into
- On the Standard toolbar, click the Step Into button
- Press F8
When code is being stepped into, the margin
corresponding to the line that is being examined displays a right-pointing
yellow arrow:
This lets you know what line is currently considered.
Application:
Examining Local Variables
|
|
- While the Code Editor is displaying the code you typed, on the main
menu, click Debug -> Step Into.
If the Locals window is not
displaying, on the main menu, click Debug -> Window -> Locals
- To perform the instructions in this section, move the windows to
make sure you can see the Code Editor, the Locals window, and the DOS
window. Here is an example:
- Notice the yellow arrow button on the left of the declaration of the
principal variable.
Notice that the Locals window displays one entry:
the principal variable. Notice that the DOS window shows a blinking
caret. To end debugging, on the main menu, click Debug -> Stop
Debugging
- Change the code as follows:
using System;
public class LoanEvaluation
{
public static int Main()
{
double principal;
double interestRate;
double period;
double interestAmount;
double futureValue;
Console.Title = "Watts A Loan?";
Console.WriteLine("This application allows you to evaluate a loan");
Console.WriteLine("To proceed, enter the following values");
Console.Write("Enter the principal: ");
principal = double.Parse(Console.ReadLine());
Console.Write("Enter the interest rate: ");
interestRate = double.Parse(Console.ReadLine()) / 100;
Console.Write("Enter the number of months: ");
period = double.Parse(Console.ReadLine()) / 12;
interestAmount = principal * interestRate * period;
futureValue = principal + interestAmount;
Console.Clear();
Console.WriteLine("============================");
Console.WriteLine("Loan Summary");
Console.WriteLine("=--------------------------=");
Console.WriteLine("Principal: {0:F}", principal);
Console.WriteLine("Interest Rate: {0:P}", interestRate);
Console.WriteLine("Period For: {0} months", period * 12);
Console.WriteLine("Interest Amount: {0:F}", interestAmount);
Console.WriteLine("Future Value: {0:F}", futureValue);
Console.WriteLine("============================");
System.Console.ReadKey();
return 0;
}
}
- To restart debugging, on the main menu, click Debug -> Step Into.
Notice that the Locals window displays a list of the local variables and
their starting values:
- To continue debugging, on the Standard toolbar, click the Step Into
button
- To continue debugging, press F8.
Notice that some text displays
in the DOS window
- Keep pressing F8 until the focus moves to the DOS window. You will
know when the Locals window is emptied, the title bar of the DOS window
becomes active, and the caret is blinking in the DOS window while
requesting a value
- When asked to enter a value for the principal, type 6500
and press Enter
- Notice that the focus moves back to the Code Editor.
Notice that
the value of the principal has changed in the Locals grid. Press F8
- Press F8 again
- When the focus moves to the DOS window, when you are asked to
provide the interest rate, type 12.65 and press Enter.
The focus moves back to the Code Editor. Notice that the value of the
interestRate variable in the Locals window has changed
- Press F8
- Press F8 again
- The focus moves to the DOS window. When the number of months is
requested, type 36 and press Enter.
The focus moves
back to the Code Editor. Notice that the value of the period variable
in the Locals window has been changed
- Press F8
- Press F8
- Press F8
- Continue pressing F8 until the DOS window comes
============================
Loan Summary
=--------------------------=
Principal: 6500.00
Interest Rate: 12.65 %
Period For: 36 months
Interest Amount: 2466.75
Future Value: 8966.75
============================
- Press Enter to get back to your programming environment
- Press F8 to end
Executing One Method at a Time
|
|
The Step Into feature is a good tool to monitor the
behavior of variables inside a method. This also allows you to know if a
method is behaving as expected. Once you have established that a method is
alright, you may want to skip it. Instead of executing one line at a time,
the debugger allows you to execute a whole method at a time or to execute
the lines in some methods shile skipping the others. To support this, you
use a feature named Step Over.
To step over a method, while debugging:
- On the main menu, click Debug -> Step Over
- On the Standard toolbar, click the Step Over button
- Press Shift + F8
As its name suggests, the Step Over feature allows you
to skip a method if you know it doesn't have any problem. When debugging,
you choose what methods to step into and which ones to step over.
Application:
Stepping Over
|
|
- Change the file as follows:
using System;
public class LoanEvaluation
{
private static double GetPrincipal()
{
double value = 0.00D;
Console.Write("Enter the principal: ");
value = double.Parse(Console.ReadLine());
return value;
}
private static double GetInterestRate()
{
double value = 0.00D;
Console.Write("Enter the interest rate: ");
value = double.Parse(Console.ReadLine());
return value;
}
private static double GetPeriods()
{
double value = 0;
Console.Write("Enter the number of months: ");
value = double.Parse(Console.ReadLine());
return value;
}
public static void ShowLoanSummary(double presentValue,
double annualRate,
double periods,
double interestCollected,
double totalCollected)
{
Console.WriteLine("============================");
Console.WriteLine("Loan Summary");
Console.WriteLine("=--------------------------=");
Console.WriteLine("Principal: {0:F}", presentValue);
Console.WriteLine("Interest Rate: {0:P}", annualRate);
Console.WriteLine("Period For: {0} months", periods * 12);
Console.WriteLine("Interest Amount: {0:F}", interestCollected);
Console.WriteLine("Future Value: {0:F}", totalCollected);
Console.WriteLine("============================");
}
public static int Main()
{
double principal;
double interestRate;
double period;
double interestAmount;
double futureValue;
Console.Title = "Watts A Loan?";
Console.WriteLine("This application allows you to evaluate a loan");
Console.WriteLine("To proceed, enter the following values");
principal = GetPrincipal();
interestRate = GetInterestRate() / 100;
period = GetPeriods() / 12;
interestAmount = principal * interestRate * period;
futureValue = principal + interestAmount;
Console.Clear();
ShowLoanSummary(principal, interestRate, period, interestAmount, futureValue);
System.Console.ReadKey();
return 0;
}
}
- To debug, on the main menu, click Debug -> Step Into.
Notice that
the yellow button is positioned in the first line under Main()
- To continue, on the Standard toolbar, click the Step Into button
button four times until the debugger gets to the principal =
GetPrincipal(); line
- Press F8 to continue.
Notice that the debugger is positioned on
the first line of the GetPrincipal() method
- Press F8 and notice that the debugger gets in the body of the
GetPrincipal() method
- Keep pressing F8 while inside the GetPrincipal() method, until the
DOS window receives focus
- When asked to provide a Principal, type 21650 and press Enter
- When focus is back to your programming environment, to end
debugging, on the main menu, click Debug -> Stop Debugging
- To start debuggin again, on the main menu, click Debug -> Step Into
and notice that the yellow button is positioned in the first line under
Main()
- To continue, on the Standard toolbar, click the Step Into button
button four times
- This time, to skip the GetPrincipal() function, on the main menu,
click Debug -> Step Over
- Notice that, instead of the debugging moving to the function, the
DOS window received focus.
When asked to provide the principal, type
21650 and press Enter
- Notice that the focus moves back to the Code Editor where the
GetInterestRate() function is called.
To execute the function, on the
Standard toolbar, click the Step Over button
- As the focus has moved to the DOS window, when the interest rate is
requested, type 14.05 and press Enter.
The focus
moves back to the Code Editor where the GetPeriod() function is called.
Notice the value of the interestRate in the Locals window
- To execute the GetPeriod() function, press Shift + F8
- As the focus has moved to the DOS window, when asked to provide the
number of months, type 48 and press Enter.
The focus
moves back to the Code Editor. Notice the period value that
corresponds to 4 years, in the Locals window
- To continue with Step Into, press F8 continually. Observe the Code
Editor and the DOS window
- Continue stepping into code until the DOS window closes
- To start a new project, on the main menu, click File -> New Project
- In the middle list, click Empty Project
- Change the Name to gdcs6 (for Georgetown Dry Cleaning
Services)
- Click OK
- In the Solution Explorer, right-click gdcs6 -> Add -> New Item...
- In the middle list, click Code File
- Change the Name to ClearningOrder and press Enter
- In the empty document, type the following:
using System;
public class OrderProcessing
{
public static int Main()
{
// Price of items
const double PriceOneShirt = 0.95;
const double PriceAPairOfPants = 2.95;
const double PriceOtherItem = 4.55;
const double TaxRate = 0.0575; // 5.75%
// Basic information about an order
string customerName, homePhone;
DateTime orderDate, orderTime;
// Unsigned numbers to represent cleaning items
uint numberOfShirts, numberOfPants, numberOfOtherItems;
// Each of these sub totals will be used for cleaning items
double subTotalShirts, subTotalPants, subTotalOtherItems;
// Values used to process an order
double totalOrder, taxAmount, salesTotal;
double amountTended, moneyChange;
Console.Title = "Watts A Loan?";
Console.Title = "Georgetown Cleaning Services";
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
// Request order information from the user
Console.Write("Enter Customer Name: ");
customerName = Console.ReadLine();
Console.Write("Enter Customer Phone: ");
homePhone = Console.ReadLine();
Console.Write("Enter the order date(mm/dd/yyyy): ");
orderDate = DateTime.Parse(Console.ReadLine());
Console.Write("Enter the order time(hh:mm AM/PM): ");
orderTime = DateTime.Parse(Console.ReadLine());
// Request the quantity of each category of items
Console.Write("Number of Shirts: ");
numberOfShirts = uint.Parse(Console.ReadLine());
Console.Write("Number of Pants: ");
numberOfPants = uint.Parse(Console.ReadLine());
Console.Write("Number of Other Items: ");
numberOfOtherItems = uint.Parse(Console.ReadLine());
// Perform the necessary calculations
subTotalShirts = numberOfShirts * PriceOneShirt;
subTotalPants = numberOfPants * PriceAPairOfPants;
subTotalOtherItems = numberOfOtherItems * PriceOtherItem;
// Calculate the "temporary" total of the order
totalOrder = subTotalShirts +
subTotalPants +
subTotalOtherItems;
// Calculate the tax amount using a constant rate
taxAmount = totalOrder * TaxRate;
// Add the tax amount to the total order
salesTotal = totalOrder + taxAmount;
// Communicate the total to the user...
Console.WriteLine("\nThe Total order is: {0:F}",
salesTotal);
// and request money for the order
Console.Write("Amount Tended? ");
amountTended = double.Parse(Console.ReadLine());
// Calculate the difference owed to the customer
// or that the customer still owes to the store
moneyChange = amountTended - salesTotal;
Console.Clear();
// Display the receipt
Console.WriteLine("====================================");
Console.WriteLine("-/- Georgetown Cleaning Services -/-");
Console.WriteLine("====================================");
Console.WriteLine("Customer: {0}", customerName);
Console.WriteLine("Home Phone: {0}", homePhone);
Console.WriteLine("Order Date: {0:D}", orderDate);
Console.WriteLine("Order Time: {0:t}", orderTime);
Console.WriteLine("------------------------------------");
Console.WriteLine("Item Type Qty Unit/Price Sub-Total");
Console.WriteLine("------------------------------------");
Console.WriteLine("Shirts{0,7}{1,10}{2,10}",
numberOfShirts.ToString(),
PriceOneShirt.ToString("F"),
subTotalShirts.ToString("F"));
Console.WriteLine("Pants{0,8}{1,10}{2,10}",
numberOfPants.ToString(),
PriceAPairOfPants.ToString("F"),
subTotalPants.ToString("F"));
Console.WriteLine("Others{0,7}{1,10}{2,10}",
numberOfOtherItems.ToString(),
PriceOtherItem.ToString("F"),
subTotalOtherItems.ToString("F"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Total Order: {0}",
totalOrder.ToString("F"));
Console.WriteLine("Tax Rate: {0}",
TaxRate.ToString("P"));
Console.WriteLine("Tax Amount: {0}",
taxAmount.ToString("F"));
Console.WriteLine("Net Price: {0}",
salesTotal.ToString("F"));
Console.WriteLine("------------------------------------");
Console.WriteLine("Amount Tended: {0}",
amountTended.ToString("F"));
Console.WriteLine("Difference: {0}",
moneyChange.ToString("F"));
Console.WriteLine("====================================");
System.Console.ReadKey();
return 0;
}
}
When executing a program, you can specify a section or
line where you want the execution to pause, for any reason you judge
necessary. This approach is useful if you have checked code up to a certain
point and it looked alright. If you are not sure about code starting at a
certain point, this can be your starting point.
To execute code up to a certain point
- Right-click the line and click Run to Cursor
- Press Ctrl + F8
Application:
Running to a Point
|
|
- In the code, right-click the salesTotal = totalOrder +
taxAmount; line and click Run To Cursor.
Make sure you can
see the Code Editor, the Locals window, and the DOS window
- When requested, enter the following values. Press Enter after
entering each value. While you are entering them, check the moving
button in the Code Editor and observe the values in the Locals window:
Customer Name: |
Steve Longley |
Customer Phone: |
301-208-2333 |
Order Date: |
04/08/2010 |
Order Time: |
08:14 AM |
Number of Shirts: |
5 |
Number of Pants: |
2 |
Number of Other Items: |
8 |
The focus moves to Microsoft Visual Studio and the Locals window:
- Press F5 to continue
- For the amount tended, type 60 and press Enter
A breakpoint on a line is the code where you want the
exection to suspend. You must explicitly specify that line by creating a
breakpoint. You can as well create as many breakpoints as you want. You can
also remove a breakpoint you don't need anymore.
To create a breakpoint, first identify the line of code
where you want to add it. Then:
- In the left margin corresponding to the line, click
- On the main menu, click Debug -> Toggle Breakpoint
- Right-click the line, position the mouse on Breakpoint, and click
Insert Breakpoint
- Click anything on the line and press F9
A breakpoint is represented by a red circular button
.
After creating a breakpoint, when code executes and reaches that line, it
would pause and let you know by drawing a right-pointing yellow button
.
After using a breakpoint, you can remove it. To delete a
breakpoint:
- Click the breakpoint in the margin
- Right-click the line that has the breakpoint, position the mouse on
Breakpoint, and click Delete Breakpoint
- Click anything on the line that has the breakpoint:
- On the main menu, click Debug -> Toggle Breakpoint
- Press F9
Remember that you can create more than one breakpoint.
If you have more than one breakpoint in your code, execution would pause at
each one of them. At any time, you can remove one or all breakpoints. To
delete all breakpoints, on the main menu, click Debug -> Delete all
Breakpoints.
Application:
Using Breakpoints
|
|
- In the Code Editor, click the margin on the left side of
subTotalOtherItems = numberOfOtherItems * PriceOtherItem;
- On the main menu, click Debug -> Start Debugging.
Notice that the
DOS window displays
- When asked, enter the values as follows and press Enter after each
Customer Name: |
Hermine Simms |
Customer Phone: |
410-573-2031 |
Order Date: |
04/08/2010 |
Order Time: |
09:22 AM |
Number of Shirts: |
3 |
Number of Pants: |
3 |
Number of Other Items: |
12 |
The focus moves back to Microsoft Visual Studio
- Press F5 to continue
- For the amount tended, type 100 and press Enter
- In the code, click the Console.Write("Number of Shirts: ");
line
- On the main menu, click Debug -> Toggle Breakpoint
- In the code, right-click the salesTotal = totalOrder +
taxAmount; line, position the mouse on Breakpoint, and click
Insert Breakpoint
- To start debugging, press F5
- When asked, enter the values as follows and press Enter after each
Customer Name: |
Ginette Rhoads |
Customer Phone: |
301-217-9494 |
Order Date: |
06/11/2010 |
Order Time: |
14:07 |
The focus moves back to Microsoft Visual Studio
- Press F5 to continue
- When asked, enter the values as follows and press Enter after each
Number of Shirts: |
0 |
Number of Pants: |
2 |
Number of Other Items: |
0 |
Order Time: |
14:07 |
The focus moves back to Microsoft Visual Studio
- Press F5 to continue
- For the amount tended, type 20 and press Enter
You can combine the Step Into and/or the Step Over
feature with breakpoints. That is, you can examine each code line after line
until you get to a specific line. This allows you to monitor the values of
variables and see their respective values up to a critical section. To do
this, first create one or more breakpoints, then proceed with steps of your
choice.
Application:
Stepping to Breakpoints
|
|
- Make sure the previous two breakpoints are still selected.
To
start debugging, on the main menu, click Debug -> Step Into. Make
sure you can see the Code Editor, the Locals window, and the DOS window
- Press F8 continually until the DOS window receives focus
- For the customer name, type James Sandt and press Enter
- Press F8 twice to continue
- For the customer phone, type 301-870-7454 and press Enter
The
focus moves back to Microsoft Visual Studio
- Press F8 to continue
- For the order date, type 10/10/10 and press Enter
- Press F8 to continue
- For the order time, type 18:02 and press Enter
- For the number of shirts, enter 8 and press Enter
- Press F8 to continue
- For the number of pants, enter 2 and press Enter
- Press F8 to continue
- For the number of other items, enter 12 and press
Enter
- Press F8 twice to continue
- For the amount tended, type 80 and press Enter
- Continue pressing F8 to the end
- On the main menu, click File -> Close Solution
- When asked whether you want to save, click No
|
|