既定の引数値へのアクセス
更新 : 2007 年 11 月
一部の言語 (Visual C++ および Microsoft Visual Basic 2005 など) では、引数への既定値の代入がサポートされています。たとえば、引数のうちの 2 つが既定値となる、有効な Visual Basic 2005 宣言を次に示します。
Public Sub MyMethod (a as Integer, _
Optional b as Double = 1.2, _
Optional c as Integer = 1)
パラメータ属性を使用して、既定のパラメータ値を代入できます。
Visual Basic および C++ では、メソッドの呼び出し時に省略可能なパラメータを省略できます。C# では、オプションの引数に値を指定する必要があります。
たとえば、次の Visual Basic と C++ のコード例は、すべて、MyMethod に対する有効な呼び出しです。
MyMethod(10, 55.3, 12)
MyMethod(10, 1.3) ' c == 1
MyMethod(11) ' b == 1.2, c == 1
MyMethod(10, 55.3, 12);
MyMethod(10, 1.3); // c == 1
MyMethod(11); // b == 1.2, c == 1
リフレクションを使用して引数の既定値を取得するには、そのパラメータの ParameterInfo オブジェクトを取得してから、ParameterInfo.DefaultValue プロパティを使用して既定値を取得します。既定値が存在しない場合は、このプロパティは、Value.DBNull を返します。
MyMethod の既定値をコンソールに出力する例を次に示します。
Dim m As MethodInfo = t.GetMethod("MyMethod")
Dim ps As ParameterInfo() = m.GetParameters()
Dim i As Integer
For i = 0 To ps.Length - 1
Console.WriteLine("Default Value == {0}", ps(i).DefaultValue)
Next i
MethodInfo m = t.GetMethod("MyMethod");
ParameterInfo[] ps = m.GetParameters();
for (int i = 0; i < ps.Length; i++)
{
Console.WriteLine("Default Value == {0}", ps[i].DefaultValue);
}
MethodInfo m = t->GetMethod("MyMethod");
ParameterInfo[] ps = m->GetParameters();
for (int i = 0; i < ps.Length; i++)
{
Console::WriteLine(S"Default Value == {0}", ps[i]->DefaultValue);
}
既定値の引数を持つメソッドを呼び出すには、Type.Missing を InvokeMember メソッドへのパラメータ値として使用します。これにより、遅延バインディング サービスは、指定されているパラメータ値にその既定値を使用できます。既定値を持たないパラメータとして Type.Missing を渡すと、ArgumentException がスローされます。Type.Missing に関しては、すべてのコンパイラのバインディング機構がこれらの規則に従っているわけではないことに注意する必要があります。この機能をサポートしないバインダや、Type.Missing を別の方法で扱うバインダもあります。Type.Missing を使用するときは、後続の既定値を記述する必要はありません。
C# 言語では、既定の引数はサポートされていません。
次の Visual Basic 2005 のコード例では、リフレクションを使用して既定の引数を持つメソッドを呼び出す方法を示します。
Option Strict Off
Imports System
Imports System.Reflection
Public Class OptionalArg
Public Sub MyMethod (a As Integer, Optional b As Double = 1.2, Optional c As Integer=1)
Console.WriteLine("a = " & a & " b = " & b & " c = " & c)
End Sub
End Class
Module Module1
Sub Main()
Dim o As New OptionalArg
Dim t As Type
t = GetType(OptionalArg)
Dim Param As Object()= {10, 20, 30}
t.InvokeMember("MyMethod", _
BindingFlags.Public Or _
BindingFlags.Instance Or _
BindingFlags.InvokeMethod Or _
BindingFlags.OptionalParamBinding, _
Nothing, _
o, _
New Object() {10, 55.3, 12})
t.InvokeMember("MyMethod", _
BindingFlags.Public Or _
BindingFlags.Instance Or _
BindingFlags.InvokeMethod Or _
BindingFlags.OptionalParamBinding, _
Nothing, _
o, _
New Object() {10, 1.3, Type.Missing})
t.InvokeMember("MyMethod", _
BindingFlags.Public Or _
BindingFlags.Instance Or _
BindingFlags.InvokeMethod Or _
BindingFlags.OptionalParamBinding, _
Nothing, _
o, _
New Object() {10, Type.Missing, Type.Missing})
End Sub
End Module
上記の方法を使用しているときは、呼び出し元が値を指定しなくても、後続の既定の引数が考慮されます。これは、既定の引数でメソッドを呼び出すための最も一般的な方法です。
MethodBase.Invoke を使用してメソッドを呼び出す場合は、値を持っていないすべてのパラメータに対して、Type.Missing を含むオブジェクト配列を渡して、どの引数が既定値であるかを明示的に指定する必要があります。