
That was posted on Twitter today when I
announced that I was working on this very blog entry. Well, I've got news for
Mr. Justin "X-mas-Hater" Kohnen.
X-mas isn't over until the fat... uhhh... lady sings. (Hmmm... that worked out
much better in my head.)
While X-mas day has come and
gone, the holiday season continues. I have enough verses left in my song to
ensure that our merry-making runs all the way 'til the new year.
"On the eighth day of X-mas my true love (DevExpress)
gave to me..."
Bread-and-Butter Refactorings in Query Expressions
Since LINQ is such a big part of what
C#
3.0 and
Visual Basic 9 are all about, I thought that showing two more
examples of refactorings that can be used in query expressions would be useful. The refactorings
we'll look at do not target query expressions specifically. Instead, these
are pre-existing, bread-and-butter refactorings that have been updated to support query
expressions properly.
What's a "bread-and-butter refactoring" you ask? It's one
of those refactorings that you can't live without—a part of your everyday
arsenal. It's important to know that these crucial refactorings work with the
latest and greatest language features.
OK, let's get started!
public static int SumOfEvenSquares(int count)
{
return (from number in Enumerable.Range(1, count)
where (number % 2) == 0
select number * number).Sum();
}
There are a number of refactorings that we could apply to the LINQ code above. First,
let's use Introduce Local to generate a new local variable assigned to the query
expression. This is easy enough to do. Just select the query expression,
press the Refactor key (CTRL+` by default), choose Introduce Local, and press
ENTER. Below is a screenshot of the preview hint for Introduce Local.

The More You Know
If you are unfamiliar with
Refactor! Pro's
preview hints, they are sort of like windows into the future. A preview hint shows what a refactoring will do before you apply it. This
feature provides the advantage you need to refactor your code
with confidence.
After naming the new local variable, our refactored code looks like so:
public static int SumOfEvenSquares(int count)
{
IEnumerable<int> evenSquares = from number in Enumerable.Range(1, count)
where (number % 2) == 0
select number * number;
return evenSquares.Sum();
}
View Screencast of
Introduce Local in Action!
I would be remiss if I didn't mention that there is another way to use Introduce Local.
In addition to pressing the Refactor key, it is also possible to apply the
refactoring using cut-and-paste. 99% of the time, when cutting an expression to
the clipboard and pasting it within the same method on an empty line above the
cut location, the user's intention is to create
a local variable assigned to that expression.
Refactor! Pro takes advantage of
this knowledge to anticipate the user's intent and automatically apply
Introduce Local.
View Screencast of Introduce Local Using Cut-And-Paste!
One of the red flags that some have raised against query expressions is their
potential to cause code duplication. For example, the expressions in the where
and select clauses from the sample
code above really should be extracted to new
methods. That way, we promote code reuse. If not, we are doomed to write the
same tiny, bite-sized expressions over and over. Fortunately,
Refactor! Pro's
Extract Method refactoring works perfectly on these expressions. With Extract
Method, we can easily turn the code above into:
private static IEnumerable<int> GetNaturals(int count)
{
return Enumerable.Range(1, count);
}
private static bool IsEven(int number)
{
return (number % 2) == 0;
}
private static int Square(int number)
{
return number * number;
}
public static int SumOfEvenSquares(int count)
{
IEnumerable<int> evenSquares = from number in GetNaturals(count)
where IsEven(number)
select Square(number);
return evenSquares.Sum();
}
Believe it or not, using
Refactor! Pro, I'm able to
produce that code in
just 42 keystrokes—including 23 keystrokes for the method names and 12
for navigation and selection. That means that only seven
keystrokes are actually needed to apply
three Extract Method refactorings!
Curious? View the Screencast of Extract Method in Action!
Finally, I must mention that Extract Method can be used with
cut-and-paste just like Introduce Local. That's right, you can cut code to the
clipboard and paste it on an empty line outside of a method. Extract Method
will take over. Again,
Refactor! Pro
is working hard to anticipate your intentions.
View the Screencast of Extract Method Using Cut-And-Paste!
And thus ends the eighth verse of my song. Today we've looked at how two bread-and-butter refactorings, Introduce Local and Extract Method, can be
used within LINQ expressions. The coolest thing is that all of the screencasts
were recorded using
Visual Studio
2008. They aren't mock ups of future features. These refactorings work
with query expressions this very minute!
My Visual Basic friends might be a little worried because I didn't show these
refactorings working in Visual Basic. Well, rest assured, the refactorings
work fine. In fact, they work using the same keystrokes!
Now, that's what I call an
X-mas present.