看看C# 6.0中那些語法糖都幹了些什麼(中篇)

一線碼農發表於2014-12-22

 

  接著上篇繼續扯,其實語法糖也不是什麼壞事,第一個就是吃不吃隨你,第二個就是最好要知道這些糖在底層都做了些什麼,不過有一點

叫眼見為實,這樣才能安心的使用,一口氣上五樓,不費勁。

 

一:字串嵌入值

  我想String.Format方法就是化成灰大家都認識,比如下面程式碼:

1     class Bird
2     {
3         private string Name = "swallow";
4 
5         public void Fly()
6         {
7             var result = string.Format("hello {0}", Name);
8         }
9     }

  這個Format有一個不好的地方就是,如果佔位符太多,就特別容易搞錯,如果你少了一個引數,程式碼就會報錯。

 

接下來跟趟順風車,去看看string.Format底層程式碼,還是蠻驚訝的發現,其實底層不過呼叫的就是StirngBuilder.AppendFormat方法。

 

因為容易報錯,所以為了保險起見就用字串拼接的方式來實現,但是我也知道字串拼接是耗時的一種操作,寫個StringBuilder又嫌麻煩,

還好C#6.0中提供了一種新鮮玩法,先看程式碼:

 1     class Bird
 2     {
 3         private string Name = "swallow";
 4 
 5         public void Fly()
 6         {
 7             //var result = string.Format("hello {0}{1}", Name);
 8 
 9             var result = "\{"hello"}:\{Name}";
10 
11             Console.WriteLine(result);
12         }
13     }

 

然後就迫不及待的去看看底層怎麼玩的,其實在下面的IL圖中可以看到,在底層最終還是呼叫了String.Format方法來實現的。

 

 

二:using靜態類

  這種寫法看起來有點不倫不類的,乍一看也沒有什麼用處,不過可以告訴我們一個原理,就是不管你上層怎麼變,編譯器還是一樣使用

全命名,這就叫萬變不離其宗吧。

 

三:空值判斷

  先還是來看看這種玩法的真容。

1     class Bird
2     {
3         public void Fly(string name)
4         {
5             var result = name?.Length;
6         }
7     }

是不是看著有點眼暈?那就對了,編譯器就是這樣靜靜的端著碗看著我們寫這些裝逼的程式碼,不過再怎麼裝逼,也逃不過ILdasm的眼睛。


 

其實仔細看IL程式碼之後,覺得一切還是那麼的熟悉,重點就是這個brtrue.s。它的狀態也決定了兩條執行流,不過在IL上面也看到了V_1這個編譯

器給我們單獨定義的一個變數,程式碼還原如下:

 1     class Bird
 2     {
 3         public void Fly(string name)
 4         {
 5             int? r;
 6 
 7             if (name == null)
 8             {
 9                 int? V_1 = new Nullable<int>();
10 
11                 r = V_1;
12             }
13             else
14             {
15                 r = new Nullable<int>(name.Length);
16             }
17         }
18     }

 

四:nameof表示式

  當我知道這個關鍵字的用途時,我的第一反應就是公司框架裡面的LogManager類,當我們new LogManager的時候,會同時把當前的類名

傳遞下去,然後做些後期處理,但是在以前我們只能這麼做,要麼用反射,要麼寫死。

 1 namespace ConsoleApplication3
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             //第一種:使用反射
 8             var ilog = new LoggerManager(typeof(Program));
 9 
10             //第二種:寫死
11             ilog = new LoggerManager("Program");
12 
13             Console.WriteLine("world");
14         }
15     }
16 
17     class LoggerManager
18     {
19         /// <summary>
20         /// 建構函式記錄下類名
21         /// </summary>
22         /// <param name="type"></param>
23         public LoggerManager(Type type)
24         {
25             //todo
26             Console.WriteLine(type.Name);
27         }
28         public LoggerManager(string className)
29         {
30             //todo
31             Console.WriteLine(className);
32         }
33     }
34 }

 

我想大家也能看到,第一種使用了反射,這是需要讀取後設資料的,效能你懂的,第二個雖然是字串,你也看到了,是寫死的方式,這個時候就

急需一個加強版,就像下面這樣。

看到IL後,反正我是雞動了。。。nameof具有上面兩者的優點,既靈活,效能又高。。。。不錯不錯,贊一下。

 

相關文章