为什么不抛出异常不理解,obj为null
object obj = null;
Console.WriteLine("Hello World " + obj);
答案 0 :(得分:21)
这将编译为
Console.WriteLine(String.Concat("Hello World ", obj));
String.Concat
method会忽略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()
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;
}
答案 1 :(得分:3)
将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 already pointed out。
*扩展方法是另一回事;它们可以在“null”参数上调用;但由于这些只表现出像实例方法一样的幻觉,因此该规则不适用于它们。实际上,扩展方法毕竟只是静态方法。如果您在null
值上打一个“on”,则表示您实际上已将null
作为参数传递。
**此处我没有将Nullable<T>
值包含在HasValue == false
中;虽然在很多情况下这些可能会被方便地视为null
,但这仅仅是为了语法上的便利:它们不再是null
,而是null
的任何其他值类型。
***我在这里谈论C#。正如SLaks在评论中指出的那样,这不是CLI本身的规则。但是,C#中的所有实例方法调用都编译为IL中的callvirt
指令,如果实例为null
,将抛出异常。
答案 2 :(得分:1)
因为那会很烦人。对于大多数pruposes,空字符串和空字符串之间没有语义差异。
答案 3 :(得分:0)
如果您在实际应用程序中遇到此问题,则可以在显示文本之前始终检查null。然后,您可以显示替代文本,或者不显示任何内容。
答案 4 :(得分:0)
因为他们实现了String.IsNullOrEmpty并留给我们来弄清楚如何使用它。