函数的默认 return 变量总是分配的吗?

Is default return variable of function always allocated?

我对如何实现与函数同名的默认变量很感兴趣。

下面3个等价的情况在编译时是否也等价?还是有些优于其他?

' EQUIVALENT CASES

' CASE 1
Function Sum(a As Integer, b As Integer) As Integer
    Return a + b
End Function

' CASE 2
Function Sum(a As Integer, b As Integer) As Integer
    Sum = a + b
End Function

' CASE 3
Function Sum(a As Integer, b As Integer) As Integer
    Dim Total As Integer
    Total = a + b
    Return Total
End Function

正如我在某处读到的那样,编译为小于 32 字节的函数被内联插入。我想知道在某些情况下,我是否可能仅仅因为选择的符号而超过或低于限制。

我不是 VB.NET 专家,但我对 C# 有所了解。在 C# 中,这种代码是不允许的。您应该始终 return 一个值,否则代码将无法编译。

我想 VB.NET 在 C# 中通过类似这样的东西来规避这个:

T Sum = default(T);

...

return Sum;

默认值为Sum,在int的情况下为0

根据这个逻辑,变量被分配,对于引用类型,这意味着不会分配,因为它们默认为 null

查看 IL:

.method public static int32  Test() cil managed
{
  // Code size       3 (0x3)
  .maxstack  1
  .locals init ([0] int32 Test)
  IL_0000:  nop
  IL_0001:  ldloc.0
  IL_0002:  ret
} // end of method Module1::Test

从这个Function:

Function Test() As Integer

End Function

你会看到init,它初始化一个变量(分配它)和ldloc,这是一个获取变量值的调用,因此,它必须被分配。

我将您的函数分别重命名为 Sum1、Sum2 和 Sum3,然后 运行 通过 LinqPad 将它们重命名。这是生成的 IL:

Sum1:
IL_0000:  ldarg.1     
IL_0001:  ldarg.2     
IL_0002:  add.ovf     
IL_0003:  ret         

Sum2:
IL_0000:  ldarg.1     
IL_0001:  ldarg.2     
IL_0002:  add.ovf     
IL_0003:  stloc.0     // Sum2
IL_0004:  ldloc.0     // Sum2
IL_0005:  ret         

Sum3:
IL_0000:  ldarg.1     
IL_0001:  ldarg.2     
IL_0002:  add.ovf     
IL_0003:  stloc.1     // Total
IL_0004:  ldloc.1     // Total
IL_0005:  ret         

似乎 Sum2 和 Sum3 产生相同的 IL。 Sum1 似乎更有效,因为它将运算符的结果直接放入堆栈。其他人必须将结果从堆栈中拉出到局部变量中,然后再将其压回堆栈!