1. Trang chủ
  2. » Công Nghệ Thông Tin

Visual studio 2010 part 20 ppsx

15 197 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 15
Dung lượng 238,54 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The program is divided into three major parts: a class to hold customer information, a class that will return a list of customers, and the class containing the Main method that runs the

Trang 1

IntelliTrace could be useful if you stepped over a statement that changed the value of

a variable and needed to go back to see what the variable value was before you stepped Figure 6-15 shows this scenario, where the highlighted event, Breakpoint hit: Main, allows you to view Locals or Call Stack The important distinction is that the values shown are for the point in time when that event occurred, not the current time, which can

be very valuable information Another important application of IntelliTrace is to inspect IntelliTrace log files that were produced by another developer or the new Microsoft Test and Lab tool that records a tester’s testing session

You can configure IntelliTrace options by selecting Tools | Options | IntelliTrace IntelliTrace will create a log file that exists as long as VS is running When VS stops, the log file is deleted, so it’s important that you copy this file before shutting down VS The location of the log file is on the Advanced branch of IntelliTrace in Tools | Options

If you receive a log file from another developer, you can load it by selecting File | Open | Open New Then you can view debugging history to view the state of the application during each event of the session

Solving Problems with VS Debugger

Previously, you’ve seen how the VS tools work and gathered a few tips on debugging This section builds upon what you’ve learned and steps you through a couple of real-world scenarios that demonstrate how to use the VS debugger to solve problems: finding and Figure 6-15 The Debug History window

Trang 2

handling bad data and fixing null references The program itself is not particularly

sophisticated, but it contains just enough logic to lead you down a rat hole and show you

how to work your way out First, we’ll look at the program, and then we’ll follow up with

two bug-fixing exercises

A Program with Bugs

The code in this section contains bugs, and it’s important that you type it in as listed or

use the downloadable code for this book from the McGraw-Hill Web site I’ll describe

each piece of code and try not to give away all of the secrets of the bugs just yet Later, I’ll guide you through a process of discovery to find and fix the bugs The program is a search application that takes the first name of a person and searches for that person through a

list of customers If the program finds the customer being searched for, it will print the

customer’s first and last name Otherwise, the program will print a message stating that it

did not find the customer

The program is divided into three major parts: a class to hold customer information,

a class that will return a list of customers, and the class containing the Main method that

runs the program The following sections describe each of these classes

The Customer Class

Any time you are working with data, you’ll have a class to hold that data Since this

application works with customers, the natural approach is to have a Customer class,

as follows:

C#:

public class Customer

{

public string FirstName { get; set; }

public string LastName { get; set; }

}

VB:

Public Class Customer

Property FirstName As String

Property LastName As String

End Class

This is the minimal information required for this demo, and any class that you build

will have more properties Notice that both properties are type string

Trang 3

The CustomerRepository Class

In this program, we create a class that is solely responsible for working with data This is a

common pattern, which is called the Repository pattern The following CustomerRepository class has a method that returns a list of Customer objects:

C#:

using System.Collections.Generic;

public class CustomerRepository

{

public List<Customer> GetCustomers()

{

var customers = new List<Customer>

{

new Customer

{

FirstName = "Franz",

LastName = "Smith"

},

new Customer

{

FirstName = "Jean "

},

new Customer

{

FirstName = "Wim",

LastName = "Meister"

}

};

return customers;

}

}

VB:

Public Class CustomerRepository

Public Function GetCustomers() As List(Of Customer)

Dim customers As New List(Of Customer) From

{

New Customer With

{

FirstName = "Franz",

LastName = "Smith"

},

New Customer With

Trang 4

{

FirstName = "Jean "

},

New Customer With

{

FirstName = "Wim",

LastName = "Meister"

}

}

Return customers

End Function

End Class

The GetCustomers method returns a List<Customer> (List(Of Customer) in VB) For

the purposes of this discussion, how the GetCustomers method works won’t matter Such

a method could easily get customers from a database, Web service, or other object For

simplicity, GetCustomers initializes a List with Customer objects The part of this method

that is particularly important is the customer whose FirstName property is set to “Jean ”

Notice the blank space appended to the name, which is required to make this scenario

behave as designed (i.e., to intentionally create a bug) It’s also conspicuous that the

Customer object with a FirstName property set to “Jean ” also does not have a LastName.

The Program with Bugs

The following is a search program that uses CustomerRepository to get a list of Customer

objects The logic will iterate through the results, checking to see if the result is equal

to the search term When the result is equal, the program prints the full name of the

customer If no matching customers are found, the program indicates that the customer

wasn’t found:

C#:

using System;

class Program

{

static void Main()

{

var custRep = new CustomerRepository();

var customers = custRep.GetCustomers();

var searchName = "Jean";

bool customerFound = false;

Trang 5

foreach (var cust in customers)

{

// 1 First Bug

if (searchName == cust.FirstName)

{

Console.WriteLine(

"Found: {0} {1}",

cust.FirstName,

cust.LastName);

customerFound = true;

}

}

if (!customerFound)

{

Console.WriteLine("Didn't find customer."); }

Console.ReadKey();

}

}

VB:

Module Module1

Sub Main()

Dim custRep As New CustomerRepository

Dim customers As List(Of Customer)

customers = custRep.GetCustomers()

Dim searchName As String = "Jean"

Dim customerFound As Boolean = False

For Each cust As Customer In customers

' 1 First Bug

If (searchName = cust.FirstName) Then Console.WriteLine(

"Found: {0} {1}",

cust.FirstName,

cust.LastName)

customerFound = True

End If

Next

Trang 6

If (customerFound = False) Then

Console.WriteLine("Didn't find customer.")

End If

Console.ReadKey()

End Sub

End Module

Notice that the searchName variable is set to “Jean” Within the loop, the searchName

is compared with the FirstName property of each Customer instance for equality Here’s

the output from when the program runs:

Didn't find customer.

What is supposed to happen is that the program should find the matching record and

print it out, but that’s not what happens Here is the first bug, and the following discussion describes how to find the cause of the bug using the VS debugger

Finding the Bug

At this point, we know there is a bug and it’s reproducible, meaning that we can use VS

to debug and find the cause of the problem In this situation, the program is saying that it

didn’t find a Customer record or, in other words, there is no record with a FirstName of

Jean However, we know for a fact that the data does include a customer whose FirstName

is Jean We need to find out why the program cannot find it The following steps show

how the VS debugger can help isolate the problem

1. Start by setting a breakpoint on the foreach loop in the Main method This wasn’t an

arbitrary decision Instead, considering the nature of the problem, I selected a part of

the program that is likely to begin providing a cue to what the problem is Looking at

the program, one of the reasons that the program might not find the searchName is that

we aren’t getting data, causing the program to not execute the body of the foreach loop

2 Press F5 to run the program in debug mode This will execute the program and make it

stop on the foreach loop, making it possible to look at program state

3.After VS hits the breakpoint, hover over customers to see if there are any values

You’ll observe that customers does have three values The fact that there are customers

indicates that the foreach loop is executing and we’ve eliminated that as a possibility

Trang 7

4. Next, set a breakpoint on the if statement, right-click the breakpoint, and set the

condition as follows:

C#:

cust.FirstName == "Jean"

VB:

cust.FirstName = "Jean"

The goal here is to see what happens when the if statement finds the record matching the searchName At this point, we’re assuming that Jean does exist in the data Working

with a small program, you can use windows such as Autos, Locals, or Watch to find this record However, many real-world scenarios will give you a list with many more records Therefore, rather than waste time drilling down through dozens of records, use the VS debugger to help find the record quickly Keep in mind that all the best plans don’t always work out, as you’ll soon see, but the primary point is taking the most productive step first Setting a conditional breakpoint demonstrates how you can set conditions that can avoid eating up time caused by stepping through loops

5 Press F5 to run the program You expect to hit the breakpoint, but that won’t happen

Confusing? We know that there isn’t anything wrong with the logic, because the if

statement condition is a simple equality operator Perhaps we’ve looked in the database

or whatever source the data came from, but it’s given in this scenario that Jean is definitely in the data However, this illustrates a common problem where the quality of data you work with is less than desired

6. This time, change the breakpoint condition on the if statement as follows and re-run the

program:

C#:

cust.FirstName.Contains("Jean")

VB:

cust.FirstName.Contains("Jean")

Remember, we suspect bad data, so the call to Contains on the string assumes that there

might be some extraneous white space or other characters around the name in the data

Hover over cust.FirstName or look at cust in one of the debug windows to verify it is

the record you are looking for This breakpoint will pause on any records that contain

the sequence of characters “Jean”, such as Jean-Claude So, you might have multiple

matches that aren’t what you want The benefit is that the number of records you must

Trang 8

look at is much fewer and you can save time If you have multiple records, you can

press F5 and the breakpoint will pause on each record, allowing you to inspect the

value In this case, the record set is so small that we hit the right record immediately

7 Press F10 to step over the if condition This will tell us whether the condition is being

evaluated properly In this case, VS does not step into the if statement but instead

moves to the end of the if statement, meaning that searchName and cust.FirstName are

not equal This means you need to take a closer look at cust.FirstName to see what the

problem is with the data

8.Next, we’ll use a couple of the VS debugger tools to inspect cust.FirstName and find

out why the equality check is not working Open the Immediate window (CTRL-D, I) and execute the following expression:

cust.FirstName

which will return this:

"Jean "

Here, you can see that the result has a trailing space—dirty data Clearly, “Jean” does

not equal “Jean ” because of the extra character in the data There are various

non-printable characters that could show up, and VS can help here too

9.Open a Memory window (CTRL-D, Y), type cust.FirstName into the Address box, and

press ENTER This will show the hexadecimal representation of the data at the memory

location of the variable, shown in Figure 6-16

The layout of the Memory window starts with an address on the left, which is

scrolled down to the line where the data in cust.FirstName variable first appears

In the middle is the hex representation of the data The final column has a readable

Figure 6-16 The Memory window

Trang 9

representation of the data where any characters that don’t have a readable representation

appear as dots You can see “.J.e.a.n.” on the first line of the third column .NET

characters are 16-bit Unicode, and the data for the character only fills the first byte, resulting in the second byte being set to 00, causing the dots between characters you see in the first column If the data used another character set, such as Japanese Kanji, you would see data in both bytes of the character The hex representation of this data

in the second column is “00 4a 00 65 00 61 00 6e 00 20” Looking at the Unicode

representation, which you can find at http://unicode.org/, you’ll see that the hex and visual representation of the characters match

You can see that I’ve highlighted the 00 20 at the end of the first line of the second column in Figure 6-16, which proves that Jean is followed by a Unicode space character

Knowing this information might help you share information with someone who is responsible for the data, letting them know that there are extraneous spaces in the data Some computer or software systems might even use other types of characters, perhaps

a proprietary delimiter for separating data, and accidentally save the data with the delimiter

Fixing the First Bug

While you might have bad data and it might not be your fault, the prospect of fixing the problem by fixing the data source is often illusive, meaning that you need to apply a fix

in your code In this section, we’ll apply a fix However, we’ll put a convoluted twist in the solution where we discover a new bug when fixing the first The purpose is twofold:

to illustrate the real-world fact that there are often multiple problems with a given piece of code and to show a completely different type of bug that you will encounter when writing your own code The following steps lead you through the fix and subsequent discovery of the new bug:

1 Press SHIFT-F5 to stop the previous debugging session

2. Implement a fix by commenting out the contents of the foreach loop and replacing with

code that protects against extraneous spaces in the data, as follows:

C#:

var firstName = cust.FirstName.Trim();

var lastName = cust.LastName.Trim();

if (searchName == cust.FirstName)

Trang 10

{

Console.WriteLine(

"Found: {0} {1}",

firstName,

lastName);

customerFound = true;

}

VB:

Dim firstName As String = cust.FirstName.Trim()

Dim lastName As String = cust.LastName.Trim()

If (searchName = cust.FirstName) Then

Console.WriteLine(

"Found: {0} {1}",

cust.FirstName,

cust.LastName)

customerFound = True

End If

Next

Notice that the fix was to use the string.Trim method to remove the extraneous space

from the data, assigning the clean results to local variables Trim defaults to using the

space character but has overloads that allow you to specify a different character, just in

case the actual character you saw in Figure 6-16 was something other than a space The rest of the logic uses variables with the clean data

3.Press F5 to run the program and see if the fix works Unfortunately, you’re stopped in

your tracks by the fact that a new error occurs: a NullReferenceException Unlike runtime

errors that give you wrong data, VS helps greatly by breaking on exceptions when they

occur in the code The next section describes this error, the NullReferenceException, in

greater detail and provides information to help you deal with the problem when it occurs

in your programs

Debugging and Resolving

NullReferenceException Problems

Encountering a NullReferenceException in your code is a common occurrence, deserving

some discussion to help you deal with these problems effectively As described in Step 3

in the preceding section, VS will pause on a NullReferenceException when running

Ngày đăng: 04/07/2014, 03:20