# 分享一個會讓人精神錯亂的 .NET 觀念 ( 神奇的 + 運算子 )

C# / .NET 是個完全物件導向的程式語言，所有的物件都有自己的型別(Type)，所以瞭解型別與善用型別是開發 .NET 應用程式很重要的基礎。

假設你現在到一間公司面試，面試官問你一個問題：「請問以下程式是否可以正常編譯並執行？」

```
Console.WriteLine(1 + "1" + true);
```

我問過 5 個會寫 .NET 的朋友，有 4 個人的回答都一樣：「不可以，因為這三個東西型別都不一樣，所以不可能被編譯，也無法執行」。

但正確答案是：「可以編譯，可以執行，而且執行結果為：**11True**」

我在過年前 Review 同事寫的程式時，發現有一段 Code 他真的是這樣寫，而且還編譯過了，編譯器還沒提供任何警告(warning)訊息，讓我當下精神錯亂，因為我無法解釋這種型別錯亂的狀況，而且這件事竟然會在 C# 中發生。

這讓我不禁想深入探討與研究為何如此，所以我親自寫了一個小程式拿去 C# 編譯器編譯，然後再用 [Reflector](http://www.red-gate.com/products/reflector/) 反組譯回來，看看實際編譯後的程式碼長的怎樣。

1\. 將以下程式碼編譯，但反組譯後的結果一模一樣：

```
Console.WriteLine(1 + "1" + true);
```

2\. 然後再試試以以下這段：

```
Console.WriteLine(1 + "1" + true + DateTime.Now);
```

反組譯的結果就不太一樣了，變成以下程式：

```
Console.WriteLine(string.Concat(new object[] { 1, "1", true, DateTime.Now }));
```

3\. 然後再試著用兩個 object 進行相加，這次就無法再編譯了：

```
object i = 1;
object j = "OK";
Console.Write(i + j);
```

\---

接著，我就往 MSDN 聖殿尋找[解答](http://msdn.microsoft.com/zh-tw/library/aa691375\(en-us,VS.71\).aspx)，最後真的給我找到關於這點疑問的說明：

> The binary + operator performs string concatenation when one or both operands are of type string. If an operand of string concatenation is null, an empty string is substituted. Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. If ToString returns null, an empty string is substituted.

由此可知 C# 的加號( + )運算子預設就支援字串串加的功能，只要一群字串串接的物件中只要有一個以上的物件型別是「字串」的話，就會全部變成「字串相加」，只要遇到「非字串」的物件，預設會使用繼承至 object 物件的 ToString() 方法進行轉型，讓所有物件都變成「字串」後進行相加動作。如果物件回傳值為 null 的話，也會改以空字串替代。

我想這一個觀念在未來也許可以拿來當成我面試程式設計師的題目。^^

**相關連結**

-   [C# Language Specification - 7.7.4 Addition operator](http://msdn.microsoft.com/zh-tw/library/aa691375\(en-us,VS.71\).aspx)
-   [C# Programmer's Reference + Operator](http://msdn.microsoft.com/zh-tw/library/k1a63xkz\(en-us,VS.71\).aspx)
-   [C# 程式設計人員參考手冊](http://msdn.microsoft.com/zh-tw/library/aa288435\(VS.71\).aspx)
