396

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?

tpower
  • 56,100
  • 19
  • 68
  • 100
  • Unless of course, you're dealing with ASP.NET MVC which will throw this error `Cannot perform runtime binding on a null reference`. – Mrchief Jan 08 '15 at 03:58
  • Related: [ArgumentNullException or NullReferenceException from extension method?](https://stackoverflow.com/q/463302/3258851) – Marc.2377 May 24 '19 at 17:20

9 Answers9

459

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.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    Marc, you're talking about “virtual” calls – but the same is true for nonvirtual calls on instance methods. I think the word “virtual” here is misplaced. – Konrad Rudolph May 11 '09 at 09:11
  • 8
    @Konrad: It depends on the context. The C# compiler usually uses callvirt even for non-virtual methods, precisely to obtain a null check. – Jon Skeet May 11 '09 at 09:33
  • I was referring to the difference between call and callvirt il instructions. In one edit I actually tried to href the two Opcodes pages, but the editor barfed at the links... – Marc Gravell May 11 '09 at 09:48
  • 2
    I don't see how this use of extension methods can be any useful, really. Just because it can be done doesn't mean it's right, and as Binary Worrier mentioned below, it looks to me more like an aberration to say the least. – Trap May 11 '09 at 09:56
  • 3
    @Trap: this feature is great if you're into functional-style programming. – Roy Tinker Sep 28 '11 at 20:07
  • @Trap: I would aver that there should have been a way to specify that non-virtual members should be invokable on null objects, especially for immutable types which are supposed to have value semantics (e.g. strings). In systems before .net, an array of strings would default to holding empty strings (since a null pointer was an acceptable representation of an empty string). If non-virtual methods on string could be used on null strings, that would have made a lot of code much cleaner. – supercat Jan 15 '12 at 18:54
  • An additional note here - You should null check within extension methods. e.g. `test.Replace("m", "0").Replace("M", "1");` in an extension method will fail. – JsAndDotNet Mar 29 '21 at 09:17
  • what a nice feature :) – Daniel Feb 02 '22 at 17:13
  • Though the answer is accurate, would you encourage this pattern? – l33t Aug 29 '23 at 07:28
  • @l33t I'm perfectly comfortable with it – Marc Gravell Aug 29 '23 at 16:08
54

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".

Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
  • 36
    Why would it warn "always cause a System.NullReferenceException". When in fact, it never will? – tpower May 11 '09 at 09:03
  • 2
    @tpower: certainly because this check has never been updated to handle extension methods correctly. I found it when I tried to call an extension method that actually only needs the type of the argument, but I didn't have an instance. Now I have to call a static method which is much longer. – Stefan Steinegger May 11 '09 at 09:37
  • 54
    Luckily, we programmers only care about errors, not warnings :p – JulianR May 11 '09 at 11:45
  • 7
    @JulianR: Yes, some do, some do not. In our release build configuration, we treat warnings as errors. So it just doesn't work. – Stefan Steinegger May 11 '09 at 12:24
  • 10
    Thanks for the note; I'll get this in the bug database and we'll see if we can fix it for C# 4.0. (No promise -- since it is an unrealistic corner case and merely a warning, we might punt on fixing it.) – Eric Lippert May 11 '09 at 17:25
  • 3
    @Stefan: Since it's a bug and not a "true" warning, you could use a #pragma statement to supress the warning to get the code pass your release build. – Martin R-L Jan 13 '10 at 08:34
  • @Martin: Yes, but this doesn't make sense. Extension methods are only for nicer syntax. If it requires a pragma, it is all for the birds. – Stefan Steinegger Jan 13 '10 at 08:45
  • 2
    This has been [reported](http://connect.microsoft.com/VisualStudio/feedback/details/695362/c-compiler-gives-incorrect-warning-expression-will-always-cause-a-system-nullreferenceexception-for-extension-methods). MS accepts the weirdness, but says fixing it is not on the top of their priority. – nawfal Dec 19 '13 at 08:42
  • @EricLippert In that case consider expression trees too. Like with `Expression> e = () => default(Person).ToString());` you get the same warning, except its not a problem if expression tree is not compiled (but only analysed). Both these exist in VS 2012 compiler as well. – nawfal Dec 19 '13 at 08:45
  • 2
    @nawfal: Well there's nothing I can do about it now! Bug the C# compiler team if you really want this warning fixed. – Eric Lippert Dec 19 '13 at 14:53
33

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.

Jordão
  • 55,340
  • 13
  • 112
  • 144
  • 4
    Voted this up because it is correct and makes sense to me (and well-written), while I also prefer the use described in answer by @Marc Gravell. – qxotk Jul 27 '18 at 21:48
22

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#.

Trap
  • 12,050
  • 15
  • 55
  • 67
Binary Worrier
  • 50,774
  • 20
  • 136
  • 184
  • I agree with you, this only might lead to confusion. – Trap May 11 '09 at 09:47
  • 22
    Indeed, to me it's like asking a corpse "Are you alive" and getting a answer of "no". A corpse can't respond to any question, neither should you be able to "call" a method on a null object. – Binary Worrier May 11 '09 at 10:20
  • Ruby does something similar with .nil? - I personally don't see anything wrong with it. It doesn't hurt readability and it can make it more readable - such as a IsNullOrEmpty or any other such combination of expectations. – cfeduke Jul 24 '09 at 17:51
  • 16
    I disagree with Binary Worrier's logic, as it's handy being able to call extensions without worrying about null refs, but +1 for analogy comedy value :-) – Tim Abell Aug 02 '11 at 10:01
  • @BinaryWorrier: The question is whether, assuming `Foo` is a class type, `Foo.Something()` should unconditionally be regarded as an operation on the object to which `Foo` holds a reference, or whether it may be an operation on `Foo` itself. It's unfortunate that C# doesn't have separate `->` and `.` operators like C does, since that would have allowed things to be clearer. – supercat Oct 29 '12 at 21:15
  • 1
    Yeah, you can argue for it all you like, it's still something that makes my sphincter twitch, and not in a good way either. – Binary Worrier Jul 22 '13 at 14:59
  • 12
    Actually, sometimes you don't know if someone is dead, so you still ask, and the person might reply, "no, just resting with my eyes closed" – nurchi Sep 17 '14 at 01:45
  • 7
    When you need to chain several operations (say 3+), you can (assuming no side-effects) turn several lines of boring boilerplate null-checking code into a elegantly chained one-liner with "null-safe" extension methods. (Similar to the suggested ".?"-operator, but admittedly not as elegant.) If it's not obvious an extension is "null-safe" I usually prefix the method with "Safe", so if for example it is a copy-method, its name could be "SafeCopy", and it would return null if the argument was null. – AnorZaken Dec 10 '14 at 22:22
  • 4
    I laughted so hard with @BinaryWorrier answer hahahaha i saw myself kicking a body to check if it was dead or not hahaha So in MY imagination, who did check if the body was dead or not was me and not the body itself, the implementation to check was in me, activelly kicking it to see if it moves. So a body don't know if it's dead or not, WHO checks, knows, now you could argue that you could "plugin" to the body a way for it to tell you if its dead or not and that in my opinion is what an Extension is for. – Zorkind Jun 22 '18 at 15:30
  • This is the only sane answer. A decade with C# and I keep getting distracted by this glitch in the language. A developer should be able to immediately tell if a method call may throw `NullReferenceException`. Given that we now have nullable reference types, this just gets worse. E.g. `foo?.MyExtensionMethod()`. – l33t Aug 29 '23 at 07:22
11

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");

        ...

    }
Zoran Horvat
  • 10,924
  • 3
  • 31
  • 43
4

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

Jaider
  • 14,268
  • 5
  • 75
  • 82
3

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 :)

Fredrik Leijon
  • 2,792
  • 18
  • 20
1

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.

Marcel Greter
  • 275
  • 1
  • 10
0

There are few golden rules when you want in your to be readable and vertical.

  • one worth saying from Eiffel says the specific code encapsulated into a method should work against some input, that code is workable if are met some preconditions and assure an expected output

In your case - DesignByContract is broken ... you are going to perform some logic on a null instance.

ruslander
  • 3,815
  • 4
  • 32
  • 34