In C#, what happens when you call an extension met

2019-01-04 17:48发布

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?

7条回答
放我归山
2楼-- · 2019-01-04 17:57

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.

查看更多
够拽才男人
3楼-- · 2019-01-04 18:00

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

查看更多
SAY GOODBYE
4楼-- · 2019-01-04 18:00

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

查看更多
Explosion°爆炸
5楼-- · 2019-01-04 18:06

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.

查看更多
手持菜刀,她持情操
6楼-- · 2019-01-04 18:08

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

        ...

    }
查看更多
小情绪 Triste *
7楼-- · 2019-01-04 18:17

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.

查看更多
登录 后发表回答