文章出處

 

     這篇繼續聊聊 ”參數“的一些話題,我們知道參數大概有”默認參數“,”可選參數“,”ref參數“,”out參數“以及”可變參數“。

下面提幾個小問題,可能在面試中會被問到。

 

Q:請問我按照如下方式傳遞參數的時候,最后的m等于多少?

 1         static void Main(string[] args)
 2         {
 3             int k = 0;
 4 
 5             Run(k++, k++, k++);
 6         }
 7 
 8         static void Run(int i, int j, int m)
 9         {
10             //最后的m等于多少
11             Console.WriteLine(m);
12         }

 

A: 不管這個問題算不算小兒科,既然被問到了,并且又是在參數這個博文里面,當然要么直接加等于2,要么就是0,如果你在

    局部代碼區域直接寫k++,那么毫無疑問的就是k=k;k=k+1,也就是先賦值再自增,那如果作為參數的話,還是一樣嗎?

    答案當然就在IL里面。

   

從IL上我們看的很清楚,即使++操作是作為參數的形式,也是依次執行了三個add,然后add完之后再call我們的run方法。

最后得到結果毫無疑問就是2了。

 

Q:我知道默認參數是C#4.0的新特性,難道它又是一塊語法糖嗎?

1         static void Run(int i = 4)
2         {
3 
4         }

A: 可以這么說的,我們知道C#有一個限制,就是默認值必須是編譯時就能確定的常量值,既然是常量值,那么這個值就一定

    會嵌入到程序集的元數據中,老規矩,繼續看下生成的IL代碼。

如果你仔細觀察,你會發現有兩個不同的地方。

①:參數列表中的opt,這個參數其實就是編譯器給該參數打上了OptionalAtrribute標記,既然是特性,它也會嵌入到程序集

     的元數據中,下面看下它的源代碼會發現沒什么有價值的地方,就是標記這個參數是不是可選的。

 

② 我們會發現有一個param參數,其實這個參數就是編譯器給參數打上的一個默認值的標記,繼續看下源代碼。

這里我們發現有一個構造函數,需要傳遞一個默認值,而這個默認值取自我們定義的常量值,也就是4.

所以綜合來說,確實是一塊語法糖,其實真實的代碼應該是這樣,只是賦值操作給了編譯器。

1         static void Run(int i)
2         {
3             i = 4;
4 
5             //....
6         }

 

Q:我知道Param有些場景會比int[]更有語意,比如下面代碼,能說明下它的實現原理嗎?

 1     public class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Add(new int[3] { 1, 2, 3 });
 6 
 7             //是不是有更好的語意
 8             AddRange(1, 2, 3);
 9         }
10 
11         /// <summary>
12         /// 這里必須傳遞int[]數組
13         /// </summary>
14         /// <param name="nums"></param>
15         static void Add(int[] nums)
16         {
17 
18         }
19 
20         /// <summary>
21         /// 這里直接傳遞數據元素值即可,不需要int[]
22         /// </summary>
23         /// <param name="nums"></param>
24         static void AddRange(params int[] nums)
25         {
26 
27         }
28     }

 

A:  確實在add的場景下語意大增了不少,同時也讓我少寫了一些代碼,那么到底param是如果做到的呢?我們繼續

      看下IL代碼。

         

從IL中上可以看到,其實所謂的調用方,即:AddRange(1, 2, 3); 它在調用之前已經new了一個arr,并且將1,2,3

加入到arr中去了,然后再調用AddRange數組的,所以可以看出,又是一枚語法糖。

好了,大概就這樣了,夜深了,睡覺了。

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()