VB.NET可选参数如何在"后台"工作?他们符合CLS吗?

时间:2020-03-06 14:27:06  来源:igfitidea点击:

假设我们有以下方法声明:

Public Function MyMethod(ByVal param1 As Integer, _
    Optional ByVal param2 As Integer = 0, _
    Optional ByVal param3 As Integer = 1) As Integer

    Return param1 + param2 + param3
End Function

VB.NET如何使可选参数在CLR的范围内起作用?可选参数是否符合CLS?

解决方案

与普遍看法相反,可选参数确实符合CLS。 (不过,我对这个主要检查是为了纪念大会,类和方法都与CLSCompliant属性设置为True。)

那么这在MSIL中是什么样的呢?

.method public static int32  MyMethod(int32 param1,
                                      [opt] int32 param2,
                                      [opt] int32 param3) cil managed
{
  .custom instance void [mscorlib]System.CLSCompliantAttribute::.ctor(bool) = ( 01 00 01 00 00 ) 
  .param [2] = int32(0x00000000)
  .param [3] = int32(0x00000001)
  // Code size       11 (0xb)
  .maxstack  2
  .locals init ([0] int32 MyMethod)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  add.ovf
  IL_0004:  ldarg.2
  IL_0005:  add.ovf
  IL_0006:  stloc.0
  IL_0007:  br.s       IL_0009
  IL_0009:  ldloc.0
  IL_000a:  ret
} // end of method Module1::MyMethod

请注意,参数-MSIL上的[opt]标记本身就支持此功能,没有任何改动。 (与MSIL对VB的Static关键字的支持不同,后者是另一个主题。)

那么,为什么不是这些在C#中?除了推测可能是需求不足之外,我无法回答。我自己的偏好始终是指定参数,即使它们是可选的-对我来说,代码看起来更简洁并且更易于阅读。 (如果省略了参数,我通常会首先寻找与可见签名匹配的重载-只有在我找不到一个我意识到涉及可选参数的重载之后)。

有趣的是,这是通过反射器获得的反编译的Ccode。

public int MyMethod(int param1, 
                   [Optional, DefaultParameterValue(0)] int param2, 
                   [Optional, DefaultParameterValue(1)] int param3)
{
    return ((param1 + param2) + param3);
}

注意Optional和DefaultParameterValue属性。尝试将它们放入Cmethods中。我们会发现仍然需要将值传递给方法。但是在VB代码中,它变成了Default!话虽这么说,我个人从来没有甚至在VB代码中使用默认值。感觉就像是骇客。方法重载对我有用。

但是,在处理Excel Interop时,默认确实会有所帮助,这对于在C#中直接使用开箱即用来说是很痛苦的。