Vb.net 是否始终分配函数的默认返回变量?

Vb.net 是否始终分配函数的默认返回变量?,vb.net,compiler-optimization,Vb.net,Compiler Optimization,我感兴趣的是如何实现与函数名相同的默认变量 即使我不使用,Sum是否始终分配?(参见案例1) 如果我选择另一个变量(Total在案例3中),是否使用它而不是Sum 在编译时,以下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

我感兴趣的是如何实现与函数名相同的默认变量

  • 即使我不使用,
    Sum
    是否始终分配?(参见案例1)
  • 如果我选择另一个变量(
    Total
    案例3
    中),是否使用它而不是
    Sum
在编译时,以下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#中,这种代码是不允许的。您应该始终
返回一个值,否则代码将无法编译

我猜VB.NET通过类似于C#中这样的方式绕过了这一点:

它默认值为
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 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似乎更有效,因为它将运算符的结果直接放在堆栈上。其他人必须将结果从堆栈中拉入局部变量,然后将其推回到堆栈中

我冒昧地猜测,编译器使所有这三个相同的东西。案例3可能会“浪费”创建变量的时间。我知道。这就是为什么我将这个问题标记为vb.net,而不仅仅是.net或c#。当答案只与c#有关时,我发表了评论。这就是我最初否决它的原因。如果我们能留在VB,我会很高兴,因为在这些情况下,C#和VB编译器的方法可能完全不同。此外,C#不支持
情况2
。如果可以,请删除答案的C部分。他是以什么方式编译程序集的?在释放模式下?然后我很确定它们会被内联。@sloth:它不会删除它们,但最终可能还是一样的(案例3最值得怀疑)。@miroxlav但我今天了解到,一般来说,是否使用helper变量很重要。请不要从中得出错误的结论。使用helper变量只会影响可读性,而不会影响执行速度,因为它可能会从JIT编译器中删除。非常有趣的是,编译器没有对它们进行优化,尤其是案例2。我很高兴我总是使用案例1,节省那些纳秒P@Keith-此IL来自LinqPad。当VS在发布模式下编译或JITted时,它可能会按照您的建议进行优化。@Keith-它可能不仅与变量创建有关,还与内联有关。函数体是内联插入的还是有一个常规调用,将参数放在堆栈上等等……啊,好的。我认为LinqPad(从未使用过它)模仿VS的功能。谢谢
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