I was half asleep yesterday when I fired off an email to my co-workers about the String.IsNullOrEmpty
method in the .NET runtime. One thing I said in the mail was:
I find it curious that IsNullOrEmpty is a static method rather than an instance method. Why can’t I say:
if (!someString.IsNullOrEmpty())
The obvious answer, as one coworker pointed out, is “because it can be null.” Calling a method on a null reference will end up throwing an exception. Embarrassing, I know. I’ll blame lack of sleep.
But I got to thinking about it later and I end up asking the same question. Let me explain.
C# 3.5 introduced extension methods, which allow you to add functionality to existing classes without having to create a derived type, recompile, or otherwise modify the original types. The idea is that you create a static class to contain the extension method, and inside that class create a static method that has a special syntax. For example, the following would create a WordCount
extension method for the String
class:
namespace ExtensionMethods { public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } }
If you then reference the namespace (with a using
statement) in the code that uses this method, you can get the word count for a string (assuming that ‘s’ is a string) by writing:
int wc = s.WordCount();
You can also call it like this:
int wc = MyExtensions.WordCount(s);
Extension methods are certainly cool, and LINQ depends on them to do what it does. Although extension methods can be very confusing and even dangerous if used indiscriminately, they’re very useful.
Think about what happens inside the compiler in order to make this possible. When the compiler sees that special “this” syntax in the extension method’s definition, it has to make an entry in its symbol table that says, in effect, “ExtensionMethods.MyExtensions.WordCount is an instance method of type System.String.” Then, when it sees that call to s.WordCount
, the compiler emits code equivalent to ExtensionMethods.MyExtensions.WordCount(s)
.
Now let’s go back to the static String.IsNullOrEmpty
method. It is defined in the String
class as:
static Boolean IsNullOrEmpty(String)
The only thing missing is the “this” syntax on the parameter. If that syntax existed, we’d be able to call IsNullOrEmpty
on a null string reference, because the compiler would have converted it into a static method call. But it wouldn’t take any changes to the .NET runtime in order to make this possible. The compiler should be able to handle it.
That is, the compiler should be able to see that you’re calling a static method using instance method syntax, and fix it up accordingly. The compiler has all the information it needs in order to do that. And with the already-existing extension method machinery built into the compiler, I can’t see that this would be especially difficult to implement. Why wasn’t it?