该方法是使用空值调用还是给出空引用异常?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
如果是这样的话,我将永远不需要检查我的“this”参数为空?
该方法是使用空值调用还是给出空引用异常?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
如果是这样的话,我将永远不需要检查我的“this”参数为空?
当前回答
extensionmethod是静态的,所以如果你不给这个MyObject添加任何东西,这应该不是问题,一个快速的测试应该可以验证它:)
其他回答
extensionmethod是静态的,所以如果你不给这个MyObject添加任何东西,这应该不是问题,一个快速的测试应该可以验证它:)
正如其他人指出的那样,在空引用上调用扩展方法会导致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");
...
}
除了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)) {...}
这里显然没有空检查。
myObject.MyExtensionMethod ();当myObject为空时,将永远不会抛出空引用异常…但是,如果MyExtensionMethod()没有正确地处理null,它将抛出异常。
https://dotnetfiddle.net/KqwLya