这篇继续聊聊 ”参数“的一些话题,我们知道参数大概有”默认参数“,”可选参数“,”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:
局部代码区域直接写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:
会嵌入到程序集的元数据中,老规矩,继续看下生成的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 ///
12 /// 这里必须传递int[]数组
13 ///
14 ///
15 static void Add(int[] nums)
16 {
17
18 }
19
20 ///
21 /// 这里直接传递数据元素值即可,不需要int[]
22 ///
23 ///
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数组的,所以可以看出,又是一枚语法糖。
好了,大概就这样了,夜深了,睡觉了。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net