1publicstaticlong BigMul(int a, int b) 2{ 3return (a * b); 4}
咦,上面的代码好像有点不对。第 3 行应该是
return (long)a * b;
才对呀。于是,再看 IL 代码:
1.method public hidebysig static int64 BigMul(int32 a, int32 b) cil managed 2{ 3 .maxstack 8 4 L_0000: ldarg.0 5 L_0001: conv.i8 6 L_0002: ldarg.1 7 L_0003: conv.i8 8 L_0004: mul 9 L_0005: ret 10}
这下对了,第 5 行和第 7 行的 conv.i8 指令将两个 int 参数转换为 long 类型,然后再调用 mul 指令(第 8 行)进行乘法运算。
不过,这样一来,Math.BigMul 方法不就完全没有存在的必要吗?调用她还不如我们自己写 (long)a * b 语句来代替她,还省了一次方法调用的开销。我原来以为 IL 语言中有什么指令可以直接将两个 int 类型的操作数相乘得到 long 类型的结果呢,而 Math.BigMul 方法就直接调用该指令。
于是,我就写了以下的程序来比较 Math.BigMul 方法和 (long)a * b 的效率:
1using System; 2using System.Diagnostics; 3 4namespace Skyiv.Ben 5{ 6sealedclass TestBigMul 7 { 8staticvoid Main() 9 { 10for (int i =0; i <5; i++) Console.WriteLine(BigMultiply(i) == LongMultiply(i)); 11 } 12 13staticlong BigMultiply(int n) 14 { 15long k =0; 16 var watch = Stopwatch.StartNew(); 17for (int i =int.MaxValue; i >0; i--) k += Math.BigMul(i, n - i); 18 watch.Stop(); 19 Console.WriteLine("Math.BigMul(): "+ watch.Elapsed); 20return k; 21 } 22 23staticlong LongMultiply(int n) 24 { 25long k =0; 26 var watch = Stopwatch.StartNew(); 27for (int i =int.MaxValue; i >0; i--) k += (long)i * (n - i); 28 watch.Stop(); 29 Console.WriteLine("long multiply: "+ watch.Elapsed); 30return k; 31 } 32 } 33}