In C#, what happens when you call an extension method on a null object?
Asked Answered
S

10

404

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?

Sickler answered 11/5, 2009 at 8:35 Comment(2)
Unless of course, you're dealing with ASP.NET MVC which will throw this error Cannot perform runtime binding on a null reference.Devoid
Related: ArgumentNullException or NullReferenceException from extension method?Hydrofoil
L
467

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.

Liturgics answered 11/5, 2009 at 8:37 Comment(11)
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.Ithaman
@Konrad: It depends on the context. The C# compiler usually uses callvirt even for non-virtual methods, precisely to obtain a null check.Stellarator
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...Liturgics
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.Demetri
@Trap: this feature is great if you're into functional-style programming.Imogene
@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.Asdic
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.Maladminister
what a nice feature :)Cazares
Though the answer is accurate, would you encourage this pattern?Wean
@Wean I'm perfectly comfortable with itLiturgics
Note that this can miserably fail with null propagation: user?.Name.IsNullOrEmpty() will return null, not false. That's why I think it's a bad idea to allow null in extension methods. They are intended to be used like instance methods and therefore should behave as such.Clemons
T
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".

Topsail answered 11/5, 2009 at 8:52 Comment(11)
Why would it warn "always cause a System.NullReferenceException". When in fact, it never will?Sickler
@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.Topsail
Luckily, we programmers only care about errors, not warnings :pScotch
@JulianR: Yes, some do, some do not. In our release build configuration, we treat warnings as errors. So it just doesn't work.Topsail
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.)Frothy
@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.Monstrosity
@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.Topsail
This has been reported. MS accepts the weirdness, but says fixing it is not on the top of their priority.Vibrations
@EricLippert In that case consider expression trees too. Like with Expression<Func<string>> 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.Vibrations
@nawfal: Well there's nothing I can do about it now! Bug the C# compiler team if you really want this warning fixed.Frothy
Update (2024): it seems that at some point since the original discussion, the warning was removed. So presumably this was made an official feature.Windsor
W
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.

Wilkey answered 27/4, 2010 at 20:29 Comment(1)
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.Built
D
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#.

Diatom answered 11/5, 2009 at 8:40 Comment(10)
I agree with you, this only might lead to confusion.Demetri
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.Diatom
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.Ralph
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 :-)Grinder
@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.Asdic
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.Diatom
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"Cornstalk
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.Blanketyblank
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.Computerize
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().Wean
T
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");

        ...

    }
Tewfik answered 20/8, 2015 at 12:1 Comment(0)
W
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

Worriment answered 5/5, 2021 at 16:50 Comment(0)
T
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 :)

Tory answered 11/5, 2009 at 8:38 Comment(0)
R
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.

Reagent answered 8/4, 2023 at 5:8 Comment(0)
O
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.

Ojeda answered 11/5, 2009 at 9:7 Comment(0)
L
-1

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)

Loiretcher answered 18/10, 2023 at 13:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.