该方法是使用空值调用还是给出空引用异常?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
如果是这样的话,我将永远不需要检查我的“this”参数为空?
该方法是使用空值调用还是给出空引用异常?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
如果是这样的话,我将永远不需要检查我的“this”参数为空?
当前回答
正如其他人指出的那样,在空引用上调用扩展方法会导致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);
}
}
这是字符串类扩展方法,可以在空引用上调用:
((string)null).AssertNonEmpty("null");
调用正常工作只是因为运行时将成功地调用空引用上的扩展方法。然后你可以使用这个扩展方法来实现保护子句,而不需要混乱的语法:
public IRegisteredUser RegisterUser(string userName, string referrerName)
{
userName.AssertNonEmpty("userName");
referrerName.AssertNonEmpty("referrerName");
...
}
其他回答
myObject.MyExtensionMethod ();当myObject为空时,将永远不会抛出空引用异常…但是,如果MyExtensionMethod()没有正确地处理null,它将抛出异常。
https://dotnetfiddle.net/KqwLya
除了Marc Gravell的正确答案。
如果this参数明显为null,你可能会从编译器得到警告:
default(string).MyExtension();
在运行时运行良好,但产生警告“Expression将始终导致System. exe”。NullReferenceException,因为string的默认值是null"。
这将工作得很好(没有例外)。扩展方法不使用虚拟调用(即它使用“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
从根本上说,对静态调用的调用是非常字面化的。
string s = ...
if(s.IsNullOrEmpty()) {...}
就变成:
string s = ...
if(YourExtensionClass.IsNullOrEmpty(s)) {...}
这里显然没有空检查。
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;
}
}
前段时间我也写过一篇关于这方面的博文。
一个空值将被传递给扩展方法。
如果该方法试图访问该对象而不检查它是否为空,则是,它将抛出异常。
一个家伙在这里写了“IsNull”和“IsNotNull”扩展方法,检查引用是否传递为空。就我个人而言,我认为这是一种偏差,不应该被看到,但这是完全有效的c#。