In C#, what happens when you call an extension method on a null object?
Does the method get called with a null value or does it give a null reference exception?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
If this is the case I will never need to check my 'this' parameter for null?
Solution 1:
That will work fine (no exception). Extension methods don't use virtual calls (i.e. it uses the "call" il instruction, not "callvirt") so there is no null check unless you write it yourself in the extension method. This is actually useful in a few cases:
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
public static void ThrowIfNull<T>(this T obj, string parameterName)
where T : class
{
if(obj == null) throw new ArgumentNullException(parameterName);
}
etc
Fundamentally, calls to static calls are very literal - i.e.
string s = ...
if(s.IsNullOrEmpty()) {...}
becomes:
string s = ...
if(YourExtensionClass.IsNullOrEmpty(s)) {...}
where there is obviously no null check.
Solution 2:
Addition to the correct answer from Marc Gravell.
You could get a warning from the compiler if it is obvious that the this argument is null:
default(string).MyExtension();
Works well at runtime, but produces the warning "Expression will always cause a System.NullReferenceException, because the default value of string is null"
.
Solution 3:
As you've already discovered, since extension methods are simply glorified static methods, they will be called with null
references passed in, without a NullReferenceException
being thrown. But, since they look like instance methods to the caller, they should also behave as such. You should then, most of the time, check the this
parameter and throw an exception if it's null
. It's OK not to do this if the method explicitly takes care of null
values and its name indicates it duly, like in the examples below:
public static class StringNullExtensions {
public static bool IsNullOrEmpty(this string s) {
return string.IsNullOrEmpty(s);
}
public static bool IsNullOrBlank(this string s) {
return s == null || s.Trim().Length == 0;
}
}
I've also written a blog post about this some time ago.