函数的默认 return 变量总是分配的吗?
Is default return variable of function always allocated?
我对如何实现与函数同名的默认变量很感兴趣。
Sum
是否总是分配,即使我不使用它? (参见 case 1
)
- 如果我选择另一个变量(
CASE 3
中的Total
),是否使用它来代替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# 中,这种代码是不允许的。您应该始终 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 似乎更有效,因为它将运算符的结果直接放入堆栈。其他人必须将结果从堆栈中拉出到局部变量中,然后再将其压回堆栈!
我对如何实现与函数同名的默认变量很感兴趣。
Sum
是否总是分配,即使我不使用它? (参见case 1
)- 如果我选择另一个变量(
CASE 3
中的Total
),是否使用它来代替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# 中,这种代码是不允许的。您应该始终 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 似乎更有效,因为它将运算符的结果直接放入堆栈。其他人必须将结果从堆栈中拉出到局部变量中,然后再将其压回堆栈!