c#中双解引用引用类型对性能的影响

本文关键字:性能 影响 引用类型 引用 | 更新日期: 2023-09-27 18:17:15

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

例如,以下代码:

public void EmptyList(ref List<string> test)
{
    test.Clear();
}
VS:

public void EmptyList(List<string> test)
{
    test.Clear();
}

编辑

看完Nicholas Carey的话后,我用上面的代码尝试了同样的事情。这是生成的程序集:

            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 

c#中双解引用引用类型对性能的影响

显式引用调用和隐式引用调用的区别是lea (Load Effective Address)指令和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 

为被调用的方法/函数生成的代码在两种情况下都是相同的。

下面是我使用的示例代码,fww:

class Program
{
  static void Main( string[] args )
  {
    object o = null ;
    FooBar( ref o ) ;
  }
  private static void FooBar( ref object o )
  {
  }
}

IMHO,省略ref关键字,除非它确实需要:它真正做的是为方程添加语义噪声。

性能差异如果存在的话,可能完全不会被注意到。我个人会根据功能需求而不是性能差异来决定是通过引用还是通过值来传递"引用参数"。

使用ref传递引用类型对调用者有很强的暗示。假设你的参考可能会改变。这对API的使用有明显的影响,并且强烈暗示您可能正在更改值。如果不是这种情况,则按值传递引用以避免混淆,因为它将导致更易于维护,更易于理解的代码。