If I have
private string Foo(string decrypted)
{
return decrypted.Substring(blah);
}
and
private string Foo(string decrypted)
{
string s = decrypted.Substring(blah);
return s;
}
Is this the same? Is the compiler able to remove s
?
How about
private string Foo(string decrypted)
{
string s = decrypted.Substring(blah);
string t = s;
return t;
}
?
Thanks.
I was curious, so I tried it out (using LINQPad 4 with optimizations). This is what I got:
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
It appears the compiler doesn't optimize away s
or t
, however, I suspect the JIT interpreter would.
It looks to me like the question is basically "does the C# compiler support named return value optimization (NRVO)?"
That's a reasonable question, I suppose, but like delnan points out, it's not particularly relevant because of the fact that strings in C# are reference types. If you're a C++ programmer, you can think of reference types as essentially equivalent to pointers. So although you are returning the string by value, you're really only returning the reference by value, not the object itself. It's just as if you were returning the pointer address by value. A copy of the entire string object need not be made, so the optimization gains you very little. The only reason you need NRVO is to avoid suffering the performance hit of a large and expensive copy, but copying a pointer/reference is not expensive.
However, if you had given a different example that used a value type rather than a reference type (e.g., a large structure), then there might be a significant performance improvement to be gained by implementing NRVO. Unfortunately, even in this case, I do not believe that the C# compiler does this. I suppose the JITer might; I can't say for sure. (And if it isn't done now, it could always be added in future versions. Although such large structures are found only rarely in C# code, so it's unlikely this is at the top of the performance team's list of goals.)
For more details, Jon Skeet's article on References and Values in C# is recommended reading.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With