【发布时间】:2010-02-25 04:23:43
【问题描述】:
既然 C# 支持命名参数,我正在检查它是否以与 VB 相同的方式实现,发现有细微差别。以这样的库函数为例:
public static void Foo(string a, string b)
{
Console.WriteLine(string.Format("a: {0}, b: {1}", a, b));
}
在 C# 中,如果你这样称呼它:
Foo(a: "a", b: "b");
编译器产生以下 IL 指令:
.locals init (
[0] string CS$0$0000,
[1] string CS$0$0001)
L_0000: nop
L_0001: ldstr "a"
L_0006: stloc.0
L_0007: ldstr "b"
L_000c: stloc.1
L_000d: ldloc.0
L_000e: ldloc.1
L_000f: call void [TestLibrary]TestLibrary.Test::Foo(string, string)
L_0014: nop
L_0015: ret
转换为以下 C# 代码:
string CS$0$0000 = "a";
string CS$0$0001 = "b";
Test.Foo(CS$0$0000, CS$0$0001);
在VB中,如果你这样称呼它:
Foo(a:="a", b:="b")
编译器产生以下 IL 指令:
L_0000: nop
L_0001: ldstr "a"
L_0006: ldstr "b"
L_000b: call void [TestLibrary]TestLibrary.Test::Foo(string, string)
L_0010: nop
L_0011: nop
L_0012: ret
转换为以下 VB 代码:
Foo("a", "b");
VB 实现它的方式需要更少的指令调用,那么 C# 实现它的方式有什么优势吗?如果不使用命名参数,C# 会产生与 VB 相同的结果。
编辑:既然我们已经确定额外指令在发布模式下会消失,那么它们在调试模式下出现的特殊原因是什么? VB在两种模式下的行为相同,C#在没有命名参数的情况下正常调用方法时不会插入额外的指令(包括使用可选参数时)。
【问题讨论】:
-
在参数上切换顺序,Foo(b:="b", a:="a") 看区别(提示:副作用顺序)
-
什么是等效的VB代码?
-
@adrianm 一个有趣的想法,但我刚刚尝试过(出于好奇),它生成的 IL 与
Foo(a: "a", b: "b"); -
@Marc 这可能是因为字符串没有副作用。如果您将它们更改为具有副作用的函数调用(即 Foo(b: Method1(), a: Method2())),则发布版本无法删除临时对象。
-
C# 规范说参数是从左到右计算的。 VB 没有这样的限制。