Extension Methods - Part 3 - Best practices

In the previous posts we had a look at what extension methods are, and how they work, and now we will consider how and when to use them.

Having bought a new hammer, everything seems to look like nails, but are there any concerns that you should have when using extension methods, and what would be best practice for use?

It is tempting to take all your utility and helper wrappers and convert them to extension methods, as it increases discoverability of the method to the developer, and makes the syntax more consistent than calling a static method on a wrapper. Compare these two:

IntUtility.IsEven(even);

even.IsEven();

But I would be worried about type pollution if extensions to the for instance the string method is a free for all, in that you might end up with an extension method hell, from all the various methods your developers have glued onto the type.

The following are the concepts that I so far consider to be helpful when implementing extension methods, and there are probably more.

Use when OO concepts don't apply

Extension methods should primarily be used when normal OO concepts don't apply, like when you're dealing with sealed classes, otherwise do as you would normally would do, and forget about extension methods.

Use to create syntactic sugar and increased readability

You can create a nice facade to existing functionality giving it a fluent interface and a Ruby like feel by doing something like this:

public static class Extensions 
{ 
	public static TimeSpan minutes(this int minutes)
	{
		return new TimeSpan(0, minutes, 0); 
	} 
	public static DateTime ago(this TimeSpan timeSpan) 
	{
		return DateTime.Now.Add(timeSpan.Negate()); 
	}
}
DateTime dt = 20.minutes().Ago();

See http://blog.troyd.net/

Methods should be cohesive with the type and serve a general purpose

The method should be cohesive with the type, and adequately generic, and use inheritance where this is not the case. Consider adding a method to validate phone numbers to int. This would not make sense, as not all instances of an int would need this method. The IsEven() method on the other hand is rather cohesive. Non-cohesive cases should lead to inheritance, where you specialize your type, to a PhoneNumber type in this case, having the appropriate instance methods.

Let developers opt-in to the extensions

Let developers opt-in to the extensions by putting them in their own discoverable namespace, like "Extensions.int" in this case, optionally specializing the namespace definitions further. I would consider it bad practice to define extension methods in namespaces that you have to import like System or core third-party namespaces. The latter could force you to get extension methods that your vendor think you want, if you decide to use their product - which would be very uncool.

Don't change state of the target

I would consider changing state of the object that the extension method applies to bad practice. The extension method should consider the object immutable, and you should instead return a new object, to keep your method side effect free.

Beware of silent rebinding

Consider the case, where you add an extension method to a type from the framework or a third-party class library, and the vendor decides to add a static instance method with the same name, but with different behavior. You would not get any compiler warnings, but the instance method would shadow the extension method, and change the behavior of your application. I'm not saying this will happen often, but it might.

Extension methods are a clever way of increasing discoverability and readability of code, and a handy way of allowing you to extend classes that you otherwise couldn't.

And if used with common sense, they will most definitely be an asset in the developers toolbox. But always keep an eye out for rebinding and issues with compile time resolving of methods.

Posted April 25, 2008 by Joachim Lykke Andersen
In

Comments [0]   

Extension Methods - Part 2 - Behind the scenes

In Part one we looked at how extension methods are implemented, and what they do. It is indeed very clever, but how does it work?

Lets fire up Ildasm and a have a look at what is really going on behind the scenes.

testmethodil_thumb[1]

Looking at the IL for the example in part one we notice that the method call to the extension method is actually just translated to a static call to the method we implemented in the Extensions class.

extensionsil_thumb[4]

And we see that the Extension method has been translated to a static method with the attribute "ExtensionAttribute" indicating that its an extension method.

So actually there is nothing new in the IL to make this happen - the CLR is the same, its simply compiler magic where the ExtensionAttribute (set via the this shortcut in the method signature) ensures that a call to an extension method resolves to a another static method in the IL.

This means that you could actually use extension methods in .Net 2.0 projects. Yes its actually true!

If you take the above implementation and change the target framework to .Net 2.0 in Visual Studio 2008's multi targeting environment, and compile you will get the following error:

Error    1    Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?

Obviously you are missing the ExtensionAttribute, and you don't want to add a reference to System.Core. But as the this attribute is only needed as an indicator at compile time, you can actually just create the attribute yourself like so:

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

}

And it compiles and runs. Logical, but a little surprising none the less. See Daniel Moths original post.

So Extension methods are actually sweet syntactic sugar that doesn't add anything to the class, and that is brought to life by a very clever compiler, without ever touching the CLR.

In my next post, I will take a stab at some best practices for the use of extension methods.

Posted April 25, 2008 by Joachim Lykke Andersen
In

Comments [0]   

Extension Methods - Part 1 - The basics

Extension methods are a powerful way of gluing your own custom functionality onto types you don't own, and make them accessible like static instance methods to the type, instead of creating a wrapper around the type.

The basics

As a very simple example, we might want to have a method on the the simple int type, that evaluates whether the value is an even number.

So we simply create a static method in a static class, and use the C# extension method shortcut this in the method signature, indicating that the compiler needs to perform a little magic for us with the int type, and implement the IsEven check.

namespace Extensions
{
    public static class Extensions
    {
        public static bool IsEven(this int number)
        {
            return number % 2 == 0;
        }
    }
}

Now we can check whether the int is even or uneven with our extension method, here in a test method:

[TestMethod]
public void IsEvenTest()
{
    int even = 2;
    int uneven = 3;

    Assert.IsTrue(even.IsEven());
    Assert.IsFalse(uneven.IsEven());
}

WindowClipping

Notice that the method is marked as an extension method in our intellisense with both an icon with an arrow down and with the (extension) tag, to avoid confusion:

extensionmethods

So what you need to create an extension method is:

  • A static class
  • A static method
  • "this" in the method signature
  • Add the namespace of the extension method to your class

Pretty simple and powerful. In my next post I will look at how this actually works.

Posted April 25, 2008 by Joachim Lykke Andersen
In

Comments [0]   

ADO.NET Entity Framework Designer will support real updates from database keeping you existing entities in the next version

In the ADO.Net Entity Framework Tools CTP2 which is the currently available version, you will most likely run into unexpected behavior when attempting to update your model from database.

If you have created an entity model from your database model, and you decide to add tables and properties to existing tables, then you would expect that an update would add these tables and properties to your entity model existing mapped entities.

However this is not currently the case. The designer will simply add new entities for all tables that doesn't correspond with you entity model.

This makes iterative modeling of entities and database model impossible and is not acceptable for a real life situation.

So i am glad that the ADO.NET team today announced that the next version will fix this issue and add a number of other productivity enhancing improvements to the designer.

Now when can we have it?

Posted April 1, 2008 by Joachim Lykke Andersen
In

Comments [0]   

Linq to SQL is for prototyping, RAD and simple static solutions

When one of our primary solutions were first developed, when I was still a freelancer at the company, I decided to go completely RAD and the solution was build completely with Subsonic.

Subsonic is awesome, and I enjoyed it greatly - the RAD effect is amazing, and you really move.

The created architecture although build to RAD extremes, has grown out of our hands, and is to say the least, not at all maintainable. For a complicated solution, the "on the spot" generated data access without well defined tiers just doesn't cut it. Its fun building with it, but the solution is a nightmare to maintain - pure software development romanticism.

Its important to have fun while developing software, but it simply isn't fun having to do massive changes in a project that has virtually no division of responsibilities.

So our hope was to create a nice scalable architecture with Linq to SQL, and so I have been doing one proof of concept after the other combined with the MVC framework. I will save my worry about the DataContext and disconnected setups to another post, but focus instead on the problem of a data model of increased complexity having to function well with Linq to SQL.

Linq to SQL shares the wins and woes with Subsonic to a great extend. It lets you easily create a 1:1 mapping of your existing database schema to classes, and is well suited for prototyping, RAD development and simple static applications.

Linq to SQL works - for the common scenarios, and if you have a simple database, that is not normalized to a high extend - it makes perfect sense. But if you have a complicated and highly normalized database layout, you will truly face the O/R dilemma: You don't need a relational representation of data in your application, you want logical objects.

In enterprise scenarios you might even have multiple data stores, and a very competent and entreprenant DBA who keeps making changes to these to keep up performance and so forth.

So while Linq to SQL lets you build strongly typed objects from tables and views, call stored procedures that return strongly typed results, represent foreign-keys as strongly typed relationships, and extend the generated classes - you will be fighting the O/R problem if you want a neat and logical data representation, as you are rather strongly coupled with the schema of your database.

What we need are objects that correspond with those you would define in your use cases and er diagrams, not objects created with a 1:1 relationship with tables in the database.

We are not going to use Linq to SQL, but at the moment we a looking into the ADO.NET Entity Framework instead, which seems to fulfill many of our demands, but I will keep you posted on our progress.

Posted April 1, 2008 by Joachim Lykke Andersen
In

Comments [0]