C# C语言中双解引用引用类型的性能影响
最近,我开始从事一个项目,其中许多引用参数是通过引用传递的。我已经研究了很多代码,这些方法中的大多数可能会丢失ref参数。虽然代码功能很好,但我想知道,如果对每个参数进行双重解引用,而不是仅仅通过值传递引用,会对性能造成什么样的影响 例如,此代码:C# C语言中双解引用引用类型的性能影响,c#,pass-by-reference,pass-by-value,C#,Pass By Reference,Pass By Value,最近,我开始从事一个项目,其中许多引用参数是通过引用传递的。我已经研究了很多代码,这些方法中的大多数可能会丢失ref参数。虽然代码功能很好,但我想知道,如果对每个参数进行双重解引用,而不是仅仅通过值传递引用,会对性能造成什么样的影响 例如,此代码: public void EmptyList(ref List<string> test) { test.Clear(); } 与此相比: public void EmptyList(List<string> test
public void EmptyList(ref List<string> test)
{
test.Clear();
}
与此相比:
public void EmptyList(List<string> test)
{
test.Clear();
}
编辑
读了尼古拉斯·凯里的话后,我用上面的代码做了同样的尝试。这就是最终的组装:
EmptyList(ref List<string> test)
00000028 mov eax,dword ptr [ebp-40h]
0000002b mov ecx,dword ptr [eax]
0000002d cmp dword ptr [ecx],ecx
0000002f call 719210C4
EmptyList(List<string> test)
00000028 mov ecx,dword ptr [ebp-40h]
0000002b cmp dword ptr [ecx],ecx
0000002d call 71920FD4
如果性能差异存在的话,它很可能完全没有被注意到。我个人决定是通过引用还是通过功能需求传递参考参数,而不是通过性能差异
使用ref传递引用类型对调用方有很大的影响。假设您的参考资料可能会发生变化。这对API的使用有明显的影响,并且强烈建议您可能正在更改值。如果不是这样,请按值传递引用以避免混淆,因为这将导致更易于维护和理解的代码。通过显式引用调用和通过隐式引用调用的区别是lea Load有效地址指令和mov“Move”指令之间的区别 好吧,在任何现代处理器上,这两条指令,以所使用的形式,都是在一个时钟周期内执行的,所以差别几乎没有意义 以下是通过[explicit]引用为调用生成的代码调试模式:
FooBar( ref o ) ;
00000035 lea ecx,[ebp-40h]
00000038 call FFD0B008
0000003d nop
FooBar( o ) ;
0000003a mov ecx,dword ptr [ebp-40h]
0000003d call FFD3B008
00000042 nop
下面是通过[隐式]引用为调用生成的代码调试模式:
FooBar( ref o ) ;
00000035 lea ecx,[ebp-40h]
00000038 call FFD0B008
0000003d nop
FooBar( o ) ;
0000003a mov ecx,dword ptr [ebp-40h]
0000003d call FFD3B008
00000042 nop
在这两种情况下,为被调用的方法/函数生成的代码都是相同的
以下是我使用的示例代码,FWIW:
class Program
{
static void Main( string[] args )
{
object o = null ;
FooBar( ref o ) ;
}
private static void FooBar( ref object o )
{
}
}
IMHO,除非确实需要,否则省略ref关键字:它真正做的只是在等式中添加语义噪音。可能没有你会注意到的。谢谢,我想知道我是否可以提出参数来删除它们,而不是混淆和不必要的,这对我来说就足够了。@scottm,性能可能几乎相同。在这两种情况下,您实际上都在传递一个内存位置,这两种方式的复制量都是相同的。。。我怀疑您永远不会看到分析器中的差异,因为从性能的角度来看,分析器非常微小,无法检测。令人困惑、不必要,并且可能使代码更加脆弱。您是如何获得这些程序集列表的?对于这种类型的分析,我希望看到的是CIL而不是原生x86。谢谢设置断点。启动调试器。当您到达断点时,打开反汇编窗口:通过Debug..Windows..discombly的菜单或键盘,[CTL]+[ALT]+D将到达该位置。+1。所有答案都是正确的,但这实际上回答了用硬数据提出的问题。@NicholasCarey有时答案太简单了!干得好。在重复测试并在ref参数的方法内部完成一些工作之后,汇编代码似乎显示了第二个取消引用调用。如果方法中没有使用参数,我假设编译器会优化第二次取消引用。