为字符串添加null时为什么没有exception?

为什么不抛出exception不理解,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()如果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参数传递给方法不一定会抛出exception; 这取决于方法的实现(在这种情况下,您可能会看到ArgumentNullException )。

试图访问null对象的成员 * **将始终抛出NullReferenceException ,保证***。

所以…

可能会或可能不会抛出exception

 object obj = null; SomeMethod(obj); // passing as parameter 

肯定会抛出exception

 object obj = null; int hashCode = obj.GetHashCode(); // calling instance method 

在有问题的代码的情况下,传递给Console.WriteLine的参数实际上是对string.Concat的编译调用的结果,它允许将null值作为参数传递并基本上忽略它们 – 正如SLaks已经指出的那样出去


*推广方法是另一回事; 它们可以在“null”参数上调用; 但由于这些只表现出像实例方法一样的幻觉 ,因此这条规则并不适用于它们。 实际上,扩展方法毕竟只是静态方法。 如果您将一个“on”称为null值,则实际上将null作为参数传递。

**这里我没有包含Nullable值和HasValue == false ; 虽然在许多情况下这些可能很方便地被视为null ,但这仅仅是为了语法上的方便:它们不会比任何其他值类型都为null

***我在这里谈论C#。 正如SLaks在评论中指出的那样,这不是CLI本身的规则。 但是C#中的所有实例方法调用都被编译为IL中的callvirt指令,如果实例为null则会抛出exception。

因为那会很烦人。 对于大多数pruposes,空字符串和空字符串之间没有语义差异。

如果您遇到实际应用程序中可能出现此问题的问题,则可以在显示文本之前始终检查null。 然后,您可以显示替代文本,或者不显示任何内容。

因为他们实现了String.IsNullOrEmpty并留给我们来弄清楚如何使用它。