gpt4 book ai didi

c# - 为什么在函数中使用名称参数实际上会生成更多代码?

转载 作者:太空狗 更新时间:2023-10-29 18:32:15 25 4
gpt4 key购买 nike

阅读 Jon Skeet 的书,我发现(现在)在函数调用中使用了“命名参数”。这是一个快速简单的示例:

void Dump(int x, int y, int z, string cSomeText)
{
// no use, just to see how we call this later
string cOnMe = string.Format("[{0}] [{1}] [{2}] [{3}]", x, y, z, cSomeText);
}

void CallDumpWithoutNameArguments()
{
// call with out Name Arguments
Dump(1, 2, 3, "Test string");
}

void CallDumpWithNameArguments()
{
// more easy to read, call the same function with Name Arguments
Dump(x: 1, y: 2, z: 3, cSomeText: "Test string");
}

使用它之后再看编译后的代码,我发现使用这个名称实际上是在调用函数之前创建变量。

这是创建的代码:

private void CallDumpWithoutNameArguments()
{
this.Dump(1, 2, 3, "Test string");
}

private void CallDumpWithNameArguments()
{
int CS$0$0000 = 1;
int CS$0$0001 = 2;
int CS$0$0002 = 3;
string CS$0$0003 = "Test string";
this.Dump(CS$0$0000, CS$0$0001, CS$0$0002, CS$0$0003);
}

和完整的编译代码,你看我用“命名参数”调用它有多大

  .method private hidebysig instance void CallDumpWithoutNameArguments()
{
.maxstack 8
nop
ldarg.0
ldc.i4.1
ldc.i4.2
ldc.i4.3
ldstr "Test string"
call instance void SubSonic.BabisExtrasNoUseIt.ExtraTestCode::Dump(int32 x, int32 y, int32 z, string cSomeText)
nop
ret
}

.method private hidebysig instance void CallDumpWithNameArguments()
{
.maxstack 5
.locals init (int32 V0,
int32 V1,
int32 V2,
string V3)
nop
ldarg.0
ldc.i4.1
stloc.0
ldc.i4.2
stloc.1
ldc.i4.3
stloc.2
ldstr "Test string"
stloc.3
ldloc.0
ldloc.1
ldloc.2
ldloc.3
call instance void SubSonic.BabisExtrasNoUseIt.ExtraTestCode::Dump(int32 x, int32 y, int32 z, string cSomeText)
nop
ret
}

所以这是c#忘记优化的一点,或者它们还有其他用途吗?

跟进

我想清楚上面的代码是编译产生的。这是我从 Servy 得到的答案。

private void CallDumpWithoutNameArguments()
{
// what generated from
// int i = 0;
// Dump(i++, i++, i++, cSomeText: "Test string");

int i = 0;
string CS$0$0000 = "Test string";
this.Dump(i++, i++, i++, CS$0$0000);
}

private void CallDumpWithNameArguments()
{
// what is generate from
// int i = 0;
// Dump(x: i++, z: i++, y: i++, cSomeText: "Test string");

int i = 0;
int CS$0$0000 = i++;
int CS$0$0001 = i++;
int CS$0$0002 = i++;
string CS$0$0003 = "Test string";
this.Dump(CS$0$0000, CS$0$0002, CS$0$0001, CS$0$0003);
}

最佳答案

这与确保代码以正确的顺序运行有关。对于命名参数,每个参数的表达式需要按照它们在源代码中出现的顺序执行,而不是它们在定义的实际参数列表中出现的顺序。想象一下(非常卑鄙的)电话:

int i = 0;
Dump(x: i++, z: i++, y: i++, cSomeText: "Test string");

它应该和下面一样吗:

Dump(0, 1, 2, "Test string");

Dump(0, 2, 1, "Test string");

如果您没有为每个命名参数设置局部变量,您最终会得到第一个,如果有,您最终会得到第二个。

看起来与其尝试确定是否有必要创建局部变量(参数是否乱序,它们是否引起副作用,这些副作用是否对其他参数中的表达式可见)更简单始终创建局部变量。已经多次声明 C# 编译器将确保优化的正确性;它为 JIT 留下了优化。

关于c# - 为什么在函数中使用名称参数实际上会生成更多代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12376473/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com