是否使用空值调用方法,或者它是否提供空引用异常?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
如果是这种情况,我将永远不需要检查我的'this'参数是否为null?
答案 0 :(得分:352)
这样可以正常工作(也不例外)。扩展方法不使用虚拟调用(即它使用“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);
}
等
从根本上说,对静态调用的调用是非常直接的 - 即
string s = ...
if(s.IsNullOrEmpty()) {...}
变为:
string s = ...
if(YourExtensionClass.IsNullOrEmpty(s)) {...}
显然没有空检查。
答案 1 :(得分:48)
除了Marc Gravell的正确答案。
如果显然该参数为null,则可以从编译器收到警告:
default(string).MyExtension();
在运行时运行良好,但会产生警告"Expression will always cause a System.NullReferenceException, because the default value of string is null"
。
答案 2 :(得分:20)
正如您已经发现的那样,因为扩展方法只是美化的静态方法,所以在传入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;
}
}
我前段时间也写过a blog post。
答案 3 :(得分:14)
null将传递给扩展方法。
如果方法试图访问该对象而不检查它是否为null,则是,它将引发异常。
这里的一个人写了“IsNull”和“IsNotNull”扩展方法,检查是否传递null。就个人而言,我认为这是一种失常,不应该看到光明,但它完全有效c#。
答案 4 :(得分:6)
正如其他人所指出的那样,在null引用上调用扩展方法会导致this参数为null,并且不会发生任何其他特殊情况。这提出了使用扩展方法编写保护子句的想法。
您可以阅读本文的示例:How to Reduce Cyclomatic Complexity: Guard Clause简短版本是:
**executed code**
这是字符串类扩展方法,可以在空引用上调用:
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);
}
}
调用工作正常,因为运行时将成功调用null引用上的扩展方法。然后你可以使用这个扩展方法来实现guard子句而不会出现凌乱的语法:
((string)null).AssertNonEmpty("null");
答案 5 :(得分:3)
extensionmethod是静态的,所以如果你对这个MyObject没有任何意义,它应该不是问题,快速测试应该验证它:)
答案 6 :(得分:0)
myObject.MyExtensionMethod();
为 null 时,myObject
永远不会抛出 Null 引用异常... 但如果 MyExtensionMethod()
没有正确处理 null,它将抛出异常 .
答案 7 :(得分:-1)
如果您希望自己具有可读性和垂直性,则几乎没有什么黄金法则。
在你的情况下 - DesignByContract已损坏......您将在null实例上执行某些逻辑。