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 extension 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:
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