如果我有
private string Foo(string decrypted)
{
return decrypted.Substring(blah);
}
和
private string Foo(string decrypted)
{
string s = decrypted.Substring(blah);
return s;
}
这是一样的吗?编译器是否能够删除s
?
怎么样
private string Foo(string decrypted)
{
string s = decrypted.Substring(blah);
string t = s;
return t;
}
感谢。
答案 0 :(得分:4)
我很好奇,所以我试了一下(使用LINQPad 4进行优化)。这就是我得到的:
private string Foo(string decrypted)
{
return decrypted.Substring(0);
}
Foo:
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: callvirt System.String.Substring
IL_0007: ret
private string Foo(string decrypted)
{
string s = decrypted.Substring(0);
return s;
}
Foo:
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: callvirt System.String.Substring
IL_0007: stloc.0 // s
IL_0008: ldloc.0 // s
IL_0009: ret
private string Foo(string decrypted)
{
string s = decrypted.Substring(0);
string t = s;
return t;
}
Foo:
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: callvirt System.String.Substring
IL_0007: stloc.0 // s
IL_0008: ldloc.0 // s
IL_0009: stloc.1 // t
IL_000A: ldloc.1 // t
IL_000B: ret
看起来编译器没有优化s
或t
,但是,我怀疑JIT解释器会。{/ p>
答案 1 :(得分:1)
在我看来问题基本上是“C#编译器是否支持named return value optimization(NRVO)?”
我认为这是一个合理的问题,但与delnan points out一样,它并不是特别相关,因为C#中的字符串是引用类型。如果您是C ++程序员,您可以将引用类型视为与指针基本相同。因此,尽管您按值返回字符串,但实际上只是按值返回引用,而不是对象本身。就像你按值返回指针地址一样。不需要制作整个字符串对象的副本,因此优化会使您获得很少的收益。您需要NRVO的唯一原因是避免遭受大型昂贵副本的性能损失,但复制指针/引用并不昂贵。
但是,如果您给出了使用值类型而不是引用类型(例如,大型结构)的不同示例,那么通过实现NRVO可能会获得显着的性能提升。不幸的是,即使在这种情况下,我也不相信C#编译器会这样做。我想JITer可能会;我不能肯定地说。 (如果现在还没有完成,可以在将来的版本中添加它。虽然在C#代码中很少发现这种大型结构,但是这不太可能是性能团队目标列表的顶部。)
有关详细信息,建议您阅读Jon Skeet关于C#中References and Values的文章。