VB.NETでもジェネリックなメソッドを実装したい
はじめに
特に需要なんてものはないんですが、VBで型パラメータで指定したインスタンスを生成したりするメソッドを定義したくなったのでちょっと調べてみました。
Module Module1 Sub Main() Dim a As Generic1(Of HogeA) = New Generic1(Of HogeA)() Dim b As Generic1(Of HogeB) = New Generic1(Of HogeB)() Dim c As HogeA = a.Generate() Dim d As HogeB = b.Generate() c.HelloA() d.HelloB() Console.WriteLine() c = Generic2.Generate(Of HogeA)() d = Generic2.Generate(Of HogeB)() c.HelloA() d.HelloB() Console.ReadLine() End Sub End Module Class Generic1(Of T As {New, IHoge}) Public Function Generate() As T Console.WriteLine("Generate():{0}", GetType(T)) Dim i = New T() i.Hello() Return i End Function End Class Class Generic2 Public Shared Function Generate(Of T As {New, IHoge})() As T Console.WriteLine("Generate():{0}", GetType(T)) Dim i = New T() i.Hello() Return i End Function End Class Interface IHoge Sub Hello() End Interface Class HogeA Implements IHoge Public Sub HelloA() Implements IHoge.Hello Console.WriteLine("HogeA") End Sub End Class Class HogeB Implements IHoge Public Sub HelloB() Implements IHoge.Hello Console.WriteLine("HogeB") End Sub End Class
メソッドHello
を宣言したインターフェースIHoge
を定義し、型パラメータの制約として引数を取らないコンストラクタを持ちなおかつIHoge
を実装したクラスのみを受け付けるクラスとメソッドを宣言しています。
それぞれのジェネリッククラス及びジェネリックメソッドは型パラメータのインスタンスを生成しインターフェースが宣言しているメソッドを実行してからインスタンスを呼び出し元へ返却しています。
なおNew
制約を付けないとジェネリッククラス内でインスタンスの生成が出来ません。
当たり前ですね。型パラメータに渡されるクラスなんてジェネリッククラスの宣言時には分かりませんし、制約が無ければ引数を取らないコンストラクタを含まないクラスだって渡せます。そうなると実行時にコンストラクタの呼び出しに失敗します。
ちなみにジェネリックで指定した型であることを明示するために変数の型を明記してますが、
Dim c = a.Generate()
や
Dim c = Generic2.Generate(Of HogeA)()
でもちゃんと型推論してくれるので大丈夫です。
余談ですが、インターフェースを実装したクラスのメソッドを呼び出すとき、参照の型がインターフェースの場合はインターフェースで宣言したメソッド名を使用しますが、参照の型がクラスの場合はクラスで宣言したメソッド名で呼び出します。
さらに余談ですが、C#ではnew()制約は型パラメータ制約の最後にしないといけないという制約がありますが、VBではそういうのはないっぽいです。
型パラメーターの制約 (C# プログラミング ガイド) | Microsoft Docs
型リスト (Visual Basic) | Microsoft Docs
おしまい