在 C# 中,当您在空对象上调用扩展方法时会发生什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/847209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In C#, what happens when you call an extension method on a null object?
提问by tpower
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?
如果是这种情况,我将永远不需要检查我的“this”参数是否为空?
采纳答案by Marc Gravell
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:
这将工作正常(也不例外)。扩展方法不使用虚拟调用(即它使用“call”il 指令,而不是“callvirt”),因此除非您自己在扩展方法中编写它,否则没有空检查。这在一些情况下实际上很有用:
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.
显然没有空检查。
回答by Fredrik Leijon
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 :)
扩展方法是静态的,所以如果你对这个 MyObject 不做任何事情,它应该不是问题,快速测试应该验证它:)
回答by Binary Worrier
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.
如果该方法尝试访问对象而不检查它是否为空,那么是的,它将抛出异常。
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#.
这里的一个人写了“IsNull”和“IsNotNull”扩展方法来检查引用是否传递为空值。就我个人而言,我认为这是一种异常现象,不应该出现在白天,但它是完全有效的 c#。
回答by Stefan Steinegger
Addition to the correct answer from Marc Gravell.
除了 Marc Gravell 的正确答案。
You could get a warning from the compiler if it is obvious that the this argument is null:
如果很明显 this 参数为空,您可能会收到编译器的警告:
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"
.
在运行时运行良好,但会产生警告"Expression will always cause a System.NullReferenceException, because the default value of string is null"
。
回答by ruslander
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
- 来自 Eiffel 的一位值得一提的是,封装到方法中的特定代码应该针对某些输入工作,如果满足某些先决条件并确保预期输出,则该代码是可行的
In your case - DesignByContract is broken ... you are going to perform some logic on a null instance.
在你的情况下 - DesignByContract 被破坏了......你将在一个空实例上执行一些逻辑。
回答by Jord?o
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 behaveas 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:
正如您已经发现的那样,由于扩展方法只是美化的静态方法,它们将null
通过传入的引用被调用,而不会NullReferenceException
被抛出。但是,由于它们对调用者来说看起来像实例方法,因此它们的行为也应该如此。然后,在大多数情况下,您应该检查this
参数并在它是null
. 如果方法明确处理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 postabout this some time ago.
回答by Zoran Horvat
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.
正如其他人指出的那样,在空引用上调用扩展方法会导致 this 参数为空,并且不会发生任何其他特殊情况。这提出了使用扩展方法来编写保护子句的想法。
You may read this article for examples: How to Reduce Cyclomatic Complexity: Guard ClauseShort version is this:
您可以阅读这篇文章作为示例:How to Reduce Cyclomatic Complexity: Guard ClauseShort 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");
...
}