Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Visual Studio 2005 (2006) [eng]

.pdf
Скачиваний:
117
Добавлен:
16.08.2013
Размер:
21.9 Mб
Скачать

Chapter 21

original method and selecting Extract Method from the context menu. In C#, this will prompt you to enter a new method name, as shown in Figure 21-5. If there are variables within the block of code to be extracted that were used earlier in the original method, they will automatically appear as variables in the method signature. Once the name has been confirmed, the new method will be created immediately after the original method. A call to the new method will replace the extracted code block.

Figure 21-5

For example, in the following code snippet, if you wanted to extract the conditional logic into a separate method, then you would select the code, shown with a gray background, and choose Extract Method from the right-click context menu:

private void button1_Click(object sender, EventArgs e)

{

string output = Properties.Settings.Default.AdventureWorksCS; if (output == null)

{

output = “DefaultConnectionString”;

}

MessageBox.Show(output);

/* ... Much longer method ... */

}

This would automatically generate the following code in its place:

Private void button1_Click(object sender, EventArgs e)

{

string output = Properties.Settings.Default.AdventureWorksCS; output = ValidateConnectionString(output); MessageBox.Show(output);

}

private static string ValidateConnectionString(string output)

{

if (output == null)

{

output = “DefaultConnectionString”;

}

return output;

}

276

Refactoring

Refactor! handles this refactoring action slightly differently. After you select the code you want to replace, Refactor! prompts you to select a place in your code where you want to insert the new method. This can help developers organize their methods in groups, either alphabetically or according to functionality. Figure 21-6 illustrates the aid that appears to enable you to position, using the cursor keys, the insert location.

Figure 21-6

After selecting the insert location, Refactor! will insert the new method, giving it an arbitrary name. In doing so it will highlight the method name, enabling you to rename the method either at the insert location or where the method is called (see Figure 21-7).

Figure 21-7

Encapsulate Field

Another common task when refactoring is to encapsulate an existing class variable with a property. This is what the Encapsulate Field refactor action does. To invoke this action, select the variable you want to encapsulate and select the appropriate refactor action from the context menu. This will give you the opportunity to name the property and elect where to search for references to the variable, as shown in Figure 21-8.

The next step after specifying the new property name is to determine which references to the class variable should be replaced with a reference to the new property. Figure 21-9 shows the preview window that is returned after the reference search has completed. In the top pane is a tree indicating which files and methods have references to the variable. The checkbox beside each row indicates whether a replacement will be made. Selecting a row in the top pane brings that line of code into focus in the lower pane. Once each of the references has been validated, the encapsulation can proceed. The class variable is updated to be private, and the appropriate references are updated as well.

277

Chapter 21

Figure 21-8

The Encapsulate Field refactoring action using Refactor! works in a similar way, except that it automatically assigns the name of the property based on the name of the class variable. The interface for updating references is also different, as shown in Figure 21-10. Instead of a modal dialog, Refactor! presents a visual aid that can be used to navigate through the references. Where a replacement is required, click the check mark. Unlike the C# dialog box, in which the checkboxes can be checked and unchecked as many times as needed, once you click the check mark, there is no way to undo this action.

Figure 21-9

Figure 21-10

278

Refactoring

Extract Interface

As a project goes from prototype or early-stage development through to a full implementation or growth phase, it is often necessary to extract the core methods for a class into an interface to enable other implementations or to define a boundary between disjointed systems. In the past you could do this by copying the entire method to a new file and removing the method contents so you were just left with the interface stub. The Extract Interface refactoring action enables you to extract an interface based on any number of methods within a class. When this refactoring action is invoked on a class, the dialog in Figure 21-11 is displayed, which enables you to select which methods are included in the interface. Once selected, those methods are added to the new interface. The new interface is also added to the original class.

Figure 21-11

In the following example, the first method needs to be extracted into an interface:

public class ConcreteClass1

{

public void ShouldBeInInterface() { /* ... */ }

public void NormalMethod(int ParameterA, string ParameterB) { /* ... */ }

public void AnotherNormalMethod() { /* ... */ }

}

Selecting Extract Interface from the right-click context menu will introduce a new interface and update the original class as follows:

interface IConcreteClass11

{

void ShouldBeInInterface();

}

279

Chapter 21

public class ConcreteClass1 : ConnectionCCharpTest.IConcreteClass11

{

public void ShouldBeInInterface() { /* ... */ }

public void NormalMethod(int ParameterA, string ParameterB) { /* ... */ }

public void AnotherNormalMethod() { /* ... */ }

}

Extracting an interface is not available within Refactor!.

Reorder Parameters

Sometimes it is necessary to reorder parameters. This is often for cosmetic reasons, but it can also aid readability and is sometimes warranted when implementing interfaces. The Reorder Parameters dialog, shown in Figure 21-12, enables you to move parameters up and down in the list according to the order in which you wish them to appear.

Figure 21-12

Once you establish the correct order, you’re given the opportunity to preview the changes. By default, the parameters in every reference to this method will be reordered according to the new order. The preview dialog, similar to the one shown in Figure 21-9, enables you to control which references are updated.

The Refactor! interface for reordering parameters is one of the most intuitive on the market. Again, Design Express has opted for visual aids instead of a modal dialog, as shown in Figure 21-13. You can move the selected parameter left or right in the parameter list and navigate between parameters with the Tab key. Once the parameters are in the desired order, the search and replace interface illustrated in Figure 21-10 enables the developer to verify all updates.

280

Refactoring

Figure 21-13

Remove Parameters

It is unusual to have to remove a parameter while refactoring, as it usually means that the functionality of the method has changed. However, having support for this action considerably reduces the amount of searching that has to be done for compile errors that can occur when a parameter is removed. The other time this action is particularly useful is when there are multiple overloads for a method. Removing a parameter may not generate compile errors; however, there may be runtime errors caused by semantic, rather than syntactical, mistakes.

Figure 21-14 illustrates the Remove Parameters dialog that is used to remove parameters from the parameters list. If a parameter is accidentally removed, it can be easily restored until the correct parameter list is arranged. As the warning on this dialog indicates, removing parameters can often result in unexpected functional errors, so it is important to review the changes made. Again, the preview window can be used to validate the proposed changes.

Figure 21-14

You cannot remove a parameter with Refactor!.

281

Chapter 21

Rename

Visual Studio 2005 provides rename support in both C# and VB.NET. The rename dialog for C# is shown in Figure 21-15; it is similar in VB.NET.

Figure 21-15

Unlike the C# rename support, which uses the preview window so you can confirm your changes, the rename capability in VB.NET simply renames all references to that variable.

Promote to Paramet4er

One of the most common refactoring techniques is to adapt an existing method to accept an additional parameter. By promoting a method variable to a parameter, the method can be made more general. It also promotes code reuse. Intuitively, this operation would introduce compile errors wherever the method was referenced. However, the catch is that the variable you are promoting to a parameter must have an initial constant value. This constant is added to all the method references to prevent any changes to functionality. Starting with the following snippet, if the method variable output is promoted, then you end up with the second snippet:

public void MethodA()

{

MethodB();

}

public void MethodB()

{

string output = “Test String”; MessageBox.Show( output);

}

After the variable is promoted, you can see that the initial constant value has been applied where this method is referenced:

public void MethodA()

{

MethodB(“Test String”);

}

public void MethodB(string output)

282

Refactoring

{

MessageBox.Show( output);

}

Promoting a variable to a parameter is not available within Refactor!.

Generate Method Stub

As you write code, you may realize that you need a method that generates a value, triggers an event, or evaluates an expression. For example, the following snippet illustrates a new method that you need to generate at some later stage:

public void MethodA()

{

string InputA;

double InputB;

int OutputC = NewMethodIJustThoughtOf(InputA, InputB);

}

Of course, the preceding code will generate a build error because this method has not been defined. Using the Generate Method Stub refactoring action, you can generate a method stub. As you can see from the following sample, the method stub is complete with input parameters and output type:

private int NewMethodIJustThoughtOf(string InputA, double InputB)

{

throw new Exception(“The method or operation is not implemented.”);

}

Generating a method stub is not available within Refactor!.

Surround with Snippet

The last refactoring action, available in both C# and VB.NET, is the capability to surround an existing block of code with a code snippet. Figure 21-16 shows the list of surrounding snippets that are available to wrap the selected line of code.

Figure 21-16

Selecting the tryf snippet results in the following code:

283

Chapter 21

public void MethodB(string output)

{

try

{

MessageBox.Show(output);

}

finally

{ /* ... */ }

}

Summar y

This chapter provided examples of each of the refactoring actions available within Visual Studio 2005. Although VB.NET developers do not get complete refactoring support out of the box, Refactor! provides a wide range of refactoring actions that complement the editor they already have.

284

Generics, Nullable Types,

and Par tial Types

When the .NET Framework was initially released, many C++ developers cited the lack of code templates as a primary reason for not moving to one of the .NET languages. Visual Studio 2005 and the .NET Framework 2.0 introduce generics, which are more than simply design-time templates, as they offer first-class support within the CLR. This chapter explores the syntax, in both C# and VB.NET, for consuming and creating generics. The chapter also looks at nullable types, which help bridge the logical gap between database and object data; partial types, which help effectively partition code to promote code generation; and operator overloading.

Generics

For anyone unfamiliar with templates in C++ or the concept of a generic type, this section begins with a simple example that illustrates where a generic can replace a significant amount of coding, while also maintaining strongly typed code. This example stores and retrieves integers from a collection. As you can see from the following code snippet, there are two ways to do this: either using a non-typed ArrayList, which can contain any type, or using a custom-written collection:

‘Option 1 – Non-typed Arraylist

‘Creation - unable to see what types this list contain Dim nonTypedList As New ArrayList

‘Adding - no type checking, so can add any type nonTypedList.Add(1)

nonTypedList.Add(“Hello”)

nonTypedList.Add(5.334)

‘Retrieving - no type checking, must cast (should do type checking too) Dim output As Integer = CInt(nonTypedList.Item(1))

‘Option 2 – Strongly typed custom written collection