厳密でないデリゲート変換 (Visual Basic)
厳密でないデリゲート変換という機能を使用することで、シグネチャが同じでない場合も Sub や関数をデリゲートやハンドラーに割り当てることができます。したがって、メソッド呼び出しの中で既に認められているバインディングに合わせて、デリゲートへのバインディングを統一できるようになります。
パラメーターと戻り値の型
厳密でない変換の場合は、Option Strict が On に設定されていても、シグネチャの厳密な一致ではなく以下の条件が必要になります。
デリゲートの各パラメーターのデータ型から、対応する関数または Sub の対応するパラメーターのデータ型への変換が、拡大変換になっている必要があります。 以下の例では、Del1 デリゲートに Integer という 1 つのパラメーターがあります。 対応するラムダ式のパラメーター m のデータ型は、Integer からの拡大変換に相当するデータ型 (Long や Double など) でなければなりません。
' Definition of delegate Del1. Delegate Function Del1(ByVal arg As Integer) As Integer
' Valid lambda expression assignments with Option Strict on or off: ' Integer matches Integer. Dim d1 As Del1 = Function(m As Integer) 3 ' Integer widens to Long Dim d2 As Del1 = Function(m As Long) 3 ' Integer widens to Double Dim d3 As Del1 = Function(m As Double) 3
縮小変換は、Option Strict が Off に設定されている場合のみ許可されます。
' Valid only when Option Strict is off: Dim d4 As Del1 = Function(m As String) CInt(m) Dim d5 As Del1 = Function(m As Short) m
対応する関数または Sub の戻り値の型からデリゲートの戻り値の型への変換も、拡大変換になっている必要があります。 del1 の戻り値の型が Integer であるため、以下の例では、対応する各ラムダ式の本体が、Integer からの拡大変換に相当するデータ型に評価される必要があります。
' Valid return types with Option Strict on: ' Integer matches Integer. Dim d6 As Del1 = Function(m As Integer) m ' Short widens to Integer. Dim d7 As Del1 = Function(m As Long) CShort(m) ' Byte widens to Integer. Dim d8 As Del1 = Function(m As Double) CByte(m)
Option Strict が Off に設定されている場合は、拡大変換は両方向で削除されます。
' Valid only when Option Strict is set to Off.
' Integer does not widen to Short in the parameter.
Dim d9 As Del1 = Function(n As Short) n
' Long does not widen to Integer in the return type.
Dim d10 As Del1 = Function(n As Integer) CLng(n)
パラメーター指定の省略
厳密でないデリゲートの場合は、対応するメソッドの中でパラメーターの指定を完全に省略することも可能です。
' Definition of delegate Del2, which has two parameters.
Delegate Function Del2(ByVal arg1 As Integer, ByVal arg2 As String) As Integer
' The assigned lambda expression specifies no parameters, even though
' Del2 has two parameters. Because the assigned function in this
' example is a lambda expression, Option Strict can be on or off.
' Compare the declaration of d16, where a standard function is assigned.
Dim d11 As Del2 = Function() 3
' The parameters are still there, however, as defined in the delegate.
Console.WriteLine(d11(5, "five"))
' Not valid.
' Console.WriteLine(d11())
' Console.WriteLine(d11(5))
一部のパラメーターを指定して、その他のパラメーターを省略することはできません。
' Not valid.
'Dim d12 As Del2 = Function(p As Integer) p
パラメーターを省略する書き方は、複雑なパラメーターがいくつもかかわっているイベント ハンドラーを定義する場合などに便利です。 イベント ハンドラーは、場合によっては引数を使用しないことがあります。 つまり、イベントが登録されているコントロールの状態に直接アクセスして、引数を無視する、という場合です。 厳密でないデリゲートでは、あいまいさを残さない限り、そのような宣言で引数を省略してもかまいません。 たとえば、パラメーターを完全に指定した以下の OnClick メソッドは、RelaxedOnClick として書き換えることができます。
Sub OnClick(ByVal sender As Object, ByVal e As EventArgs) Handles b.Click
MessageBox.Show("Hello World from" + b.Text)
End Sub
Sub RelaxedOnClick() Handles b.Click
MessageBox.Show("Hello World from" + b.Text)
End Sub
AddressOf の例
前の例では、ラムダ式を使用して、型の関係を見やすくしていました。 ところが、AddressOf、Handles、AddHandler のいずれかを使用するデリゲートの割り当てでも、同じような厳密でない書き方が可能です。
以下の例では、関数 f1、f2、f3、f4 をすべて Del1 に割り当てることができます。
' Definition of delegate Del1.
Delegate Function Del1(ByVal arg As Integer) As Integer
' Definitions of f1, f2, f3, and f4.
Function f1(ByVal m As Integer) As Integer
End Function
Function f2(ByVal m As Long) As Integer
End Function
Function f3(ByVal m As Integer) As Short
End Function
Function f4() As Integer
End Function
' Assignments to function delegate Del1.
' Valid AddressOf assignments with Option Strict on or off:
' Integer parameters of delegate and function match.
Dim d13 As Del1 = AddressOf f1
' Integer delegate parameter widens to Long.
Dim d14 As Del1 = AddressOf f2
' Short return in f3 widens to Integer.
Dim d15 As Del1 = AddressOf f3
次の例は、Option Strict が Off に設定されている場合のみ有効です。
' If Option Strict is Off, parameter specifications for f4 can be omitted.
Dim d16 As Del1 = AddressOf f4
' Function d16 still requires a single argument, however, as specified
' by Del1.
Console.WriteLine(d16(5))
' Not valid.
'Console.WriteLine(d16())
'Console.WriteLine(d16(5, 3))
関数の戻り値の排除
厳密でないデリゲート変換では、関数を Sub デリゲートに割り当てることによって、関数の戻り値を事実上無視することも可能です。 一方、Sub を関数デリゲートに割り当てることはできません。 以下の例では、関数 doubler のアドレスを Sub デリゲート Del3 に割り当てています。
' Definition of Sub delegate Del3.
Delegate Sub Del3(ByVal arg1 As Integer)
' Definition of function doubler, which both displays and returns the
' value of its integer parameter.
Function doubler(ByVal p As Integer) As Integer
Dim times2 = 2 * p
Console.WriteLine("Value of p: " & p)
Console.WriteLine("Double p: " & times2)
Return times2
End Function
' You can assign the function to the Sub delegate:
Dim d17 As Del3 = AddressOf doubler
' You can then call d17 like a regular Sub procedure.
d17(5)
' You cannot call d17 as a function. It is a Sub, and has no
' return value.
' Not valid.
'Console.WriteLine(d17(5))
参照
処理手順
方法 : Visual Basic でプロシージャを別のプロシージャに渡す