为什么不抛出异常不明白,obj 为 null
object obj = null;
Console.WriteLine("Hello World " + obj);
为什么不抛出异常不明白,obj 为 null
object obj = null;
Console.WriteLine("Hello World " + obj);
这编译为
Console.WriteLine(String.Concat("Hello World ", obj));
该String.Concat
方法忽略null
参数。
它是这样定义的:(来自.Net参考源)
public static String Concat(Object arg0, Object arg1) {
if (arg0==null) {
arg0 = String.Empty;
}
if (arg1==null) {
arg1 = String.Empty;
}
return Concat(arg0.ToString(), arg1.ToString());
}
我不知道为什么它不简单地返回arg1.ToString()
if arg0==null
。
该String.Concat(string, string)
方法定义如下:
public static String Concat(String str0, String str1) {
if (IsNullOrEmpty(str0)) {
if (IsNullOrEmpty(str1)) {
return String.Empty;
}
return str1;
}
if (IsNullOrEmpty(str1)) {
return str0;
}
int str0Length = str0.Length;
String result = FastAllocateString(str0Length + str1.Length);
FillStringChecked(result, 0, str0);
FillStringChecked(result, str0Length, str1);
return result;
}
将参数传递null
给方法不一定会引发异常;这取决于方法的实现(在这种情况下,您可能会看到一个ArgumentNullException
)。
尝试访问对象**的成员*总是会抛出, 保证***。null
NullReferenceException
所以...
object obj = null;
SomeMethod(obj); // passing as parameter
object obj = null;
int hashCode = obj.GetHashCode(); // calling instance method
对于有问题的代码,您传递给的参数Console.WriteLine
实际上是编译调用的结果string.Concat
,它允许null
将值作为参数传递并基本上忽略它们——正如SLaks 已经指出的那样。
*扩展方法是另一回事;它们可以在“空”参数上调用;但由于这些只是呈现出类似于实例方法的错觉,因此该规则不适用于它们。事实上,扩展方法毕竟只是静态方法。如果你调用一个“on”一个null
值,你实际上是null
作为一个参数传递的。
**这里我不包括Nullable<T>
带有HasValue == false
;的值 尽管在许多情况下这些可能被方便地对待null
,但这只是为了语法上的方便:它们只不过是null
任何其他值类型都可以null
。
***我在这里谈论 C#。正如 SLaks 在评论中指出的那样,这不是 CLI 本身的规则。但是 C# 中的所有实例方法调用都编译为callvirt
IL 中的指令,如果实例是null
.
因为那会很烦人。对于大多数目的来说,空字符串和空字符串之间没有语义差异。
因为他们实现了 String.IsNullOrEmpty 并将其留给我们来弄清楚如何使用它。
如果您有可能在实际应用程序中发生这种情况的问题,您可以在显示文本之前始终检查 null。然后,您可以显示替代文本,或者什么都不显示。