Extension methods on a null object instance
Extension methods gave developers with a lot of bandwidth to do interesting (read ‘cool’) things. But there are a couple of things that we need to be aware of while using these extension methods.
I have a StringUtil class that defines two extension methods:
1: public static class StringUtils
2: {
3: public static string Left(this string arg, int leftCharCount)
4: {
5: if (arg == null)
6: {
7: throw new ArgumentNullException("arg");
8: }
9: return arg.Substring(0, leftCharCount);
10: }
11:
12: public static string Right(this string arg, int rightCharCount)
13: {
14: if (arg == null)
15: {
16: throw new ArgumentNullException("arg");
17: }
18: return arg.Substring(arg.Length - rightCharCount);
19: }
20: }
From the code above, they print the left / right ‘n’ characters of a given string. I can call these methods as:
1: try
2: {
3: string name = "Arun Mahendrakar";
4: Console.WriteLine(name.Left(4));
5: Console.WriteLine(name.Right(11));
6: }
7: catch (Exception exception)
8: {
9: Console.WriteLine(exception);
10: }
As expected, the output is:
Now what happens if my name variable is null? For normal methods, this would throw a NullReferenceException.
1: string name = null;
2: // the below line throws a NullReferenceException
3: Console.WriteLine(name.StartsWith("abc"));
But apparently you can call an extension method even if the name instance is null. So if I run the below code, I get a ArgumentNullException that is thrown from the Left extension method (which means that the extension method was indeed called).
1: string name = null;
2: Console.WriteLine(name.Left(4));
Here’s why I think MS allows us to make this call. Forget about extension methods for a moment. Since it is a static method, we can call the Left() as:
1: string name = null;
2: StringUtils.Left(name, 4);
Even though name is null, this is a perfectly valid call and it should not throw NullReferenceException exception. In effect, this is the exact same thing we’re doing when we use Left as an extension method. In order to keep the same convention / thinking, it is my opinion that MS allowed us to make this call.
A similar argument follows why I’m throwing an ArgumentNullException and not a NullReferenceException exception. When I say ‘name.Left(4)’, the variable ‘name’ is actually being passed as an argument to the Left extension method – look at the definition of the method to know what I’m talking about.
Continuing about extension methods, LINQ reaped the most benefit from extension methods. Thanks to Jon Skeet, I used his snippet to find the extension methods declared in the System.Linq namespace and there are a whooping 500 such methods. Here’s a complete list if anyone is interested. (For some reason, I cannot do a direct link to the files anymore. The file you’re looking for is the ExtensionMethodsInSystem.LinqNamespace.txt file).