|
ある型の配列は、親(先祖)の型の配列として代入したり引数に渡すことができます。
StringはObjectを継承する型なので、こんな代入ができます。
Dim objs As Object() = New String() { "a", "b", "c" }
// ただしIntegerなど構造体の配列ではできない。
さて、Control.Invokeの宣言はこんな形です。
Public Function Invoke (method As Delegate, ParamArray args As Object()) As Object
ParamArrayは可変長引数を意味し、コンパイラによって自動的に配列に変換されて引数に渡されます。
例えば
Invoke(hogeDelegate, "a", "b")
はコンパイラによって
Invoke(hogeDelegate, New Object() { "a", "b" })
とコンパイルされ、実行されます。
ParamArrayの引数に直接Object()を渡すこともできます。
Dim objs As Object() = { "a", "b" }
Invoke(hogeDelegate, objs)
これは一つ前のInvoke(hogeDelegate, "a", "b")と全く同じ動作になります。
ではこのargsパラメータにString()を渡した場合どうなるでしょうか?
ここで、冒頭で述べた動作が出てきます。
つまり、
Dim strs As String() = { "a", "b" }
Invoke(hogeDelegate, strs)
は、strsがObject()として扱えるために、
Invoke(hogeDelegate, objs)
と同じに扱われます。
その結果、hogeDelegateに渡される引数は、String()が一つではなく、Stringが2つということになります。
Delegate Sub hogeDelegate(strs AS String()) ' ←想定していたデリゲート
Delegate Sub hogeDelegate(strA AS String, strB As String) ' ←実際に渡された引数
配列一つをParamArray Object()に渡す場合は
Invoke(hogeDelegate, New Object() { strs })
のように明示的にObject()を作るのが安全です。
こうすれば、引数は「String()が一つ」であることがはっきりします。
|