Saturday, October 24, 2009

Now that Visual Studio 2010 Beta 2 is finally out the door, I’ve had a bit more time to spend coding on some of my personal projects. Yesterday, I happened upon a cool trick while using the new Generate from Usage feature. It was so helpful to me that I thought others might benefit, so I’m sharing it here.

The Anonymous Type Problem

When you need to project some data from a LINQ expression, anonymous types can be enormously convenient.

C# Query

Because anonymous types are… well… anonymous, they don’t have names that can be expressed in code. This is problematic if you want to expose an anonymous type as the return type of a function. I have run into this problem many times. When refactoring code, it’s easy to get into a situation like the one below.

Broken C# Function

So, how can you get around this problem? Well, there a few possibilities.

  1. You could replace ??? with object and use reflection to get at the properties. (Yuck!)
  2. You could make the function generic and add a parameter to “mumble” the anonymous type.1 (Awkward!)
  3. Assuming C# 4.0, you could replace ??? with dynamic.2 (No compiler errors!)

Because none of these solutions is particularly savory, most of us are forced to create a new named type to replace the anonymous type. Thankfully, there are some fantastic third-party refactoring tools out there that can automate this tedious process, but if you don’t use one of these tools you’re stuck writing the code by hand.

Actually, no, that’s not quite true.

Generate from Usage to The Rescue!

In Visual Studio 2010, the new Generate from Usage feature makes the task of coding up new classes a snap! Just type a new name for the anonymous type in the editor, making the code look like a type constructor followed by an object initializer. Then, press Ctrl+. to expand the smart tag that immediately appears and choose the first suggestion to generate a new class.

Generate Class

Next, expand each smart tag in the object initializer to generate each property.

Generate Property

When you’re finished, you should have a brand new class containing each property, declared as auto-implemented properties. Cool!

Generated Class

For Visual Basic coders, Generate from Usage is even easier. Let’s start with the same LINQ expression in VB. (Notice the lack of the “_” line continuation characters. Hooray for VB10 implicit line continuation!)

VB Query

Just like before, type the name of the new type that you wish to generate and press Ctrl+. to expand the smart tag. After choosing the first suggestion from the smart tag, you’re finished. The VB Generate Class feature will drill into the object initializer and generate all of the necessary properties at the same time that the class is generated.

VB Generate Class

Wrapping Up

Of course, this technique is not without flaws.

  • The resulting type is not immutable like the anonymous type that you’re replacing. To address this, you can easily modify the generated properties to be read-only.
  • The new type does not have the same structural equality semantics that anonymous types have. In practice, I’ve rarely run into an bug caused by anonymous type structural equality, but if this is a concern for you, use one of the excellent third-party tools that account for these differences.

 

1See Wes Dyer's excellent article for an example of this clever trick.
2Check out Bill Wagner's post for details.

posted on Saturday, October 24, 2009 10:01:40 AM (Pacific Standard Time, UTC-08:00)  #    Comments [5]

kick it on DotNetKicks.com
 Saturday, March 14, 2009

In Visual Basic .NET, there are several cases in which the statement completion list will present the user with a list of values rather than the standard completion set. Most often, this occurs when assigning to a variable of one of the common System.Drawing types, Color, Brush or Pen.

Value Completion List

At first glance, the screenshot above might seem as if the Visual Basic IDE has hard-coded a set of values into IntelliSense, but that’s not the case. In fact, this is caused by a seldom-used feature of XML Documentation that is supported by Visual Basic .NET, but isn’t currently supported by C#1. By cracking open the the XML Documentation file for System.Drawing.dll (located at C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\System.Drawing.xml on my machine), we’ll see a curious XML tag on the System.Drawing.Color definition.

<member name="T:System.Drawing.Color">
  <
summary>Represents an ARGB (alpha, red, green, blue) color.</summary>
  <
filterpriority>1</filterpriority>
  <completionlist cref="T:System.Drawing.Color" />
</
member>

The highlighted completionlist tag above is used by Visual Basic to populate the completion list with the public shared2 fields and properties from the specified class or module. In this particular case, the XML documentation causes Visual Basic to populate the completion list with the public shared properties of System.Drawing.Color.

Don’t believe me? Just comment out the System.Drawing.Color completionlist tag above, save and restart Visual Studio to see how this influences the statement completion list.

Standard Completion List

Many of you are probably thinking, “so, is this just a nifty implementation detail, or is something I can actually use?” The answer is, yes, this something you can use today to customize Visual Basic’s statement completion. The code below demonstrates how the completionlist tag can be used.

''' <completionlist cref="CommonOperations"/>
Public Class Operation
     Private ReadOnly _execute As Func(Of Integer, Integer, Integer)

     Public Sub New(ByVal execute As Func(Of Integer, Integer, Integer))
         _execute = execute
     End Sub

     Public Function
Execute(ByVal arg1 As Integer, ByVal arg2 As Integer) As Integer
         Return
_execute(arg1, arg2)
     End Function
End Class

Public NotInheritable Class
CommonOperations
     Public Shared ReadOnly Add = New Operation(Function(x, y) x + y)
     Public Shared ReadOnly Subtract = New Operation(Function(x, y) x - y)
     Public Shared ReadOnly Multiply = New Operation(Function(x, y) x * y)
     Public Shared ReadOnly Divide = New Operation(Function(x, y) x / y)
End Class

Visual Basic will automatically pick up the completionlist tag in the code above and use it to populate the completion list like so.

Custom Value Completion List

While a bit limited, it’s pretty easy to customize the statement completion list experience for Visual Basic to make certain types of APIs more discoverable. It’s as simple as a single XML tag.

1Kevin Pilch-Bisson (C# IDE Developer Lead and swell guy) has a clever idea for supporting the completionlist tag in the C# statement completion list while staying true to the C# IntelliSense model.
2The VB "Shared" keyword = static in C#.

posted on Saturday, March 14, 2009 12:23:10 PM (Pacific Standard Time, UTC-08:00)  #    Comments [4]

kick it on DotNetKicks.com
 Monday, December 31, 2007

Mug

Hello again, X-mas celebrants! I have just one last verse in my carol to make all of your Visual Studio 2008 experiences bright. Don't let your hearts be saddened because my song is drawing to a close. After today, a new year filled with its own code blessings will be upon us.

My last offering is a simple one—a stocking stuffer, really. It's one last refactoring targeted at Visual Basic developers.

And so, it is with a heavy heart that I begin the last verse of the "Twelve Days of Refactor! X-mas..."

"On the twelfth day of X-mas my true love (DevExpress) gave to me..."

Extract XML Literal to Resource

In my opinion, the most compelling new feature of Visual Basic 9 is XML Literals. We've already seen how Refactor! Pro can be used to manipulate XML Literals to great effect, saving literally hundreds of keystrokes. However, sometimes we don't want to dynamically build XML. Sometimes we simply want to consume a chunk of raw XML.

Module TwelveDaysOfXmas
  Sub Main()
    Dim lBook = <book isbn="12252007">
                 <title>Refactoring: The True Meaning of X-mas</title>
                 <price>$0.00</price>
                 <author>
                   <first-name>Dustin</first-name>
                   <last-name>Campbell</last-name>
                 </author>
               </book>
  End Sub
End Module

If we're not adding embedded expressions to the above XML literal, it really belongs in a resource file. However, moving that XML to a resource is a terrible inconvenience. Thankfully, Refactor! Pro provides the Extract XML Literal to Resource refactoring. When applied to the code above, Extract XML Literal to Resource produces the following:

Module TwelveDaysOfXmas
  Sub Main()
    Dim lBook = XElement.Parse(My.Resources.XMLFile)
  End Sub
End Module

When compared to the acrobatics we've already seen Refactor! Pro perform on XML Literals, this refactoring might seem like a very small thing. It may be simple, but it's incredibly helpful when you need it. The first time that you attempt to move an XML Literal to a resource for translation purposes or any other reason, you'll be thankful that you have Extract XML Literal to Resource to do the job for you.

Check Out This Screencast to See Everything that Extract XML Literal to Resource Handles for You!

And so ends my song. We've taken a merry sleigh ride through many of the new language features available in Visual Studio 2008, and we've seen how Refactor! Pro can help you leverage those features today. It's been my distinct pleasure to be your guide on this journey.

Before I take my leave, I have one small piece of advice. If you've been waiting impatiently for the other tool to support for Visual Studio 2008, remember that Refactor! Pro has been there since the very first beta. No matter what that tool vendor may try to tell you, Visual Studio 2008 was not a surprise. Everyone had more than a year to prepare. The only ones taken by surprise were those who weren't paying attention.

And with that, I wish you a continued happy holiday season and hope Refactor! Pro can make your new year bright!

Happy New Year!

posted on Monday, December 31, 2007 10:57:09 AM (Pacific Standard Time, UTC-08:00)  #    Comments [5]

kick it on DotNetKicks.com
 Sunday, December 30, 2007

Mug

Greetings friends! I bring tidings of comfort and joy! That is, you can rest comfortably and joyously, knowing that you don't have to wait for refactorings that leverage the new language features of Visual Studio 2008. These refactorings are available today.

I'm very excited about today's verse. As promised yesterday, I'm back to share some more refactoring possibilities for Visual Basic XML Literals. By the end of the verse, you should have a sense of how powerful these refactorings truly are. If you're a Visual Basic developer, you definitely won't want to miss this!

"On the eleventh day of X-mas my true love (DevExpress) gave to me..."

More Refactoring in XML Literals

Yesterday, we saw how our bread-and-butter refactorings can be used on the inner text of XML tags to create new embedded expressions. This is extremely helpful when trying to make the contents of an XML literal more dynamic. Today, we'll take things a step further to see how we can use Refactor! Pro to manipulate the XML tags themselves.

Module TwelveDaysOfXmas
  Sub Main()
    Dim aPrice As Decimal = 0
    Dim lBook = <book isbn="12252007">
                 <title>Refactoring: The True Meaning of X-mas</title>
                 <price><%= aPrice.ToString("C") %></price>
                 <author>
                   <first-name>Dustin</first-name>
                   <last-name>Campbell</last-name>
                 </author>
               </book>
  End Sub
End Module

Consider the code above. Since Refactor! Pro works on XML tags, we can select the entire <price> tag and apply Extract Method to get the following:

Module TwelveDaysOfXmas
  Private Function GetPrice(ByVal aPrice As Decimal) As XElement
    Return <price><%= aPrice.ToString("C") %></price>
  End Function

  Sub Main()
    Dim aPrice As Decimal = 0
    Dim lBook = <book isbn="12252007">
                 <title>Refactoring: The True Meaning of X-mas</title>
                 <%= GetPrice(aPrice) %>
                 <author>
                   <first-name>Dustin</first-name>
                   <last-name>Campbell</last-name>
                 </author>
               </book>
  End Sub
End Module

A potential complication is the use of aPrice in the embedded expression. Fortunately, Extract Method intelligently analyzes this and declares it as a parameter of the new method.

View Screencast to See Extract Method in Action!

Refactor! Pro's ability to manipulate XML tags makes it easy to dynamically build XML. In fact it can save minutes of menial coding labor.

Take another look at the first code example above. Go ahead. I'll wait.

Now, imagine how much effort it would take to transform that code into this:

Module TwelveDaysOfXmas
  Private Function GetTitle(ByVal aTitle As String) As XElement
    Return <title><%= aTitle %></title>
  End Function

  Private Function GetPrice(ByVal aPrice As Decimal) As XElement
    Return <price><%= aPrice.ToString("C") %></price>
  End Function

  Private Function GetAuthor(ByVal aFirstName As String, _
                             ByVal aLastName As String) As XElement
    Return <author>
             <first-name><%= aFirstName %></last-name>
             <last-name><%= aLastName %></last-name>
           </author>
  End Function

  Private Function GetBook(ByVal aPrice As Decimal, _
                           ByVal aIsbn As String, _
                           ByVal aTitle As String, _
                           ByVal aFirstName As String, _
                           ByVal aLastName As String) As XElement
    Return <book isbn=<%= aIsbn %>>
             <%= GetTitle(aTitle) %>
             <%= GetPrice(aPrice) %>
             <%= GetAuthor(aFirstName, aLastName) %>
           </book>
  End Function

  Sub Main()
    Dim lBook = GetBook(0D, _
                  "12252007", _
                  "Refactoring: The True Meaning of X-mas", _
                  "Dustin", _
                  "Campbell")
  End Sub
End Module

That's pretty insane, isn't it? Well, with Refactor! Pro, this is a snap. In fact, most of the effort is spent typing the names of new variables and methods. The refactorings themselves take only seconds to apply.

Don't Believe Me? Check Out This Screencast!

One point I've saved until now is that Refactor! Pro is the very first tool to offer refactorings for Visual Basic XML Literals. That's just one more compelling reason that Refactor! Pro should be a part of your Visual Studio 2008 installation this holiday season.

Happy Holidays!

posted on Sunday, December 30, 2007 3:58:57 PM (Pacific Standard Time, UTC-08:00)  #    Comments [4]

kick it on DotNetKicks.com
 Saturday, December 29, 2007

Mug

I'm afraid that I have an apology to make. I feel that I've given my Visual Basic friends a raw deal because the verses of my carol thus far have been primarily about C#. Oh sure, the verses usually end with a paragraph or two mentioning how a particular refactoring works in VB, but I haven't devoted a whole verse exclusively to a Visual Basic 9 feature. Until now. Today's verse is dedicated specifically to the coolest new feature of Visual Basic 9: XML Literals.

So, sit back and relax. It's time for a little Visual Basic X-mas cheer!

"On the tenth day of X-mas my true love (DevExpress) gave to me..."

Refactoring in XML Literals

A couple of months ago, I wrote about how we were adding first-class refactoring support for Visual Basic XML Literals. If you're unfamiliar with XML Literals, they allow developers to embed XML directly into their code like so:

Module TwelveDaysOfXmas
  Sub Main()
    Dim lBook = <book isbn="12252007">
                 <title>Refactoring: The True Meaning of X-mas</title>
                 <price><%= 0D.ToString("C") %></price>
                 <author>
                   <first-name>Dustin</first-name>
                   <last-name>Campbell</last-name>
                 </author>
               </book>
  End Sub
End Module

It's the VB Compiler's job to transform the above XML Literal into instances of XElements, XAttributes and XNames from the System.Xml.Linq namespace.

Module TwelveDaysOfXmas
  Sub Main()
    Dim lBook = New XElement("book", _
                    New XAttribute("isbn", "12252007"), _
                    New XElement("title", "Refactoring: The True Meaning of X-mas"), _
                    New XElement("price", 0D.ToString("C")), _
                    New XElement("author", _
                        New XElement("first-name", "Dustin"), _
                        New XElement("last-name", "Campbell")))
  End Sub
End Module

The real power of XML Literals is the ability to embed expressions directly into the XML. In the first code example above, the <price> tag contains an embedded expression.

<price><%= 0D.ToString("C") %></price>

Embedded expressions open the door to dynamic XML generation. Very, very cool.

The only real problem that I have with XML Literals is that embedded expressions are such a pain to write. Not only does the expression itself have to be written, but the delimiters contain no less than five symbols. Granted, VB's IntelliSense fills in the last two after I've typed the first three, but that's still three characters to type with the shift key held down. That's pretty painful. It would be great if a refactoring tool existed that handled this work for us. Oh wait. I work on a refactoring tool that does that very thing. That's right, Refactor! Pro works on XML Literals!

Check out the preview hint for Introduce Local when the contents of the <title> tag are selected:

Introduce Local on Xml Literal Preview Hint

And here's the code after Introduce Local is applied:

Introduce Local on Xml Literal

Visual Basic developers everywhere can rejoice. You no longer have to type <%= again because the bread-and-butter refactorings work in XML Literals!

View Screencast of XML Literal Refactoring in Action!

Tomorrow: more refactorings for XML Literals. You won't want to miss it!

posted on Saturday, December 29, 2007 10:40:08 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Friday, December 28, 2007

Cookies

Welcome back for more X-mas refactoring fun! There are just four more verses in my carol, but I'll make them count. Refactor! Pro can bless your Visual Studio 2008 installation in many more ways, so I'll have to pick the very best.

"On the ninth day of X-mas my true love (DevExpress) gave to me..."

Expand Lambda Expression

In my sixth verse, I described a feature of Refactor! Pro that enables developers to leverage the dreaded lambda expressions. That refactoring (Compress to Lambda Expression) provides a way to transform an anonymous method into a lambda expression. Today we're looking at lambda expressions from the opposite perspective—transforming a lambda expression into an anonymous method. Expand Lambda Expression is the refactoring that performs this conversion. Given the lambda expression in the code below...

using System;

namespace TwelveDaysOfXmas
{
  class Program
  {
    static void Main()
    {
      var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

      var numberText = Array.ConvertAll<int, string>(numbers, n => n.ToString("x8"));

      foreach (var text in numberText)
        Console.WriteLine(text);
    }
  }
}

Expand Lambda Expression will produce this:

using System;

namespace TwelveDaysOfXmas
{
  class Program
  {
    static void Main()
    {
      var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

      var numberText = Array.ConvertAll<int, string>(numbers, delegate(int n)
                                                              {
                                                                return n.ToString("x8");
                                                              });

      foreach (var text in numberText)
        Console.WriteLine(text);
    }
  }
}

I'm sure that some of you are scratching your heads. "Why in the world would I want to do that? Aren't lambda expressions better?" Well, yes. However, transforming a lambda expression into an anonymous method makes other refactorings available. For example, after expanding our lambda expression, we might want to use Name Anonymous Method to make the anonymous method a member of the current type. That way, we're promoting code reuse. Check out the preview hint for Name Anonymous Method below.

Name Anonymous Method Preview Hint

Once Name Anonymous Method is applied, we can give the new method a good name and we're done!

using System;

namespace TwelveDaysOfXmas
{
  class Program
  {
    private static string GetHexText(int n)
    {
      return n.ToString("x8");
    }
    static void Main()
    {
      var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

      var numberText = Array.ConvertAll<int, string>(numbers, GetHexText);

      foreach (var text in numberText)
        Console.WriteLine(text);
    }
  }
}

View Screencast of Expand Lambda Expression and Name Anonymous Method in Action!

I must say, it gladdens my heart to know that there is a tool available right now that allows me to refactor the latest and greatest language features of Visual Studio 2008. In fact, we've raised the bar by releasing a major update to Refactor! Pro. That's right, Refactor! Pro 3.0 is now available and ships with 150 refactorings for C#, Visual Basic, C++, ASP .NET, XAML, and even JavaScript. The future is looking very bright indeed!

posted on Friday, December 28, 2007 12:53:10 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Thursday, December 27, 2007

Bells

JustinKohnen: @dcampbell: um... Christmas is over dude ;)

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.

Introduce Local Preview Hint

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.

posted on Thursday, December 27, 2007 3:38:20 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com
 Wednesday, December 26, 2007

Presents

Season's greetings! We're halfway through my X-mas carol describing how Refactor! Pro can be used to leverage the new features of Visual Studio 2008. Today, I'm sharing a little more Refactor! Pro love by demonstrating a refactoring that literally can save minutes of menial coding. That's right, minutes. Interested? OK, just let me clear my voice...

"On the seventh day of X-mas my true love (DevExpress) gave to me..."

Create Backing Store

A couple of days ago, I showed how Refactor! Pro can transform properties into C# 3.0 Auto-Implemented Properties. However, sometimes the opposite is needed. We need a way to convert from an auto-implemented property to a standard property and field. Consider the following code:

using System;
using System.Drawing;

namespace TwelveDaysOfXmas
{
  class Present
  {
    public Color Color1 { get; set; }
    public Color Color2 { get; set; }
  }
}

Suppose that we want to add logic to both the Color1 and Color2 properties to ensure that they can't be set to the same value. Now, imagine how much effort that would take. An awful lot of keystrokes are needed to get to the code below.

using System;
using System.Drawing;

namespace TwelveDaysOfXmas
{
  class Present
  {
    private Color m_Color1;
    public Color Color1
    {
      get { return m_Color1; }
      set
      {
        if (m_Color2 == value)
          return;
        m_Color1 = value;
      }
    }
    private Color m_Color2;
    public Color Color2
    {
      get { return m_Color2; }
      set
      {
        if (m_Color1 == value)
          return;
        m_Color2 = value;
      }
    }
  }
}

Fortunately, Refactor! Pro provides a refactoring, called Create Backing Store, which converts an auto-implemented property into a standard property with a field backing store. In other words, it transforms this...

public Color Color1 { get; set; }

...into this.

private Color m_Color1;
public Color Color1
{
  get
  {
    return m_Color1;
  }
  set
  {
    m_Color1 = value;
  }
}

That's pretty close to what we want. With the help of two other refactorings, Introduce Setter Guard Clause and Collapse Accessor, we can continue to manipulate the property to get the code below.

private Color m_Color1;
public Color Color1
{
  get { return m_Color1; }
  set
  {
    if (m_Color1 == value)
      return;
    m_Color1 = value;
  }
}

Now we just have to make a minor edit to the guard clause and we're done.

View Screencast of These Refactorings in Action!

And that concludes my verse for today. Remember that the features I'm showing you are available for download this very second. So, if you're tired of waiting for <whisper>the other tool</whisper> to get its act together, Refactor! Pro can have you running laps through Visual Studio 2008 in no time.

posted on Wednesday, December 26, 2007 12:52:42 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Tuesday, December 25, 2007

Presents

Merry X-mas friends! It is indeed X-mas day, and I have returned with a special gift for you. Today, I'm doing my part to bring peace on earth and goodwill toward developers by showing one way that Refactor! Pro can simplify the dreaded lambda expressions. I'll achieve this by showing three refactorings which can be used together to transform some very C-ish code into modern C# 3.0 code.

And now, it's time to continue my anthem.

There's a hush. All is quiet. Then, in the silence, a still, small voice is heard. It grows louder and louder until...

"On the sixth day of X-mas my true love (DevExpress) gave to me..."

Compress to Lambda Expression

I'm not exactly sure why, but every time that I mention "lambda expressions" to developers, their faces show confusion and terror. My guess is that this reaction is caused by one of three things:

  1. A fear of Greek letters (i.e. "lambda")
  2. A fear of all things pointy (i.e. the => operator that lambda expressions bristle with.)
  3. A fear of all things functional (i.e. passing functions around like candy.)

It's for these reasons that I'll demonstrate a couple of other refactorings first. We'll work our way up to lambda expressions. Let's start with something more familiar.

using System;
using System.Collections.Generic;

namespace TwelveDaysOfXmas
{
  class CompressToLambdaExpression
  {
    public static int SumList(List<int> list)
    {
      int sum = 0;
      for(int i = 0; i < list.Count; i++)
        sum += list[i];
      return sum;
    }
  }
}

The code above is an example of the sort of imperative code that we write all of the time. What do I mean by "imperative?" Well, it's like writing a recipe for the computer—describing, in excruciating detail, the steps to solve a problem. There's nothing terribly wrong with that. After all, it's how our computer processors work. They execute a list of instructions—one at a time. However, there is another way that this code can be written.

On the other side of the coin from imperative code is declarative code. Declarative code describes what should be done instead of specifically how it should be done. Writing code declaratively has many potential benefits over the imperative style.

  1. It can be easier to read.
  2. It can be easier for the compiler/runtime to optimize.
  3. It can promote code reuse.

We can write the above code a bit more declaratively by using a foreach loop.

using System;
using System.Collections.Generic;

namespace TwelveDaysOfXmas
{
  class CompressToLambdaExpression
  {
    public static int SumList(List<int> list)
    {
      int sum = 0;
      foreach (int number in list)
        sum += number;
      return sum;
    }
  }
}

That's better! To save keystrokes, Refactor! Pro provides a For to ForEach refactoring that easily performs this conversion. Here's how the preview hint for this refactoring looks:

For to ForEach Preview Hint

Another declarative possibility is to call the List<T>.ForEach method instead using of a foreach loop. In that case, we would pass an anonymous delegate to the method as the body of the loop like so:

using System;
using System.Collections.Generic;

namespace TwelveDaysOfXmas
{
  class CompressToLambdaExpression
  {
    public static int SumList(List<int> list)
    {
      int sum = 0;
      list.ForEach(delegate(int number)
      {
        sum += number;
      });
      return sum;
    }
  }
}}

In a declarative fashion, the above code states, "loop through the entire list, and execute this function (delegate) for each item in the list." A powerful feature of the anonymous delegate is that it references a variable (sum) outside of the delegate body, producing a closure. (For more information on closures, check out this article.)

Of course, Refactor! Pro provides a refactoring that renders this transformation trivial: Introduce ForEach Action. The screenshot below shows the preview hint for this refactoring.

Introduce ForEach Action Preview Hint

Now, some of you might be saying, "Whoa! That anonymous delegate sure is an ugly little spud1." You're right, it is. Enter the lambda expression.

I don't want to present an entire history of lambda expressions here, but you should understand that they pre-date computers entirely. So, if you've been wondering where these crazy new things came from, know that they really aren't crazy "new" things. Lambda expressions have been around since the 1930s.

A C# lambda expression is really just an anonymous delegate on steroids. It retains all of the functionality of an anonymous delegate but adds conciseness, better type inference and even pseudo-meta-programming via expression trees.

Using a lambda expression is straight-forward, if a little funky:

using System;
using System.Collections.Generic;

namespace TwelveDaysOfXmas
{
  class CompressToLambdaExpression
  {
    public static int SumList(List<int> list)
    {
      int sum = 0;
      list.ForEach(number => sum += number);
      return sum;
    }
  }
}

If this is the first time that you've seen a lambda expression in the wild, compare it with the anonymous delegate that we used before. The parameters are declared to the left of the => operator, and the body is declared to the right. The compiler works out the types of the parameters so there's no need to specify them.

Of course, my X-mas present for you today is another refactoring: Compress to Lambda Expression. This refactoring (available now) converts anonymous delegates into lambda expressions, saving dozens of keystrokes and head scratches. Again, here is the preview hint to show what this refactoring does:

Compress to Lambda Expression Preview Hint

View Screencast of These Refactorings in Action!

As always, I'm demonstrating features of Refactor! Pro that can be used to leverage the new features in Visual Studio 2008 right now. In fact, all of the refactorings above have been shipping for several months. In other words, these aren't in some super-secret beta. They have been released.

As another refactoring goodie has been successfully unwrapped, it's time to take my leave of you. Until tomorrow, have a warm and happy X-mas!

1Ray Stanz, Ghostbusters.

posted on Tuesday, December 25, 2007 9:31:26 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]

kick it on DotNetKicks.com
 Monday, December 24, 2007

Nutcracker

'Twas the night before X-mas, when all through the house,
Not a creature was stirring, not even a mouse;
The stockings were hung by the chimney with care,
In hopes that DevExpress soon would be there;
The children were nestled all snug in their beds,
While visions of
Refactor! Pro danced in their heads.

Ho, ho, ho! I'm back to stuff your stockings with another feature of Refactor! Pro that lets you leverage Visual Studio 2008 on this fine X-mas Eve.

But wait! Who's that knocking at your front door? Why it's a group of carolers, here to sing a noël for us. Shhh! They're about to begin.

"On the fifth day of X-mas my true love (DevExpress) gave to me..."

Convert to Auto-Implemented Property

One of the tastiest syntactic sugar cookies that has been added to C# 3.0 is Auto-Implemented Properties. This feature allows C# developers to define properties far more concisely than before. Here's how we used to define properties in C# 2.0:

using System;
using System.Drawing;

namespace TwelveDaysOfXmas
{
  class Present
  {
    private Color m_Color;
    private bool m_HasBow;

    public Present(Color color, bool hasBow)
    {
      m_Color = color;
      m_HasBow = hasBow;
    }

    public Color Color
    {
      get { return m_Color; }
    }
    public bool HasBow
    {
      get { return m_HasBow; }
      set { m_HasBow = value; }
    }
  }
}

Whew! That's a lot of effort! Thanks to auto-implemented properties, we can now define our properties like so:

using System;
using System.Drawing;

namespace TwelveDaysOfXmas
{
  class Present
  {
    public Present(Color color, bool hasBow)
    {
      Color = color;
      HasBow = hasBow;
    }

    public Color Color { get; private set; }
    public bool HasBow { get; set; }
  }
}

Convert to Auto-Implemented Property is a refactoring that can be used to change the first example into the second example. Check out the preview hint below to see everything that this refactoring will do for you.

Convert to Auto-Implemented Property Preview Hint

  1. It removes the field that serves as the backing store for the property.
  2. It converts all field references into references to the property.
  3. It replaces the property with an auto-implemented version. I should point out that the refactoring intelligently generates an auto-implemented property with a private setter because the property is read-only (write-only properties are handled similarly).
  4. There is also a Convert to Auto-Implemented Property (convert all) refactoring which will transform all of the properties in the current type.

That's all there is to it! This refactoring does exactly what you expect it to do, and using it will save you dozens of keystrokes.

Unfortunately, our Visual Basic friends aren't feeling the love. You see, auto-implemented properties is a C# 3.0-only feature that did not make it into Visual Basic 9. However, it would be shameful to leave any developer out in the cold. At the request of the Visual Basic team, we've added a new feature that provides the illusion of auto-implemented properties in Visual Basic.

VB Property Collapse 1

The above screenshot shows what the code looks like as it is being edited. As you can see, no changes have been made yet. However, once the editor caret leaves the property, the field and property automatically collapse onto one line:

VB Property Collapse 2

View Screencast of VB Property Collapse in Action!

That sleight-of-hand helps VB code appear more concise. I hope this will help our Visual Basic friends feel a warm glow this holiday season.

And with that, I must bid you farewell. Until next time...

He spoke not a word, but went straight to his work,
And filled all the stockings; then turned with a jerk,
And laying his finger aside of his nose,
And giving a nod, up the chimney he rose.
He sprang to his sleigh, to his team gave a whistle,
And away they all flew, like the down of a thistle:
But I heard him exclaim, as he drove out of sight—
Merry X-mas to all, and to all a good night.

posted on Monday, December 24, 2007 7:39:36 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Sunday, December 23, 2007

Santa Cat

Feliz Navidad my mistletoe aficionados! I've just finished warming up my voice and am ready to continue my aria of Refactor! Pro support for Visual Studio 2008. Ready or not, here we go!

And a one, and a two, and a one, two, three, four!

"On the fourth day of X-mas my true love (DevExpress) gave to me..."

Rename Works In Query Expressions

Today, instead of examining a brand new feature, we'll see how a pre-existing refactoring handles the new features of C# 3.0 and Visual Basic 9. Adding support for new language features involves much more than simply creating a handful of new refactorings—all existing refactorings must be updated as well. With Refactor! Pro, you can be confident that we've done our homework and provided support for Visual Studio 2008 across the entire product.

Of all the refactorings available to me, I use Rename the most frequently. This is due to the fact that I use Refactor! Pro to shape my code while I write it. Often, while coding a solution, I find that a variable's meaning is no longer consistent with its name. When this happens, Rename allows me to change the variable's name efficiently and accurately. In fact, I've used Rename so often that I've grown to trust it implicitly.

Rename doesn't let me down when I'm working with a C# 3.0 query expression. With the editor caret positioned on the identifier of the from clause, I can press the Refactor key (CTRL+` on my machine), and Rename kicks in, highlighting the active identifier and all its references.

Rename in C# Query Expression (start)

At this point, I can just type the new variable name. All references are updated in real time.

Rename in C# Query Expression (end)

View Screencast of Rename in Action!

Rename also works perfectly in an equivalent Visual Basic query expression (using fancy Aggregate syntax). Again, it's as easy as pressing the Refactor Key...

Rename in VB Query Expression (start)

...and typing the new variable name.

Rename in VB Query Expression (end)

Neat!

The moral of today's verse is that Refactor! Pro offers deep support for Visual Studio 2008 in every refactoring. You can rest assured that all refactorings just work as expected. And most importantly, they are working this very minute. Not tomorrow. Not sometime in January. Now.

Have a Merry X-mas!

posted on Sunday, December 23, 2007 12:22:04 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Saturday, December 22, 2007

Nutcracker

Welcome back my 'nog-froth mustachioed friends! I've returned with another helping of Refactor! Pro goodness for Visual Studio 2008. One scrooge commented that the last present was a little weak, so I've decided to give a bigger gift this time. However, I will be saving some of my bestest presents for the very end.

So, sit back, relax and take out your ear plugs as I serenade you with my third verse.

"On the third day of X-mas my true love (DevExpress) gave to me..."

Name Anonymous Type

Of all the new features in C# 3.0 and Visual Basic 9, Anonymous Types is one of the most convenient. This feature allows the user to create new objects "on the fly," without providing type definitions for them. For example:

var person = new { Name = "St. Nick", Age = "Really Old" };
Console.WriteLine(person.Name);

When the C# compiler encounters the code above, it generates a new type with two string properties: Name and Age.

This powerful new feature is not without limitations. Because anonymous types have no accessible type name (they're anonymous - duh!), they can only be referenced by variables that are implicitly-typed. This becomes very frustrating when using anonymous types in other natural ways.

public static ??? CreatePerson()
{
  return new { Name = "St. Nick", Age = "Really Old" };
}

What should I fill in for ??? in the code above? One possibility is to use object. However, if I do that, how do I access the properties from client code? Reflection? An awkward casting helper?

Recently, this very problem was hashed out on the MSDN forums. The general consensus was, when you want to expose an anonymous type in an API (e.g. return an anonymous type from a method), swap it out for a defined type. However, defining a new type that matches an anonymous type is cumbersome. Thankfully, Refactor! Pro can step in and do this work for you. When the Name Anonymous Type refactoring is applied to the anonymous type above, the following class is generated:

[DebuggerDisplay("\\{ Name = {Name}, Age = {Age} \\}")]
public sealed class Person: IEquatable<Person>
{
  private readonly string m_Name;
  private readonly string m_Age;

  public Person(string name, string age)
  {
    m_Name = name;
    m_Age = age;
  }

  public override bool Equals(object obj)
  {
    if (obj is Person)
      return Equals((Person)obj);
    return false;
  }
  public bool Equals(Person obj)
  {
    if (!EqualityComparer<string>.Default.Equals(m_Name, obj.m_Name))
      return false;
    if (!EqualityComparer<string>.Default.Equals(m_Age, obj.m_Age))
      return false;
    return true;
  }
  public override int GetHashCode()
  {
    int hash = 0;
    hash ^= EqualityComparer<string>.Default.GetHashCode(m_Name);
    hash ^= EqualityComparer<string>.Default.GetHashCode(m_Age);
    return hash;
  }
  public override string ToString()
  {
    return String.Format("{{ Name = {0}, Age = {1} }}", m_Name, m_Age);
  }

  public string Name
  {
    get
    {
      return m_Name;
    }
  }
  public string Age
  {
    get
    {
      return m_Age;
    }
  }
}

View Screencast of Name Anonymous Type in Action!

You might be thinking, "Wow! That's a lot of code! Is all of that really necessary?" The answer is, yes, all of that code is necessary to produce a type definition that is equivalent to the subtle features of an anonymous type. In C#, anonymous types are immutable so we must generate read-only fields and properties. In addition, the equality and identity of anonymous types are explicitly defined so they can be compared with one another. In other words, C# anonymous types have value-type semantics. The following code sample might clarify this:

var person1 = new
{
  Name = "Dustin Campbell",
  Age = "32"
};

var person2 = new
{
  Name = "Dustin Campbell",
  Age = "32"
};

var person3 = new
{
  Name = "Dustin's Trophy Wife",
  Age = "Undisclosed (but probably really, really young)"
};

Console.WriteLine(person1.Equals(person2));
Console.WriteLine(person2.Equals(person3));

Because of the value-type characteristics of anonymous types, the above code outputs the following to the console.

True
False

Of course, if Name Anonymous Type is applied, the same output is produced.

Traditionally, the Visual Basic team likes to make life hard for us, and anonymous types are no exception. Contrary to C#, the Visual Basic compiler generates mutable anonymous types. In addition, Visual Basic allows for partially-mutable anonymous types when the Key keyword is applied. (This is further proof that C# and Visual Basic have very different agendas and destinies.) Fortunately, Name Anonymous Type is intelligent enough to handle these differences.

Dim person = New With {.Name = "St. Nick", .Age = "Really Old"}

When applied to the above code, Name Anonymous Type generates a new Person class like so:

<DebuggerDisplay("\{ Name = {Name}, Age = {Age} \}")> _
Public NotInheritable Class Person
  Private m_Name As String
  Private m_Age As String

  Public Sub New(ByVal name As String, ByVal age As String)
    m_Name = name
    m_Age = age
  End Sub

  Public Overrides Function ToString() As String
    Return String.Format("{{ Name = {0}, Age = {1} }}", m_Name, m_Age)
  End Function

  Public Property Name() As String
    Get
      Return m_Name
    End Get
    Set(ByVal value As String)
      m_Name = value
    End Set
  End Property
  Public Property Age() As String
    Get
      Return m_Age
    End Get
    Set(ByVal value As String)
      m_Age = value
    End Set
  End Property
End Class

To be consistent with the reference-type semantics of Visual Basic anonymous types, Name Anonymous Type produces a mutable class. Gone are the overrides to Equals() and GetHashCode(). In addition, the properties are read-write. It's this sort of language independence that makes Refactor! Pro a choice tool for Visual Studio 2008 development.

And that wraps up another verse in my holiday sing-a-long! Remember that the features I am showing can be used right now. There's no need to wait for some forthcoming beta. You can use them today. Until next time...

posted on Saturday, December 22, 2007 8:35:00 AM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com
 Friday, December 21, 2007

Fireplace

Season's greetings! Welcome back for another dose of Yuletide cheer! Yesterday, I sang to you about one way in which Refactor! Pro can be used to leverage the new features of C# 3.0 and Visual Basic 9 right now. Today, I'm back with another verse to warm your hearts this holiday season.

So, strike up the band! Rouse the drunken carolers! It's time to go a wassailing once more.

"On the second day of X-mas my true love (DevExpress) gave to me..."

Make Explicit

Like its sister refactoring, Make Explicit enables developers to manipulate implicitly-typed local variables. However, it performs the opposite operation as Make Implicit. It converts implicitly-typed local variables to explicit ones. In other words, Make Explicit will transform the following code:

var number = 42ul;

Like so:

ulong number = 42ul;

Make Explicit must do a great deal of work to determine the type of the expression that an implicitly-typed local variable is assigned to. Consider the following code (which I found lurking in some corner of the 'net):

using System;
using System.Linq;
using System.ServiceProcess;

namespace TwelveDaysOfXmas
{
  class MakeExplicit
  {
    static void DisplayServices()
    {
      var services = from service in ServiceController.GetServices()
                     where service.Status == ServiceControllerStatus.Running
                     orderby service.ServiceName ascending
                     select service;

      foreach (ServiceController aService in services)
      {
        Console.WriteLine(aService.ServiceName);
      }

      Console.ReadLine();
    }
  }
}

In order to determine the type of services, Make Explicit must have a full understanding of LINQ. First, it must transform the query expression into the appropriate extension methods and lambda expressions like so:

var services = ServiceController.GetServices()
                 .Where(service => service.Status == ServiceControllerStatus.Running)
                 .OrderBy(service => service.ServiceName)

Next, Make Explicit must be able to resolve the extension methods and infer the types of the lambda expressions. Once this is done, the type of the expression can finally be determined. That's an awful lot of work, but it's required to ensure that the type is inferred accurately. Fortunately, Make Explicit executes all of this with blazing speed and infers the correct type:

IOrderedEnumerable<ServiceController> services = from service in ServiceController.GetServices()
                                                 where service.Status == ServiceControllerStatus.Running
                                                 orderby service.ServiceName ascending
                                                 select service;

View Screencast of Make Explicit in Action! (#1)

If you have any doubt that Make Explicit is really doing this much work behind the scenes, try commenting out the orderby clause. Make Explicit will infer the correct type even after the query expression has changed:

IEnumerable<ServiceController> services = from service in ServiceController.GetServices()
                                          where service.Status == ServiceControllerStatus.Running
                                          //orderby service.ServiceName ascending
                                          select service;

View Screencast of Make Explicit in Action! (#2)

Finally, I should mention that Make Explicit works just as handily with Visual Basic.

Dim services = From service In ServiceController.GetServices() _
               Where service.Status = ServiceControllerStatus.Running _
               Order By service.ServiceName Ascending

In the above code, Make Explicit properly infers the type of services as IOrderedEnumerable<ServiceController>. Awesome.

One last closing thought: some of you might be thinking right now, "Why would I want to do this? Aren't implicitly-typed local variables better?" There are a few scenarios in which Make Explicit is useful:

  1. Specifying the type name sometimes makes code easier to read.
  2. It simplifies porting code backwards (e.g. to compile in an earlier version of Visual Studio).
  3. It can be helpful for learning and understanding code.

For these reasons, Make Explicit takes its rightful place among the refactorings that support Visual Studio 2008.

"And a partridge in a pear tree..."

And so concludes today's verse. It's time to settle back with a warm mug of spiked eggnog and kick up your feet. Join me tomorrow as we take a peek at another way in which Refactor! Pro brings the X-mas love.

posted on Friday, December 21, 2007 10:44:12 AM (Pacific Standard Time, UTC-08:00)  #    Comments [3]

kick it on DotNetKicks.com
 Thursday, December 20, 2007

Fireplace

Gentle readers, in the spirit of X-mas, I'd like to sing you a carol. This jolly tune (based on a popular old English carol) enumerates ways that Refactor! Pro can warm your installation of Visual Studio 2008 this holiday season. In contrast to some of our... ahem... <whisper>competition</whisper>, the features I'll be showing can be used today. In fact, most of these features have been shipping since Visual Studio 2008 was still a wee child known by its code name, Orcas.

But, hey, enough of my yammering! Stoke the fire and put on a kettle! Let the merry-making begin!

"On the first day of X-mas my true love (DevExpress) gave to me..."

Make Implicit

Visual Studio 2008 introduced a welcome addition to both the C# and Visual Basic languages: implicitly-typed local variables. While this feature is necessary to properly support another feature, anonymous types, it can also be used to enhance the readability of client code—especially when generic types are being used. Consider the following code:

private static Dictionary<string, Guid> BuildIdTable()
{
  Dictionary<string, Guid> map = new Dictionary<string, Guid>();

  // Fill map with entries...

  return map;
}

That sort of code can be a bit frustrating. Dictionary<TKey, TValue> is extremely powerful, but can be awkward to use. The developer is forced to fully declare the type name (which is often quite long) on both the left and right sides of the local variable declaration. Thankfully, an implicitly-typed local variable can alleviate this problem:

private static Dictionary<string, Guid> BuildIdTable()
{
  var map = new Dictionary<string, Guid>();

  // Fill map with entries...

  return map;
}

Now for the really good news: Refactor! Pro provides Make Implicit, a refactoring which easily converts explicitly-declared local variables to implicit ones. Check out the preview hint for Make Implicit:

View Screencast of Make Implicit in Action!

Of course, like most of our refactorings, Make Implicit works in Visual Basic as well.

Some critics might be thinking, "What's the point? It just deletes text and inserts a keyword! I could write a macro to do that!" Well, before those skeptics get too comfortable with their new macro, consider what Make Implicit must do with code like the following:

ulong number = 42;

If Make Implicit were simply to swap ulong for var, there would be a serious problem. Instead of ulong, the type of number would be inferred as int, changing the meaning of the code. To fix this problem, a minor adjustment is made to prevent shooting the code in its proverbial foot.

var number = 42ul;

So, throw your macro away! Let Make Implicit handle the edge cases intelligently.

Ho, ho, ho! That's quite a gift under the tree! Come back tomorrow when I continue my jaunty tune and look at another Visual Studio 2008-specific refactoring that is available to you today: Make Explicit.

posted on Thursday, December 20, 2007 10:31:39 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Friday, November 23, 2007
Visual Studio 2008's multi-targeting support for compiling projects to different versions of the .NET Framework is very powerful. Multi-targeting is a compelling feature because it enables users to continue working on solutions that target .NET Framework 2.0 and 3.0 while upgrading to the latest and greatest IDE. What isn't obvious is that all projects, regardless of target, are compiled with the C# 3.0 compiler. That means users can employ many of the new C# 3.0 language features in legacy projects. The only language features that can't be used are those that require library support from .NET Framework 3.5, in essence, LINQ, Expression Trees and Extension Methods. Implicitly-typed local variables, lambda expressions, auto-implemented properties, object and collection initializers, and anonymous types are all fair game. It's sort of like having C# 3.0-lite or C# 2.5.

Interestingly, it has recently been discovered that even Extension Methods can be used in projects targeting .NET Framework 2.0 and 3.0. All that must be done to enable this support is to create a new System.Runtime.CompilerServices.ExtensionAttribute.

using System;

namespace System.Runtime.CompilerServices
{
  public class ExtensionAttribute: Attribute
  {
  }
}

This trick does have flaws. There are potential scoping issues that occur when an assembly containing a custom System.Runtime.CompilerServices.ExtensionAttribute is referenced by a project that targets .NET Framework 3.5. A compiler warning is generated stating that "the predefined type 'System.Runtime.CompilerServices.ExtensionAttribute' is defined in multiple assemblies in the global alias." However, this is only a minor irritation. In my tests, Extension Methods still worked properly despite the warning.

The ability to use C# 3.0 features in .NET Framework 2.0 or 3.0 projects is very powerful. It helps users get comfortable with the new syntax without having to upgrade projects to .NET Framework 3.5. Viva la C# 2.5!

posted on Friday, November 23, 2007 7:29:08 AM (Pacific Standard Time, UTC-08:00)  #    Comments [5]

kick it on DotNetKicks.com
 Thursday, August 30, 2007
Debates about the fonts and colors that programmers use tend to get out of control very quickly. While studies on the readability and eye fatigue of various font and color schemes exist, it very much remains a matter of personal preference. However, one detail that many programmers seem to agree on is that the default scheme presented by Visual Studio is less than ideal. Standard 10 point Courier New is simply difficult for most people (at least most people that care about this sort of thing—except Rick Strahl) to look at all day.

VS 2005 Default with ClearType

A common solution—especially for high-resolution displays—is to increase the font size in the editor. Personally, I'm a big fan Microsoft's Consolas font, and as Scott Hanselman points out, I really feel that it looks best at 15 point.

VS 2005 with Consolas and ClearType

This is well-covered territory in the blogosphere, but I want to discuss a point that frequently is overlooked. While many of us strive for the perfect font and color scheme in the text editor, we neglect the opportunities for improvement in other windows. For example, I may feel good about using 15-point Consolas to decrease my eye strain, but I haven't done anything to improve my experience with IntelliSense.

VS 2005 Intellisense

(Public speakers are often the biggest culprits of this. Helpful presenters will increase the size of their editor font, but few will adjust other areas such as IntelliSense, debugging windows, etc.)

Fortunately, Visual Studio 2005 makes changing the fonts and colors of much of the IDE easy. The "Show settings for" combo box on the Fonts and Colors page of Visual Studio's Options dialog provides the ability to customize many areas of the IDE, in addition to the text editor. For example, the default font setting for the statement completion window is definitely too small when compared to the 15-point font size that I use in the text editor.

Statement Completion options

One simple trick to improve the readability of the statement completion window is to use exactly the same font and point size as the text editor. Logically, if I'm searching for a class or method name in IntelliSense, it might be easier to find if it looks exactly like it will when inserted into the text editor.

IntelliSense with Consolas

A similar effect can be achieved by adjusting the font of the editor tooltips. Compare the default setting...

Editor Tooltips

...to the adjusted one.

Editor Tooltips with Consolas

Other good candidates for similar adjustment are:

  • DataTips – These are the cool expandable tooltips that appear when identifiers are moused-over in debug mode. Making these easier to read is a must.
  • [All Text Tool Windows] – This is actually a font and color group that controls several settings. When selected, any adjustment made affects the Command, Disassembly, Find Results, Immediate, Memory, Output and Registers windows.
  • [Watch, Locals, and Autos Tool Windows] – As the name suggests, this group handles adjustments for the Watch, Locals and Autos windows.

Remember: when your goal is to improve readability and reduce eye fatigue, adjusting the font in the text editor isn't enough. Pay attention to the font in all areas of Visual Studio.

posted on Thursday, August 30, 2007 10:15:54 AM (Pacific Standard Time, UTC-08:00)  #    Comments [6]

kick it on DotNetKicks.com
 Thursday, August 16, 2007
After writing up this post, I found similar instructions elsewhere. Oh well... you can't always be first.

CopySourceAsHtml on the context menu of Visual Studio's editorCopySourceAsHtml is an extremely useful Visual Studio add-in that places a new menu item on the context menu of the editor. This is especially helpful for bloggers looking for an easy way to get rich source code highlighting into their blogs.

In general, I usually find it necessary to massage the HTML results a bit to get code to look good in RSS feeds, but it is far easier than, say, manual highlighting.

Yesterday, while working on my Art of Currying article, I found it necessary to highlight some C# 3.0 code and was disappointed to find that the trusty "Copy As HTML..." menu item wasn't available. Fortunately, it's very easy to install the add-in into Visual Studio 2008 beta 2.

The CopySourceAsHtml installer drops four files in the "My Documents\Visual Studio 2005\Addins" directory:

  • CopySourceAsHtml.AddIn -- an XML file that describes the add-in and is used for registration with Visual Studio.
  • CopySourceAsHtml.dll -- the add-in itself.
  • CopySourceAsHtml.dll.config -- a configuration file that contains various user settings.
  • CopySourceAsHtml.pdb -- debugging symbols for the add-in. This really isn't needed but it doesn't hurt anything either.

Simply copy these files to the "My Documents\Visual Studio 2008\Addins" directory. If the "Addins" subdirectory doesn't exist, just create it. If you are using Windows Vista, substitute "Users\CURRENTUSER\Documents" for "My Documents".

Next, in a text editor, open the CopySourceAsHtml.AddIn file that you just copied and change the two <Version> tags from 8.0 to 9.0. When you're finished, it should look like this:

<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<
Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">
  <
HostApplication>
    <
Name>Microsoft Visual Studio Macros</Name>
    <Version>9.0</Version>
  </
HostApplication>
  <
HostApplication>
    <
Name>Microsoft Visual Studio</Name>
    <
Version>9.0</Version>
  </
HostApplication>
  <
Addin>
    <
FriendlyName>CopySourceAsHtml</FriendlyName>
    <
Description>Adds support to Microsoft Visual Studio 2005 for copying source code, syntax highlighting, and line numbers as HTML.</Description>
    <
Assembly>CopySourceAsHtml.dll</Assembly>
    <
FullClassName>JTLeigh.Tools.CopySourceAsHtml.Connect</FullClassName>
    <
LoadBehavior>1</LoadBehavior>
    <
CommandPreload>0</CommandPreload>
    <
CommandLineSafe>0</CommandLineSafe>
  </
Addin>
</
Extensibility>

Save the file and... your're done! Start up Visual Studio 2008 beta 2, and that handy context menu item is now available and works great.

posted on Thursday, August 16, 2007 8:03:44 AM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com
 Saturday, June 09, 2007
This week at Tech Ed, Microsoft announced that the official name of Visual Studio Code Name "Orcas" would be Visual Studio 2008. It seems clear to me from the current beta release that a 2007 ship date is probably within reach. Is the 2008 moniker simply for insurance?

posted on Saturday, June 09, 2007 4:27:03 AM (Pacific Standard Time, UTC-08:00)  #    Comments [4]

kick it on DotNetKicks.com
 Friday, April 27, 2007
I've decided to take the plunge and install Visual Studio Code Name "Orcas" Beta 1 on my development machine. For several months, I have been dutifully installing the latest CTPs into virtual machines to toy with and test CodeRush and Refactor! on. However, with the beta release, I'm living a bit closer to the edge. I have spotted and reported a couple of very minor bugs, but hey, this is beta software, right? Regardless of these minor blips, my experience has been nothing short of pure enjoyment. I'm not saying that everyone should install it right now, but for me, it's been fantastic.

posted on Friday, April 27, 2007 3:06:47 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Wednesday, April 18, 2007
This article delves into a certain peculiarity of the .NET garbage collector. Along the way, it explores IL, optimized JIT-compiled code and even the underlying CLR structures.
posted on Wednesday, April 18, 2007 7:08:50 AM (Pacific Standard Time, UTC-08:00)  #    Comments [6]

kick it on DotNetKicks.com
 Wednesday, February 28, 2007
OK, I'm done downloading the March CTP of Orcas. Everyone else can go ahead. Thanks for your patience. :-)


posted on Wednesday, February 28, 2007 4:50:29 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com
The Orcas March CTP is out! You can get the installer version here and the VPC image here. This is first CTP that has all of the features from last May's LINQ Preview. IOW, this is a big one!

On a side note, I would appreciate everyone waiting to download until I'm finished so that I can maximize my bandwidth. TIA! ;-)

posted on Wednesday, February 28, 2007 9:18:15 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]

kick it on DotNetKicks.com
 Friday, January 12, 2007
If you were wondering why the posts have slowed to a trickle here, it's because we were gearing for this grand new release.
posted on Friday, January 12, 2007 6:08:36 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]

kick it on DotNetKicks.com
 Tuesday, November 07, 2006
Get the details here.

posted on Tuesday, November 07, 2006 8:14:43 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Wednesday, November 01, 2006
For those of you who like to live on the edge (are you hearing me Sam?), Microsoft has released an October CTP for Orcas -- the next version of Visual Studio. You can get it here.

Once again, it is in the form of a Virtual PC image but the 4GB download has been separated into chunks of 700MB. Also, don't forget to download the base image if you haven't already. Happy downloading!

posted on Wednesday, November 01, 2006 6:41:55 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Wednesday, August 30, 2006
Responding to a user's comments about a warning raised by Microsoft's Code Analysis tool in Visual Studio Team System.
posted on Wednesday, August 30, 2006 4:17:27 AM (Pacific Standard Time, UTC-08:00)  #    Comments [5]

kick it on DotNetKicks.com