: C# 2008 Programmer

Refactoring Support

Refactoring Support

Another useful feature available in Visual Studio 2008 is code refactoring. Even though the term may sound unfamiliar, many of you have actually used it. In a nutshell, code refactoring means restructuring your code so that the original intention of the code is preserved. For example, you may rename a variable so that it better reflects its usage. In that case, the entire application that uses the variable needs to be updated with the new name. Another example of code refactoring is extracting a block of code and placing it into a function for more efficient code reuse. In either case, you would need to put in significant amount of effort to ensure that you do not inadvertently inject errors into the modified code. In Visual Studio 2008, you can perform code refactoring easily. The following sections explain how to use this feature.

Rename

Renaming variables is a common programming task. However, if you are not careful, you may inadvertently rename the wrong variable (most people use the find-and-replace feature available in the IDE, which is susceptible to wrongly renaming variables). In C# refactoring, you can rename a variable by selecting it, right-clicking, and choosing Refactoring?Rename (see Figure 2-44).


Figure 2-44

You are prompted for a new name (see Figure 2-45). Enter a new name, and click OK.


Figure 2-45

You can preview the change (see Figure 2-46) before it is applied to your code.


Figure 2-46

Click the Apply button to change the variable name.

Extract Method

Very often, you write repetitive code within your application. Consider the following example:

private void Form1_Load(object sender, EventArgs e) {
int num = 10, sum = 0;
for (int i = 1; i <= num; i++) {
sum += i;
}
}

Here, you are summing up all the numbers from 1 to num, a common operation. It would be better for you to package this block of code into a function. So, highlight the code (see Figure2-47), right-click it, and select Refactor?Extract Method.


Figure 2-47

Supply a new name for your method (see Figure 2-48). You can also preview the default method signature that the refactoring engine has created for you. Click OK.


Figure 2-48

The block of statements is now encapsulated within a function and the original block of code is replaced by a call to that function:

private void Form1_Load(object sender, EventArgs e) {
Summation();
}
private static void Summation() {
int num = 10, sum = 0;
for (int i = 1; i <= num; i++) {
sum += i;
}
}

However, you still need to do some tweaking because the variable sum should be returned from the function. The code you highlight will affect how the refactoring engine works. For example, if you include the variables declaration in the highlighting, a void function is created.

While the method extraction feature is useful, you must pay close attention to the new method signature and the return type. Often, some minor changes are needed to get what you want. Here's another example:

Single radius = 3.5f;
Single height = 5;
double volume = Math.PI * Math.Pow(radius, 2) * height;

If you exclude the variables declaration in the refactoring (instead of selecting all the three lines; see Figure 2-49) and name the new method VolumeofCylinder, a method with two parameters is created:

private void Form1_Load(object sender, EventArgs e) {
Single radius = 3.5f;
Single height = 5;
double volume = VolumeofCylinder(radius, height);
}
private static double VolumeofCylinder(Single radius, Single height) {
return Math.PI * Math.Pow(radius, 2) * height;
}


Figure 2-49

Here are some observations:

?Variables that are defined outside of the highlighted block for refactoring are used as an input parameter in the new method.

?If variables are declared within the block selected for refactoring, the new method will have no signature.

?Values that are changed within the block of highlighted code will be passed into the new method by reference.

Reorder and Remove Parameters

You can use code refactoring to reorder the parameters in a function. Consider the following function from the previous example:

private static double VolumeofCylinder(Single radius, Single height) {
return Math.PI * Math.Pow(radius, 2) * height;
}

Highlight the function signature, right-click it, and select Refactor?Reorder Parameters (see Figure2-50).


Figure 2-50

You can then rearrange the order of the parameter list (see Figure 2-51).


Figure 2-51

Click OK. You can preview the changes before they are made (see Figure 2-52).


Figure 2-52

Once you click the Apply button, your code is changed automatically:

private void Form1_Load(object sender, EventArgs e) {
Single radius = 3.5f;
Single height = 5;
double volume = VolumeofCylinder(height, radius);
}
private static double VolumeofCylinder(Single height, Single radius) {
return Math.PI * Math.Pow(radius, 2) * height;
}

All statements that call the modified function will have their arguments order changed automatically.

You can also remove parameters from a function by highlighting the function signature, right-clicking, and selecting Refactor?Remove Parameters. Then remove the parameter(s) you want to delete (see Figure 2-53). All statements that call the modified function will have their calls changed automatically.


Figure 2-53

Encapsulate Field

Consider the following string declaration:

namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public string caption;
private void Form1_Load(object sender, EventArgs e) {
//...
}
}
}

Instead of exposing the caption variable as public, it is a better idea to encapsulate it as a property and use the set and get accessors to access it. To do that, right-click on the caption variable and select Refactor?Encapsulate Field (see Figure 2-54).


Figure 2-54

Assign a name to your property (see Figure 2-55). You have the option to update all external references or all references (including the one within the class), and you can choose to preview your reference changes. When you're ready, click OK.


Figure 2-55

After you've previewed the changes (see Figure 2-56), click Apply to effect the change.


Figure 2-56

Here is the result after applying the change:

namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
private string caption;
public string Caption {
get { return caption; }
set { caption = value; }
}
private void Form1_Load(object sender, EventArgs e) {
//...
}
}
}

Extract Interface

You can use the refactoring engine to extract an interface from a class definition. Consider the following Contact class:

namespace WindowsFormsApplication1 {
class Contact {
public string FirstName {
get; set;
}
public string LastName {
get; set;
}
public string Email {
get; set;
}
public DateTime DOB {
get; set;
}
}
}

Right-click the Contact class name and select Refactor?Extract Interface (see Figure 2-57).


Figure 2-57

The Extract Interface dialog opens, and you can select the individual public members to form the interface (see Figure 2-58).


Figure 2-58

The new interface is saved in a new .cs file. In this example, the filename is IContact.cs:

using System;
namespace WindowsFormsApplication1 {
interface IContact {
DateTime DOB { get; set; }
string Email { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
}
}

The original Contact class definition has now been changed to implements the newly created interface:

class Contact : WindowsFormsApplication1.IContact {
public string FirstName
...

Promote Local Variable to Parameter

You can promote a local variable into a parameter. Here's an example:

private void Form1_Load(object sender, EventArgs e) {
LogError("File not found.");
}
private void LogError(string message) {
string SourceFile = "Form1.cs";
Console.WriteLine(SourceFile + ": " + message);
}

You want to promote the variable SourceFile into a parameter so that callers of this function can pass in its value through an argument. To do so, select the variable SourceFile, right-click, and then select Refactor?Promote Local Variable to Parameter (see Figure 2-59).


Figure 2-59

Note that the local variable to be promoted must be initialized or an error will occur. The promoted variable is now in the parameter list and the call to it is updated accordingly:

private void Form1_Load(object sender, EventArgs e) {
LogError("File not found.", "Form1.cs");
}
private void LogError(string message, string SourceFile) {
Console.WriteLine(SourceFile + ": " + message);
}


: 1.079. /Cache: 3 / 0