In a recent post, I pointed out that extension methods can be called on null references. For example, this works perfectly fine:
public static void PrintToConsole(this string self)
{
if(self != null)
Console.WriteLine("The string is: " + self);
else
Console.WriteLine("The string is NULL.");
}
// Elsewhere in the code
string myString = null;
myString.PrintToConsole();
I said I’d give some examples of where this would actually be useful (not just a gimmick as it might appear on first blush).
One such case is parameter validation. Rick Brewster has come up with a fantastic approach for parameter validation, which lets your code look something like this:
public static void Copy(T[] dst, long dstOffset, T[] src, long srcOffset, long length)
{
Validate.Begin()
.IsNotNull(dst, “dst”)
.IsNotNull(src, “src”)
.Check()
.IsPositive(length)
.IsIndexInRange(dst, dstOffset, “dstOffset”)
.IsIndexInRange(dst, dstOffset + length, “dstOffset + length”)
.IsIndexInRange(src, srcOffset, “srcOffset”)
.IsIndexInRange(src, srcOffset + length, “srcOffset + length”)
.Check();
// Further code snipped.
}
No doubt that’s beautiful syntax. But one of Rick’s main goals was this: Incur the least possible overhead if the parameters are all correct. In particular, don’t instantiate any additional objects if the parameters are correct.
And the way this is achieved depends on the fact that extension methods can be called on null references. If all the parameters are OK, the Begin() method, the IsNotNull() method, and so on, all return null. However, they still have a return type, and that return type has extension methods on it called “Begin”, “IsNotNull”, “IsPositive” and so forth.