Archives for : December2008

Extension Methods Practically Applied

It seems odd to me that I’ve never spoken on extension methods considering the broad range of subjects I’ve covered. So here I am writing on them.

So what are extension methods? They are methods you can tack on to existing objects to extend their functionality without having to extend them.

“Brian, if you want new functionality to an object why not just inherit the object and write the methods yourself?”

“Well Ivan, what if you don’t want to? I don’t mean to be flippant but if I have string and want to add a ‘ValidateEmail’ method should I create a new class that inherits from string and then provide the ‘ValidateEmail’ class?”

“No, you simply create a static class that takes a string and returns a boolean.”

“But Ivan, that is what extension methods do while providing an interface via the VS IDE. It’s cleaner and easier to use.”

“Oh, well, um, nothing to see here”

(wow, I need to work on some better inner dialogue ;))

The reason I titled this post ‘Extension Methods Pratically Applied’ is that I wanted to put out there how I tend to use extension methods. First of all when working on development of a solution that spans multiple projects we tend to have a project named “Common”. This contains custom controls used in different projects of the solution, images and other wpf resources used in different projects and finally extension methods. Each of these exist in their own directory. If they aren’t then things tend to get awfully messy.

So let’s throw in some code for two different sets of extention methods:

namespace ProjectName.Common
{
    public static class DoubleExtensions
    {
        public static string NullToEmpty(this double? d)
        {
            return d == null ? "" : d.ToString();
        }
        public static double NullToZero(this double? d)
        {
            return d == null ? 0 : (double)d;
        }
    }
}

and

namespace ProjectName.Common
{
    public static class StringExtensions
    {
        public static string NullToEmpty(this string s)
	{
	    return s == null ? string.Empty : s;
	}
	public static string EmptyToNull(this string s)
	{
	    return (string.IsNullOrEmpty(s)) ? null : s;
        }
        public static double? ToNullableDouble(this string s)
        {
            try { return double.Parse(s); }
            catch { return null; }
        }
    }
}

First, extension methods have to be in a static class. Second, I would highly recommend naming your extension method class “ObjectExtensions” where “Object” is the type of object the extension method is for. When other programmers come along it’s nice if they know where to put in their own extension methods. Hopefully this will also help cut down on any redundancy. Third is the “this” keyword. That is what tells the framework what object the the extension method is for.

By far the most common usage for me of extension methods is within forms. The DAO generator we use is .netTiers. For nullable fields, like Height for a person in the example I’m about to show, these are presented as nullable primitives. When working with forms to show data that presents a problem. The following code does not work:

public void LoadForm(Person TargetFriendly)
{
    this.txtPersonHeight.Text = TargetFriendly.Height;
}

public void SaveForm(Person TargetFriendly)
{
    TargetFriendly.Height = this.txtPersonHeight.Text;
}

and gives me the errors “Cannot implicitly convert type ‘double?’ to ‘string'” and “Cannot implicitly convert type ‘string’ to ‘double?'”.

This is where the extension methods come in handy. At the top of our form for loading and saving person info we add ‘using ProjectName.Common’. Then we can do:

public void LoadForm(Person TargetFriendly)
{
    this.txtPersonHeight.Text = TargetFriendly.Height.NullToEmpty();
}

public void SaveForm(Person TargetFriendly)
{
    TargetFriendly.Height = this.txtPersonHeight.Text.ToNullableDouble();
}

Another great thing about this that intellisense fully supports extension methods. For my ‘ToNullableDouble’ it looks like:
ExtensionMethodsIDE

where the method has the blue down arrow. What is also here that my screen capture software doesn’t show is the tool tip that pops up that says, “(extension) double? string.ToNullableDouble()”

I would encourage you to use extension methods as they can make life a lot easier. Just make sure you put them where they can easily be found and name them appropriately.

Later,
Brian

Making Classes and Properties Immutable

Hopefully we all know string is immutable. When you type:

string x = "";
x = "asdf";

what you are really doing is creating two different strings, not changing the value, per se, of x but actually creating a new x.
That is why in heavy string operations it is recommended you use StringBuilder like:

StringBuilder sbName = new StringBuilder();
sbName.Append("asdf");

since appending to sbName doesn’t create a new string but continues to add to the string value of sbName.

So why do you care? Well, maybe you don’t. I’ve started to move into a more multi-threaded world where the state of objects and their properties could potientially be invalid if an external thread changes the value of a property. I’ve been reading Effective C# and More Effective C# and enjoying them. They are books that target specific development issues and paradigms that help you become a better C# developer. The books are written by Bill Wagner who is a regular blogger I follow.

Even though Effective C# came out in the .NET 2.0 days a lot of the book is still relevant, however, quite a few of the code samples could be updated.

Item 7 in Effective C# says “Prefer Immutable Atomic Value Types”. Now to paraphrase the chapter to an extreme it basically says, “Immutable code is easier to maintain”. I would add an addendum that whether you like it or not there is a good chance that code you write will be used in a multi-threaded environment and immutable will matter.

Now obviously to blindly say all classes must be like this is absurd. As Bill’s Item 7 says, however, “Prefer Immutable Atomic Value Types”.

In .NET 3.0 properties made things a bit easier in general. Prior to 3.0 for a property you would have to do:

private int _myInt;
public int MyInt
{
    get { return _myInt; }
    set { _myInt = value; }
}

In .NET 3.0 you don’t have to define the private. When the code is compiled it will take care of that for you. So the above code becomes:

public int MyInt { get; set; }

Now say you have to class:

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }
    public Customer(){}
}

If you were working in a multi-threaded environment you might have a problem if this happens:

public void HandleCustomerData(Customer MyCustomer)
{
    MyCustomer.FirstName = "George";

    //use myCustomer to do a bunch of stuff

    MyCustomer.FirstName = "Joe";

    //use myCustomer to do a bunch of stuff
}

This could cause a big problem if MyCustomer is getting passed around a lot in different threads. Now I know this is rather contrived but it is still a real issue.

Properties an additional feature here in 3.0 that makes things easier for creating an immutable. Imagine you have to class:

public class Customer
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public Address Address { get; private set; }
    public Customer(string FirstName, string LastName, Address Address)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
        this.Address = Address;
    }
}

You can see here that I’m using the private keyword on the set method. As it implies this forces the set methods of the properties to private so they can only be changed internally in the class. I would recommend reading “Effective C#” for a better explanation of why to use immutable values but by using the private in a property this becomes easier.

So there it is, prefer immutable atomic values in your classes and use the private keyword to help you.

Later,
Brian

Update:
The more I read this the more I think I over-simplified Bill’s reason for preferring immutable atomic value types. Just get the book and read it. It’s a fairly small book but every nugget has value.