本文翻译自: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? 是使用null值调用方法还是提供null引用异常?
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? 如果是这种情况,我永远不需要检查我的'this'参数是否为null?
#1楼
参考:https://stackoom.com/question/3YOf/在C-中-当您在null对象上调用扩展方法时会发生什么
#2楼
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. 正如您已经发现的那样,因为扩展方法只是美化的静态方法,所以在传入null
引用的情况下调用它们,而不会抛出NullReferenceException
。 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
. 那么,您应该在大多数情况下检查this
参数并在它为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: 如果方法显式处理null
值并且其名称适当地表示它,则不执行此操作,如下例所示:
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楼
As others pointed out, calling an extension method on null reference causes the this argument to be null and nothing else special will happen. 正如其他人所指出的那样,在null引用上调用扩展方法会导致this参数为null,并且不会发生任何其他特殊情况。 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: 您可以阅读本文的示例: 如何减少Cyclomatic复杂性:Guard子句短版本是这样的:
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: 这是可以在null引用上调用的字符串类扩展方法:
((string)null).AssertNonEmpty("null");
The call works fine only because runtime will successfully call the extension method on null reference. 调用工作正常,因为运行时将成功调用null引用上的扩展方法。 Then you can use this extension method to implement guard clauses without messy syntax: 然后你可以使用这个扩展方法来实现guard子句而不会出现凌乱的语法:
public IRegisteredUser RegisterUser(string userName, string referrerName)
{
userName.AssertNonEmpty("userName");
referrerName.AssertNonEmpty("referrerName");
...
}
#4楼
That will work fine (no exception). 这样可以正常工作(也不例外)。 Extension methods don't use virtual calls (ie it uses the "call" il instruction, not "callvirt") so there is no null check unless you write it yourself in the extension method. 扩展方法不使用虚拟调用(即它使用“call”il指令,而不是“callvirt”),因此除非您在扩展方法中自己编写,否则不会进行空值检查。 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 - ie 从根本上说,对静态调用的调用是非常直接的 - 即
string s = ...
if(s.IsNullOrEmpty()) {...}
becomes: 变为:
string s = ...
if(YourExtensionClass.IsNullOrEmpty(s)) {...}
where there is obviously no null check. 哪里显然没有空检查。
#5楼
extensionmethod是静态的,所以如果你不对这个MyObject做任何事情它应该不是问题,快速测试应该验证它:)
#6楼
A null will be passed to the extension method. null将被传递给扩展方法。
If the method tries to access the object without checking is it null, then yes, it will throw an exception. 如果该方法试图访问该对象而不检查它是否为null,则是,它将引发异常。
A guy here wrote "IsNull" and "IsNotNull" extension methods that check is the reference passed null or not. 这里的一个人写了“IsNull”和“IsNotNull”扩展方法,检查是否传递null。 Personally I think this is an aberration and shouldn't have seen light of day, but it's perfectly valid c#. 就个人而言,我认为这是一种失常,不应该看到日常光,但它是完全有效的c#。