VB.NET のオプション パラメータは内部でどのように機能しますか?CLS に準拠していますか?
質問
次のメソッド宣言があるとします。
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 に準拠していますか?
解決
興味深いことに、これはリフレクター経由で取得された、逆コンパイルされた C# コードです。
public int MyMethod(int param1,
[Optional, DefaultParameterValue(0)] int param2,
[Optional, DefaultParameterValue(1)] int param3)
{
return ((param1 + param2) + param3);
}
Optional 属性と DefaultParameterValue 属性に注目してください。それらを C# メソッドに入れてみてください。それでもメソッドに値を渡す必要があることがわかります。ただし、VB コードでは、デフォルトに変わります。とはいえ、私は個人的には VB コードでも Default を使用したことがありません。ハックのような感じです。メソッドのオーバーロードは私にとってはうまくいきます。
ただし、C# でそのまま使用するのは面倒な Excel 相互運用機能を扱う場合は、デフォルトが役に立ちます。
他のヒント
一般に信じられていることに反して、オプションのパラメータは 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
パラメーターの [opt] マークに注意してください -- MSIL はこれをハックなしでネイティブにサポートしています。(MSIL による VB の Static キーワードのサポートとは異なり、これはまったく別のトピックです。)
では、なぜこれらが C# にないのでしょうか?需要がないと思われるのではないかという私の推測以外には、これには答えることができません。私自身は、たとえそれがオプションであっても、常にパラメーターを指定することを好みました。私にとっては、コードがすっきりして読みやすくなります。(パラメータが省略されている場合、私は多くの場合、最初に表示されているシグネチャに一致するオーバーロードを探します。見つからなかった後で初めて、オプションのパラメータが関係していることに気づきます。)