Reputation: 56866
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?
Upvotes: 411
Views: 73000
Reputation: 11
You can use different different methods for different references types for checking like,
For IEnumerable type you can use,
public static bool IsNullOrEmpty(this IEnumerable<T> enumerableList) { return enumerableList == null || !enumerableList.Any(); }
Just like that we can create different different according to our need.
public static bool IsNullOrEmpty(this Datatable dataTable) { return dataTable == null || dataTable.Rows.Count == 0; }
This should help
Upvotes: 1
Reputation: 471
Note that if your object is member of another object, which might be null, the extension method will not be called because of short-circuiting, but will result in null. For example
var res = myObj?.MemberString.IsNullOrEmpty();
will make res being of type bool? - so using it in an if() condition will raise a compiler error. Solution
var res = (myObj?.MemberString).IsNullOrEmpty();
Now res is of type bool because the extension method is being called always.
Important for older C# versions (no support for nullable): This principle is particularly important in case the extension method returns an object, because then the difference will not be detected by the compiler. This can lead into a NullReferenceException, although the code appears to be safe here. Solution in this case is also to insert the braces as shown above. (Outcome of discussion in C# null checking extension method on sub-object does not work)
Upvotes: -1
Reputation: 275
This edge-case behavior is now noted in the c# specs for the extension method invocations: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11893-extension-method-invocations
Unlike an instance method invocation, no exception is thrown when expr evaluates to a null reference. Instead, this null value is passed to the extension method as it would be via a regular static method invocation. It is up to the extension method implementation to decide how to respond to such a call.
Upvotes: 1
Reputation: 14874
myObject.MyExtensionMethod();
will never throw a Null Reference Exception when myObject
is null... BUT it will throw an Exception if MyExtensionMethod()
does not handle null properly.
https://dotnetfiddle.net/KqwLya
Upvotes: 4
Reputation: 11301
As others pointed out, calling an extension method on null reference causes the this argument to be null and nothing else special will happen. This gives raise to an idea to use extension methods to write guard clauses.
You may read this article for examples: How to Reduce Cyclomatic Complexity: Guard Clause Short version is this:
public static class StringExtensions
{
public static void AssertNonEmpty(this string value, string paramName)
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException("Value must be a non-empty string.", paramName);
}
}
This is the string class extension method which can be called on null reference:
((string)null).AssertNonEmpty("null");
The call works fine only because runtime will successfully call the extension method on null reference. Then you can use this extension method to implement guard clauses without messy syntax:
public IRegisteredUser RegisterUser(string userName, string referrerName)
{
userName.AssertNonEmpty("userName");
referrerName.AssertNonEmpty("referrerName");
...
}
Upvotes: 12
Reputation: 56457
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.
Upvotes: 34
Reputation: 64628
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"
.
Upvotes: 54
Reputation: 1062494
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.
Upvotes: 476
Reputation: 51709
A null will be passed to the extension method.
If the method tries to access the object without checking is it null, then yes, it will throw an exception.
A guy here wrote "IsNull" and "IsNotNull" extension methods that check is the reference passed null or not. Personally I think this is an aberration and shouldn't have seen light of day, but it's perfectly valid c#.
Upvotes: 22
Reputation: 3875
There are few golden rules when you want in your to be readable and vertical.
In your case - DesignByContract is broken ... you are going to perform some logic on a null instance.
Upvotes: 0
Reputation: 2802
The extensionmethod is static, so if you don't to anything to the this MyObject it shouldn't be a problem, a quick test should verify it :)
Upvotes: 3