Tuesday, February 10, 2009

ReSharper Recipe: Move Method

Its a shame that ReSharper does not support moving a method directly. It's not hard to do in sequence but it does take a few extra seconds.

Move Method

The fastest way to move a method is to use “Make Method Static” followed by “Make Method Non-Static”. But first, some sample code to work with...

The Car class:

public class Car
{
public CarEngine Engine;

public Car()
{
Engine = new CarEngine(4, 0.5f);
}

public float ComputeEngineVolume()
{
return
Engine.LitersPerCylinder *
Engine.NumCylinders;
}
}

The CarEngine class:

public class CarEngine
{
public float LitersPerCylinder;
public int NumCylinders;

public CarEngine(int numCylinders,
float litersPerCylinder)
{
NumCylinders = numCylinders;
LitersPerCylinder = litersPerCylinder;
}
}

Calling code:

Car c = new Car();
float volume = c.ComputeEngineVolume();

Clearly, the ComputeEngineVolume method belong to the CarEngine class and not to the Car class. To move the method we’ll use two steps, first we'll use the "Make Method Static" refactoring on the ComputeEngineVolume method. You should make sure that you get the target object as a input parameter to the static method. CarEngine in this case. The resulting code is:

Car class:

public class Car
{
...

    public static float ComputeEngineVolume(
CarEngine engine)
{
return
engine.LitersPerCylinder *
engine.NumCylinders;
}
}

Calling code

Car c = new Car();
float volume = Car.ComputeEngineVolume(c.Engine);


The next step is to use the "Make Method Non-Static" refactoring to move the method to its new home, the CarEngine class. In the dialog, select the appropriate target class and let ReSharper do its work.

The Car class:

public class Car
{
public CarEngine Engine;

public Car()
{
Engine = new CarEngine(4, 0.5f);
}
}

The CarEngine class:

public class CarEngine
{
...

public float ComputeEngineVolume()
{
return
LitersPerCylinder *
NumCylinders;
}
}

And the calling code:

Car c = new Car();
float volume = c.Engine.ComputeEngineVolume();

A final touch would probably be to refactor the ComputeEngineVolume method into a Volume property but we’ll leave it for now.

Tweaks

If you want to have a bit more control over the process you could initiate it by using a “Introduce Parameter” refactoring to hand pick the target class. This is useful if you have a more complex scenario then the simple property used here.