为什么它是有效连接空string,但不要调用“null.ToString()”?
这是有效的C#代码
var bob = "abc" + null + null + null + "123"; // abc123 这不是有效的C#代码
 var wtf = null.ToString(); // compiler error 
为什么第一个陈述是有效的?
第一个工作的原因是:
来自MSDN :
在string连接操作中,C#编译器将空string视为空string,但不转换原始空string的值。
有关+二元运算符的更多信息:
当一个或两个操作数是stringtypes时,二元+运算符执行string连接。
如果string连接的操作数为空,则replace空string。 否则,通过调用从objecttypesinheritance的虚拟
ToString方法,将任何非string参数转换为其string表示forms。如果
ToString返回null,则replace空string。
第二个错误的原因是:
null(C#参考) – null关键字是表示空引用的文字,不引用任何对象。 null是引用typesvariables的默认值。
 因为C#中的+运算符在内部转换为String.Concat ,这是一个静态方法。 而这个方法恰好把null当作一个空string来处理。 如果你看看Reflector中的String.Concat的来源,你会看到它: 
 // while looping through the parameters strArray[i] = (str == null) ? Empty : str; // then concatenate that string array 
(MSDN也提到它: http : //msdn.microsoft.com/en-us/library/k9c94ey1.aspx )
 另一方面, ToString()是一个实例方法,你不能在null调用(什么types应该用于null ?)。 
第一个样本将被翻译成:
 var bob = String.Concat("abc123", null, null, null, "abs123"); 
  Concat方法检查input并将空string转换为空string 
第二个样本将被翻译成:
 var wtf = ((object)null).ToString(); 
 所以在这里会产生一个null引用exception 
 你的代码的第一部分就像在String.Concat中那样String.Concat , 
 这是C#编译器在添加string时调用的内容。  “ abc" + null被转换为String.Concat("abc", null) , 
 在内部,该方法用String.Emptyreplacenull 。 所以,这就是为什么你的第一部分代码不会抛出任何exception。 它就像 
 var bob = "abc" + string.Empty + string.Empty + string.Empty + "123"; //abc123 
在代码的第二部分抛出exception,因为'null'不是一个对象, null关键字是一个表示空引用的文字,不引用任何对象。 null是引用typesvariables的默认值。
 而' ToString() '是一个方法,可以被一个对象的实例调用,但不是任何文字。 
在.net之前的COM框架中,任何接收到string的例程在完成时都需要释放它。 由于空string被传入和传出例程是非常常见的,而且由于试图将空指针“释放”被定义为合法的无作用操作,Microsoft决定让空string指针表示一个空string。
 为了与COM有一定的兼容性,.net中的许多例程将把空对象解释为空string的合法表示。 对于.net及其语言(最明显的是允许实例成员表示“不要调用为虚拟”),微软可能已经使得声明的types为String的null对象更像空string。 如果微软已经这么做了,那么它也必须使Nullable<T>工作有些不同(以便允许Nullable<String> – 它们应该是IMHO所做的事情)和/或定义一个NullableStringtypes,与String可互换,但不会将null视为有效的空string。 
 事实上,在一些情况下, null将被视为一个合法的空string,而其他字符则不会。 不是非常有帮助的情况,而是程序员应该注意的一个情况。 通常,如果stringValue为null ,那么stringValueforms的expression式将失败,但是大多数接受string作为参数的框架方法和运算符都将null视为空string。 
  '+'是一个中缀运算符。 像任何运营商一样,它真的在调用一个方法。 你可以想象一个非中缀版本"wow".Plus(null) == "wow" 
实施者已经决定了这样的事情…
 class String { ... String Plus(ending) { if(ending == null) return this; ... } } 
所以..你的例子变成了
 var bob = "abc".Plus(null).Plus(null).Plus(null).Plus("123"); // abc123 
这是一样的
 var bob = "abc".Plus("123"); // abc123 
  null从来没有成为一个string。 所以null.ToString()与null.VoteMyAnswer()没有区别。  ;) 
 我猜是因为这是一个不涉及任何对象的文字 。  ToString()需要一个object 。 
有人在这个讨论的话题中说过, 你不能从无到有做一个string。 (这是一个很好的短语,因为我认为)。 但是,您可以 :-),如以下示例所示:
 var x = null + (string)null; var wtf = x.ToString(); 
工作正常,并没有抛出exception。 唯一的区别是你需要将一个空值转换成一个string – 如果你删除(string)转换 ,那么这个例子仍然编译,但是会抛出一个运行时exception:“运算符+”在input'<null>'和'<null>'“。
注意在上面的代码示例中,x的值不是您可能期望的,它在将其中一个操作数转换为string后实际上是一个空string。
 另一个有趣的事实是,在C#/ .NET中,如果考虑不同的数据types, null的处理方式并不总是相同的 。 例如: 
 int? x = 1; // string x = "1"; x = x + null + null; Console.WriteLine((x==null) ? "<null>" : x.ToString()); 
 关于代码片段的第一行 :如果x是包含值1的可为空的整数variables(即int? ),则返回结果<null> 。 如果它是一个值为"1"的string(如注释中所示),那么您将返回"1"而不是<null> 。 
  NB也有趣:如果你使用var x = 1; 对于第一行,那么你会得到一个运行时错误。 为什么? 因为赋值会将variablesx转换为不可为空的数据typesint 。 编译器不会假设int? 在这里,因此在添加null的第二行失败。 
 将null添加到string将被忽略。  null (在你的第二个例子中)不是任何对象的实例,所以它甚至没有ToString()方法。 这只是一个文字。 
 因为串联string时, string.Empty和null之间没有区别。 您也可以将null传递给string.Format 。 但是你试图调用一个null的方法,这总是会导致一个NullReferenceException ,因此会产生一个编译器错误。 
 如果由于某种原因,你真的想要这样做,你可以写一个扩展方法,检查null ,然后返回string.Empty 。 但是像这样的扩展只能在绝对必要时使用(在我看来)。 
一般情况:根据规范,它可能有效也可能不会有效接受null作为参数,但在null上调用方法总是无效的。
这是和其他话题,为什么+操作符的操作数可以是空string的情况下。 这是有点VB的东西(对不起,伙计们)让程序员生活更容易,或假设程序员不能处理空值。 我完全不同意这个规范。 “未知”+“任何事物”应该仍然是“未知的”…