2019独角兽企业重金招聘Python工程师标准>>>
高级语言之所以成为高级语言,编译器付出了很多。params在给我们带来方便的同时,编译器也是贡献不少。
实例代码:
using System;
public class Test
{ public static void Main(){ Console.WriteLine("结果1"); say("hello","world");Console.WriteLine("结果2"); say("aaaa","sssss","ddddd");Console.ReadKey();}public static void say(string str,string str2) { Console.WriteLine("single");Console.WriteLine(str);Console.WriteLine(str2); }public static void say(params string[] str){Console.WriteLine("params");foreach(string s in str) {Console.WriteLine(s);}}
}
说明下目的,
say("hello","world");
是为了验证在参数同时适配
public static void say(string str,string str2)
public static void say(params string[] str)
的时候,编译器是调用哪个函数。
say("aaaa","sssss","ddddd");
是为了察看params的运作过程
代码结果:
分析:
从结果1可看出在同时符合确定变量和可变变量的时候,编译器调用的是确定变量的函数,至于原因等说完params在提。
反编译这段代码。
注意参数,这里并没有出现params字样,说明到这个层级是不存在params了,接着看main函数。
.method public hidebysig static void Main() cil managed
{.entrypoint// Code size 79 (0x4f).maxstack 3.locals init (string[] V_0)IL_0000: ldstr bytearray (D3 7E 9C 67 31 00 ) // .~.g1.IL_0005: call void [mscorlib]System.Console::WriteLine(string)IL_000a: ldstr "hello"IL_000f: ldstr "world"IL_0014: call void Test::say(string,string) // 结果1的调用IL_0019: ldstr bytearray (D3 7E 9C 67 32 00 ) // .~.g2.IL_001e: call void [mscorlib]System.Console::WriteLine(string)IL_0023: ldc.i4.3IL_0024: newarr [mscorlib]System.StringIL_0029: stloc.0IL_002a: ldloc.0IL_002b: ldc.i4.0IL_002c: ldstr "aaaa"IL_0031: stelem.refIL_0032: ldloc.0IL_0033: ldc.i4.1IL_0034: ldstr "sssss"IL_0039: stelem.refIL_003a: ldloc.0IL_003b: ldc.i4.2IL_003c: ldstr "ddddd"IL_0041: stelem.refIL_0042: ldloc.0IL_0043: call void Test::say(string[]) //结果2的调用IL_0048: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()IL_004d: popIL_004e: ret
} // end of method Test::Main
从结果1可以清楚地看到调用的是确定参数函数,往下的IL_0024构建了一个数组,然后在一个个的把参数推送进数组,最后调用了say(string[] )函数.
结论:
params的实现只是将单个的参数打包成数组,,调用数组参数函数,事实上你并不能同时声明,say(string[])和say(params string[]),会提示已存在.在这里也能解释为什么在既可变参,也可定参的情况下使用定参的原因了.使用变参需要额外的代码打包参数.