January 2007 - Posts

DevTeach 2007

Ahhh, May in Montreal - what could be better? Well, geek talk in May in Montreal - that's what.

Yes my friends it's time again for my favorite conference of the year, DevTeach. It is a community oriented conference with a very friendly atmosphere and it features top quality speakers from Canada and across the globe. It's also very affordable, if you register before the end of January it will cost you $899. If you miss that deadline it's still less than $1,000 as long as you register before the end of February. User group members can get an additional $50 off with a discount code available through their group.

I'll be doing three talks this year:

  • Discoverability and the .NET Framework
  • Some Specifics on Generics
  • Multi-Threading in Windows Forms Applications

For full details and to register, check out the conference web site at http://www.devteach.com.

See you there.

Posted by windsor | with no comments
Filed under: ,

Application Settings Made Easy with My and Visual Basic 2005

Most applications require some configuration settings that could change over time. Classic examples would be a connection string to a database, the URL to your company web site, or the path to a log file. These settings could be stored in the application itself but this would mean that, should the setting change, the application would have to be modified, recompiled, and redeployed. A better approach would be to store the values of these settings in some external data store; traditionally this has been an INI file, a “plain” XML file, or the Windows registry.

When .NET was introduced it included built in support for configuration files which, amongst other things, could store application settings. To store settings you have to add specific XML tags and values into the configuration file so that associated classes in the Framework will be able to access them. For example, if you wanted to add a setting called AppBackColor you would include the following in your configuration file:

<configuration>
  <appSettings>
    <add key=”AppBackColor” value=”AntiqueWhite” />
  </appSettings>
</configuration>

You would then be able to access the setting using:

Imports System.Configuration
Private Sub Form1_Load(...) Handles MyBase.Load
    Dim backColor As String
    backColor = ConfigurationSettings.AppSettings("AppBackColor")
    Me.BackColor = Color.FromName(backColor)
End Sub

There are three main issues with this procedure. First, you need to know the format of XML that’s needed in the configuration file. Second, you access the individual settings by passing their name as a string to the AppSettings object. And third, the setting value comes back to you as a string.

This means you have three potential points of failure that will all rear their ugly heads at runtime. You could potentially put improperly formatted XML in the configuration file, you could type the name of the setting incorrectly when trying to access it, and you could give the setting an invalid value (in the example above that would be something that is not a know color to .NET).

In Visual Basic 2005 you have another option. Microsoft has added both Visual Studio designers and new .NET Framework classes to make management and use of settings much, much easier. To add a new setting or to change an existing one, open your project properties, select the Settings tab, and you will be presented with the settings editor grid (see Figure 1).

Settings Grid with an application setting

Figure 1 – Settings Grid with an application setting

Each setting now has four properties instead of just the two used previously. The Name and Value are there as before but now you also have a Type and a Scope. The Type property allows us to strongly type the setting, meaning that you cannot set an initial Value that is not of the correct type and when you use the setting in code you will not have to cast or convert it from a string. The final property is Scope which can be set to Application or User. Application scoped settings are read-only and serve the same function as settings in previous versions of Visual Basic while user scoped settings are specific to an individual user and can be modified in code. User scoped settings will be discussed later in this article.

The data you’ve entered in the settings grid is saved in the configuration file as before, it’s just done for us by the designer. You don’t have to know which tags are required and what their attributes are nor do you have to worry about spelling or capitalization mistakes. Entering the settings shown in Figure 1 will result in this being added to the configuration file:

<configuration>
  <!-- other stuff not related to settings -->
  <applicationSettings>
    <SettingsDemo.My.MySettings>
      <setting name="AppBackColor" serializeAs="String">
        <value>AntiqueWhite</value>
      </setting>
    </SettingsDemo.My.MySettings>
  </applicationSettings>
</configuration>

Now that the new setting has been configured, it can be used in your code. In this case you could use it to initialize the background color of the main form. The setting is accessed using the My namespace (which is a major addition to Visual Basic 2005) and is much cleaner than our previous example.

Private Sub Form1_Load(...) Handles MyBase.Load
    Me.BackColor = My.Settings.AppBackColor
End Sub

It’s important to note that AppBackColor has become a property of the Settings class. When your application starts, Visual Basic reads the settings from the configuration file and builds these properties dynamically. Because your setting is now a property you don’t have to worry about typing the name incorrectly (you’ll get a compiler error if you do) and you get the benefits of strong typing. That is the value of the AppBackColor property is a Color, not a string that needs to be converted to a Color.

You can see that these new features address the issues found in the older settings architecture and greatly ease the process of managing and using application settings. But wait, there’s more! There’s still user scoped settings to cover.

Designer and .NET Framework support for user scoped settings, or per-user settings, is wholly new to Visual Basic 2005 (For information on how to accomplish this in previous versions of Visual Basic.NET, see Rocky Lhotka’s article entitled Storing User Configurations which can be found at http://shrinkster.com/c3x). User settings are used in much the same way as application settings but the effect is quite different.

You add a user setting in exactly the same way as an application setting but you set the Scope to User. Figure 2 shows a user setting called UserFont with an initial value of Microsoft Sans Serif, 8.25pt.

Settings Grid with an application and a user setting

Figure 2 – Settings Grid with an application and a user setting

This new setting will update the configuration file to look like this:

<configuration>
  <!-- other stuff not related to settings -->
  <userSettings>
    <SettingsDemo.My.MySettings>
      <setting name="UserFont" serializeAs="String">
        <value>Microsoft Sans Serif, 8.25pt</value>
      </setting>
    </SettingsDemo.My.MySettings>
  </userSettings>
  <applicationSettings>
    <SettingsDemo.My.MySettings>
      <setting name="AppBackColor" serializeAs="String">
        <value>AntiqueWhite</value>
      </setting>
    </SettingsDemo.My.MySettings>
  </applicationSettings>
</configuration>

And, as before, the new setting can now be used in code.

Private Sub Form1_Load(...) Handles MyBase.Load
    Me.BackColor = My.Settings.AppBackColor
    Me.Font = My.Settings.UserFont
End Sub

This, however, is where the similarities end. As mentioned previously, user settings are specific to a user and can be modified at runtime. So what happens when you change a setting for a user? Let’s assume you have a menu option that lets the user change the font for the main form of our application. If the user does change the font, you’ll likely want to save their choice so that you can restore it the next time the application runs. To do this you will use the UserFont setting.

When the application closes you will set UserFont to the font of the main form and then save the setting.

Private Sub Form1_FormClosed(...) Handles Me.FormClosed
    My.Settings.UserFont = Me.Font
    My.Settings.Save()
End Sub

When you do this a user specific configuration file called user.config will be created in a folder under the Documents and Settings for the person currently logged in to Windows. This file will store the setting data specific to that user.

Nice? It gets even better. You can actually achieve the same result without any code. The Windows Forms designer supports binding user settings to properties of forms or controls. For example, you could bind the UserFont setting to the Font property of our application’s main form (Form1). In the Properties Window for Form1 find (ApplicationSettings) and expand it. Then select (PropertyBinding) and click the button with the ellipses to open the binding editor form (see Figure 3). Finally, select the Font property, click the dropdown, and select UserFont from the list.

Binding a user setting to a property

Figure 3 – Binding a user setting to a property

With this done you no longer need to set the Font property in the Form’s Load event and you don’t need to set UserFont in the FornClosed event either. The data binding handles this for us.

The last thing to mention is the call to My.Settings.Save which you saw in the FormClosed event. This actually wasn’t necessary, it was added it for completeness. If you look in the Application tab of your Project Properties you’ll see a CheckBox with the caption “Save My.Settings on Shutdown” (see Figure 4). If this is checked (and it is by default) then Visual Basic will automatically save user settings just before the application terminates. The combination of this option and the visual tools to bind settings to form and control properties give you a no-code solution for implementing user settings.

Enabling the automatic saving if user settings

Figure 4 – Enabling the automatic saving if user settings.

As you’ve seen, the addition of My to Visual Basic 2005, new classes to the .NET Framework 2.0 and new designers to Visual Studio 2005 vastly improves our ability to manage and use application and user specific settings in our applications.

Posted by windsor | with no comments

Some Specifics on Generics

Generics are the most significant language addition to .NET 2.0. They allow for code re-use in ways not previously available and make it much easier to write type-safe, better performing code. That is, they help you turn runtime exceptions into compile-time errors while making your application run faster. Sound good?

What’s the Problem?
The classic example used to demonstrate the problem Generics solve is the general purpose collection. In .NET 1.1 collection classes like the ArrayList and HashTable are object based so they can store data of any type. Unfortunately this benefit has a cost, the lack of type safety. The user of the ArrayList cannot restrict the types it stores, which can potentially lead to runtime errors.

Dim al As New ArrayList()
al.Add(11)
al.Add(42)
al.Add(18.0)  ' will cause a runtime error in the for loop
Dim sum As Integer = 0
For i As Integer = 0 To al.Count
    sum += CInt(al(i))
Next

ArrayList al = new ArrayList();
al.Add(11);
al.Add(42);
al.Add(18.0);  // will cause a runtime error in the for loop
int sum = 0;
for (int i = 0; i < al.Count; i++) { sum += (int)alIdea; }

The solution to this problem in .NET 1.1 is to create a strongly-type collection class by inheriting from CollectionBase (or DictionaryBase is you want HashTable like functionality). While this task is not difficult it is tedious and leads to code bloat. You have to write almost exactly the same code for each and every type which requires a strongly-typed collection.

Public Class IntCollection
    Inherits CollectionBase
    Default Public Property Item(ByVal index As Integer) As Integer
        Get
            Return (CType(List(index), Integer))
        End Get
        Set(ByVal Value As Integer)
            List(index) = Value
        End Set
    End Property
    Public Function Add(ByVal value As Integer) As Integer
        Return (List.Add(value))
    End Function
    Public Function IndexOf(ByVal value As Integer) As Integer
        Return (List.IndexOf(value))
    End Function
    Public Sub Insert(ByVal index As Integer, ByVal value As Integer)
        List.Insert(index, value)
    End Sub
    Public Sub Remove(ByVal value As Integer)
        List.Remove(value)
    End Sub
End Class

public class IntCollection : CollectionBase
{
    public int this[int index]
    {
        get { return ((int)List[index]); }
        set { List[index] = value; }
    }
    public int Add(int value)
    {
        return (List.Add(value));
    }
    public int IndexOf(int value)
    {
        return (List.IndexOf(value));
    }
    public void Insert(int index, int value)
    {
        List.Insert(index, value);
    }
    public void Remove(int value)
    {
        List.Remove(value);
    }
}

A second problem is performance. Value types need to be boxed when being added to the collection and the unboxed when they are retrieved. This is a “double whammy” because not only do you pay the penalty for boxing but you also add more and more work to the garbage collection mechanism as the collection grows. Even if you’re storing reference types there is still some penalty for casting.

Using Generics
Generics are designed to address the issues stated above without sacrificing developer productivity. The idea is to allow classes to be parameterized by the types they store and manipulate. The type parameter or parameters, which are enclosed in angle brackets and separated by commas, can be added to a class or method declaration. The type parameter acts as a placeholder for the actual type that will be used at runtime. For example you could create a generic Stack class:

Public Class Stack(Of T)
    Private _items As New List(Of T)
    Public Sub Push(ByVal item As T)
        _items.Add(item)
    End Sub
    Public Function Pop() As T
        If _items.Count = 0 Then
            Throw New InvalidOperationException("Stack is empty")
        End If
        Dim index As Integer = _items.Count - 1
        Dim item As T = _items(index)
        _items.RemoveAt(index)
        Return item
    End Function
End Class

public class Stack<T> {
    private List<T> _items = new List<T>();
    public void Push(T item) { _items.Add(item); }
    public T Pop() {
        if (_items.Count == 0) {
            throw new InvalidOperationException(“Stack is empty”);
        }
        int index = _items.Count – 1;
        T item = _items[index];
        _items.RemoveAt(index);
        return item;
    }
}

In this case the type parameter is T (it is common practice to use a single capital letter as the name for a type parameter but you are free to use more descriptive names if you choose) so the type would be know as “Stack of T”. T is used as the type for the regular parameter to Push and the return type of Pop. It is interesting to note that it is also used as the type argument in the construction of the internal List of items. The type argument defines the specific type you wish to use for that instance of the generic class.

The .NET Framework 2.0 adds several new generic collection classes in the System.Collections.Generic namespace, the most commonly used being List<T> (the generic version of ArrayList) and Dictionary<K, T> (the generic version of HashTable).

Dim al As New List(Of Integer)
al.Add(11)
al.Add(42)
al.Add(18.0)  ' will cause a complie time error
Dim sum As Integer = 0
For i As Integer = 0 To al.Count
    sum += al(i)  ' no cast or unboxing required
Next

List<int> al = new List<int>();
al.Add(11);
al.Add(42);
al.Add(18.0);  //will cause a complie time error
int sum = 0;
for (int i = 0; i < al.Count; i++) { 
    sum += alIdea; // no cast or unboxing required
}

Generic Methods
You have seen adding type parameters to classes, you can do the same thing for methods. This can be done even if the class itself is not generic. To do this you use the same syntax style as with classes, adding the type parameter after the name of the method but before the regular parameter list.

Private Class Utility
    Public Function Max(Of T)(ByVal a As T, ByVal b As T) As T
        If a > b Then
            Return a
        End If
        Return b
    End Function
End Class
' usage of Max
Public Sub MaxTest()
    Dim u As New Utility()
    Dim i As Integer = u.Max(Of Integer)(7, 11)
    ' Use type inference
    Dim d As Double = u.Max(10.0, 42.42)
End Sub

private class Utility
{
    public T Max<T>(T a, T b)
    {
        if (a > b) { return a; }
        return b;
    }
}
 
// usage of Max
public void MaxTest()
{
    Utility u = new Utility();
    int i = u.Max<int>(7, 11);
    double d = u.Max(10.0, 42.42);  //OK, uses type inference
}

When using generic methods, the C# compiler is able to infer the type arguments from the types of the regular parameters passed so you do not have to explicitly state them.

Constraints
Time to “fess up”, the code for the Max method in the example directly above does not compile. The condition (a > b) causes a compiler error because it does not have meaning for all possible values of T. To get it to work you need to modify the code somewhat.

Public Class Utility
    Public Function Max(Of T)(ByVal a As T, ByVal b As T)
        If a.CompareTo(b) > 0 Then
            Return a
        End If
        Return b
    End Function
End Class

public class Utility
{
    public T Max<T>(T a, T b)
    {
        if (a.CompareTo(b) > 0) { return a; }
        return b;
    }
}

OK, it still doesn’t compile. Using CompareTo is a valid solution but it requires that the type assigned to T implement the IComparable interface. You need to indicate this constraint to the C# compiler. This requires one additional code change.

Public Class Utility
    Public Function Max(Of T As IComparable(Of T)) _
        (ByVal a As T, ByVal b As T)
        If a.CompareTo(b) > 0 Then
            Return a
        End If
        Return b
    End Function
End Class

public class Utility
{
    public T Max<T>(T a, T b) where T : IComparable<T> 
    {
        if (a.CompareTo(b) > 0) { return a; }
        return b;
    }
}

Other common constraints are: requiring a particular base type for the type argument, indicating that the type argument must be a reference type or value type, and indicating that the type argument must have a default constructor.

Conclusion
Generics are better for you than Broccoli (assuming that easier to write, type-safe, performant code is important to you, if not the please do a Google search for Ruby to find material more to your taste). As you work with .NET 2.0 you will begin to get the “Zen of Generics” and then you will see that the immediate benefits of strongly-typed collections are really just the tip of the Iceberg<T> where T : Big, ICold.

Posted by windsor | with no comments

Blog Chain Letter (err... Tag)

I don't know if this is the next big blog thing or not but I have been chosen to participate. Through the ether of the blogosphere I have been tagged by D'Arcy Lussier, who was tagged by Matt Ranlett, who was tagged by Brendon Schwartz, who was tagged by Shawn Wildermuth, who didn't wait to get tagged by Jeff Pulver.

According to the storied history of this process I am supposed to tell you five things about myself that you, gentle reader, probably do not know. Mom, this is the point at which you should stop reading this post.

  1. I did not use a computer until my first year of university. I started my post-secondary education looking to be a math teacher and only took a computer course because it was required by all science students. I really enjoyed it and started to tak others as electives. When I didn't get in to teacher's college I switched majors to computer science. The rest, as they say, is history.
  2. I'm a horrible two-finger typist. It's shamefull for someone who's been in the industry for so long but it's true. I hope to one day address this issue. I also hope to one day win the lottery without ever buying tickets.
  3. It takes my a long time to write anything (e.g. email, blog posts, articles, etc.). For example this post will take upwards of an hour. I have been getting better at it and plan to start adding more articles here to continue to improve. Hopefully this will lead to published articles and perhaps a book or two one day.
  4. I'm a pretty decent golfer when I get a chance to play. Right now I'm about a 16 handicap but I can get that down to 11 or 12 if I play every week. A couple years ago I went to four wedges, (PW, 53, 56 and 60) and that has really helped my short game. I rarely have to take a 1/2 or 3/4 swing anymore.
  5. From the chair in my home office and can see nine computers, two TVs, two DVD players, two XBOXes, a VCR, and a digital cable box. I would be embarassed to tell you what's in the other rooms of my home.

There, now you know me like we have been friends forever. You can come by anytime and crash on my couch and I can ask you to lend me some money (please check your email, the request will be arriving shortly).

My last duty, according to the Blog Tag Manifesto, is to tap five more people. I'll start with newly awarded MVP Chris Dufour. Since I picked Chris I'll add his partners in crime at the East of Toronto .NET User Group: Jean-Luc David and Kate Gregory. To finish off the list I'll go with two of my ObjectSharp homies: Barry Gervin and Bruce Johnson.

Blog away!

Posted by windsor | 1 comment(s)
Filed under:

Microsoft MVP - Year Four

I just received the email, I have been awarded as a Microsoft Most Valuable Professional (MVP) for another year. It always great to be recognized for your efforts but it feels somewhat strange to be receive an award for something you love to do. Anyway, I'm proud to be included amongst the group of talented and community minded individuals that make up the MVP team.

https://mvp.support.microsoft.com/profile=DB17DD56-DBFF-4992-BD11-9E047D691F2A

Posted by windsor | 2 comment(s)
Filed under: