C# Extension Methods

After a few months I've enjoyed the newly ( or not ) added extension methods in 3.0 yesterday i discovered that one of the assumptions I've made about them was false. My assumption was that if the instance on witch you call an extension method is NULL you would get a NullReferenceException. Turns out it's not the case and you can call the extension method on a null reference.

Thinking about it later, it makes sense. In reality extension methods are nothing more than syntax sugar for calling static methods. And since too much sugar can hurt extension methods might do the same thing if not properly used. The code speaks pretty much for itself.

The class used as example:

1 public class TestClass
2 {
3     //existing method defined on the class
4     public string Hello()
5     {
6         return "Hello";
7     }
8 }

Static class defining extension method

1 public static class ExtensionContainer
2 {
3     //the extension method defined as static
4     public static string NewHello(this TestClass instance)
5     {
6         return "World";
7     }
8 }

Test code:

 1 class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5         // declare and create a test instance
 6         TestClass first = new TestClass();
 7 
 8         Console.WriteLine(first.Hello()); //outputs: "Hello"
 9         //call the extension method as a normal method
10         Console.WriteLine(first.NewHello()); // outputs: "World"
11 
12         // declare a null reference
13         TestClass second = null;
14 
15         try
16         {
17             //calling a method on a null reference throws
18             Console.WriteLine(second.Hello()); //will throw Null Reference exception
19         }
20         catch (NullReferenceException)
21         {
22             Console.WriteLine("NullReference calling Hello");
23         }
24 
25         try
26         {
27             //calling an extension method does not throw
28             Console.WriteLine(second.NewHello()); //will not throw
29         }
30         catch (NullReferenceException)
31         {
32             Console.WriteLine("NullReference calling NewHello");
33         }
34 
35         //the next two calls are exactly the same
36         Console.WriteLine(second.NewHello());
37         Console.WriteLine(ExtensionContainer.NewHello(second));
38 
39         Console.ReadKey();
40     }
41 }

Even now is still consider extension methods as a very valuable addition to the language, but you just need to understand exactly what they are. The wrong assumption about calling them on a null reference can affect some design choices you may take where in case of a null reference you want an exception to be thrown and no other method called.

Also using them when appropriate the ability to call extension methods on null references might help you write more readable code by moving the null check in the extension method. This can be particularly useful on writing extension methods that are supposed to be used in Views in ASP.NET MVC where moving the null check in the method leaves the the view's html code easier to read an understand.

One conclusion that I've drown from this is that in an extension method you should either check for null and throw NullReferenceException if null is not a valid value or handle null appropriately.

PS: Is it visible that the last 6+ months I've been working with C# and not C++ ? :)

Comments