Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中双解引用引用类型的性能影响_C#_Pass By Reference_Pass By Value - Fatal编程技术网

C# C语言中双解引用引用类型的性能影响

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

最近,我开始从事一个项目,其中许多引用参数是通过引用传递的。我已经研究了很多代码,这些方法中的大多数可能会丢失ref参数。虽然代码功能很好,但我想知道,如果对每个参数进行双重解引用,而不是仅仅通过值传递引用,会对性能造成什么样的影响

例如,此代码:

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参数的方法内部完成一些工作之后,汇编代码似乎显示了第二个取消引用调用。如果方法中没有使用参数,我假设编译器会优化第二次取消引用。