Bagikan melalui


Variasi dalam Delegat (Visual Basic)

.NET Framework 3.5 memperkenalkan dukungan variasi untuk mencocokkan tanda tangan metode dengan tipe pendelegasian untuk semua delegasi di C# dan Visual Basic. Ini berarti Anda dapat menetapkan ke delegasi tidak hanya metode yang memiliki tanda tangan yang cocok, tetapi juga metode yang mengembalikan tipe yang lebih turunan (kovariansi) atau yang menerima parameter dengan tipe yang kurang turunan (kontravariansi) dibandingkan yang ditentukan oleh tipe delegasi. Ini termasuk delegasi generik dan non-generik.

Misalnya, pertimbangkan kode berikut, yang memiliki dua kelas dan dua delegasi: generik dan non-generik.

Public Class First
End Class

Public Class Second
    Inherits First
End Class

Public Delegate Function SampleDelegate(ByVal a As Second) As First
Public Delegate Function SampleGenericDelegate(Of A, R)(ByVal a As A) As R

Saat membuat delegasi jenis SampleDelegate atau SampleDelegate(Of A, R) , Anda dapat menetapkan salah satu metode berikut untuk delegasi tersebut.

' Matching signature.
Public Shared Function ASecondRFirst(
    ByVal second As Second) As First
    Return New First()
End Function

' The return type is more derived.
Public Shared Function ASecondRSecond(
    ByVal second As Second) As Second
    Return New Second()
End Function

' The argument type is less derived.
Public Shared Function AFirstRFirst(
    ByVal first As First) As First
    Return New First()
End Function

' The return type is more derived
' and the argument type is less derived.
Public Shared Function AFirstRSecond(
    ByVal first As First) As Second
    Return New Second()
End Function

Contoh kode berikut mengilustrasikan konversi implisit antara tanda tangan metode dan jenis delegasi.

' Assigning a method with a matching signature
' to a non-generic delegate. No conversion is necessary.
Dim dNonGeneric As SampleDelegate = AddressOf ASecondRFirst
' Assigning a method with a more derived return type
' and less derived argument type to a non-generic delegate.
' The implicit conversion is used.
Dim dNonGenericConversion As SampleDelegate = AddressOf AFirstRSecond

' Assigning a method with a matching signature to a generic delegate.
' No conversion is necessary.
Dim dGeneric As SampleGenericDelegate(Of Second, First) = AddressOf ASecondRFirst
' Assigning a method with a more derived return type
' and less derived argument type to a generic delegate.
' The implicit conversion is used.
Dim dGenericConversion As SampleGenericDelegate(Of Second, First) = AddressOf AFirstRSecond

Untuk lebih banyak contoh, lihat Menggunakan Varians pada Delegasi (Visual Basic) dan Menggunakan Varians untuk Delegasi Generik Func dan Action (Visual Basic).

Varians dalam Parameter Jenis Generik

Di .NET Framework 4 dan yang lebih baru, Anda dapat mengaktifkan konversi implisit antar delegasi, sehingga delegasi generik yang memiliki jenis berbeda yang ditentukan oleh parameter jenis generik dapat ditetapkan satu sama lain, jika jenis diwariskan satu sama lain sebagaimana diperlukan oleh varians.

Untuk mengaktifkan konversi implisit, Anda harus secara eksplisit mendeklarasikan parameter generik dalam delegasi sebagai kovarian atau kontravarian dengan menggunakan in kata kunci atau out .

Contoh kode berikut menunjukkan bagaimana Anda dapat membuat delegasi yang memiliki parameter jenis generik kovarian.

' Type T is declared covariant by using the out keyword.
Public Delegate Function SampleGenericDelegate(Of Out T)() As T
Sub Test()
    Dim dString As SampleGenericDelegate(Of String) = Function() " "
    ' You can assign delegates to each other,
    ' because the type T is declared covariant.
    Dim dObject As SampleGenericDelegate(Of Object) = dString
End Sub

Jika Anda hanya menggunakan dukungan varian untuk mencocokkan tanda tangan metode dengan jenis delegasi dan tidak menggunakan kata kunci in dan out, Anda mungkin menemukan bahwa terkadang Anda dapat membuat instans delegasi dengan ekspresi lambda atau metode yang identik, tetapi Anda tidak dapat menetapkan satu delegasi ke delegasi lainnya.

Dalam contoh kode berikut, SampleGenericDelegate(Of String) tidak dapat dikonversi secara eksplisit ke SampleGenericDelegate(Of Object), meskipun String mewarisi Object. Anda dapat memperbaiki masalah ini dengan menandai parameter T generik dengan out kata kunci.

Public Delegate Function SampleGenericDelegate(Of T)() As T
Sub Test()
    Dim dString As SampleGenericDelegate(Of String) = Function() " "

    ' You can assign the dObject delegate
    ' to the same lambda expression as dString delegate
    ' because of the variance support for
    ' matching method signatures with delegate types.
    Dim dObject As SampleGenericDelegate(Of Object) = Function() " "

    ' The following statement generates a compiler error
    ' because the generic type T is not marked as covariant.
    ' Dim dObject As SampleGenericDelegate(Of Object) = dString

End Sub

Delegasi Generik yang Memiliki Parameter Jenis Varian dalam .NET Framework

.NET Framework 4 memperkenalkan dukungan varians untuk parameter jenis generik di beberapa delegasi generik yang ada:

Untuk informasi dan contoh selengkapnya, lihat Menggunakan Varians untuk Delegasi Generik Func dan Action (Visual Basic).

Mendeklarasikan Parameter Tipe Variabel pada Delegasi Generik

Jika delegasi generik memiliki parameter jenis generik kovarian atau kontravarian, maka dapat disebut sebagai delegasi generik varian.

Anda dapat mendeklarasikan kovarian parameter jenis generik dalam delegasi generik dengan menggunakan out kata kunci. Jenis kovarian hanya dapat digunakan sebagai jenis pengembalian metode dan bukan sebagai jenis argumen metode. Contoh kode berikut menunjukkan cara mendeklarasikan delegasi generik kovarian.

Public Delegate Function DCovariant(Of Out R)() As R

Anda dapat mendeklarasikan parameter jenis generik kontravarian dalam delegasi generik dengan menggunakan in kata kunci. Jenis kontravarian hanya dapat digunakan sebagai jenis argumen metode dan bukan sebagai jenis pengembalian metode. Contoh kode berikut menunjukkan cara mendeklarasikan delegasi generik kontravarian.

Public Delegate Sub DContravariant(Of In A)(ByVal a As A)

Penting

ByRef parameter di Visual Basic tidak dapat ditandai sebagai varian.

Dimungkinkan juga untuk mendukung variansi dan kovarians dalam delegasi yang sama, tetapi untuk parameter jenis yang berbeda. Ini ditunjukkan dalam contoh berikut.

Public Delegate Function DVariant(Of In A, Out R)(ByVal a As A) As R

Menginstansiasi dan Memanggil Delegasi Generik Varian

Anda dapat menginstansiasi dan memanggil delegate varian sama seperti Anda menginstansiasi dan memanggil delegate yang invarian. Dalam contoh berikut, delegasi diinisialisasi menggunakan ekspresi lambda.

Dim dvariant As DVariant(Of String, String) = Function(str) str + " "
dvariant("test")

Menggabungkan Delegat Generik Variatif

Anda tidak boleh menggabungkan delegasi varian. Metode Combine ini tidak mendukung konversi delegasi varian dan mengharapkan delegasi berjenis yang sama persis. Ini dapat menyebabkan pengecualian run-time saat Anda menggabungkan delegasi baik dengan menggunakan Combine metode (di C# dan Visual Basic) atau dengan menggunakan + operator (di C#), seperti yang ditunjukkan dalam contoh kode berikut.

Dim actObj As Action(Of Object) = Sub(x) Console.WriteLine("object: {0}", x)
Dim actStr As Action(Of String) = Sub(x) Console.WriteLine("string: {0}", x)

' The following statement throws an exception at run time.
' Dim actCombine = [Delegate].Combine(actStr, actObj)

Variasi pada Parameter Tipe Generik untuk Tipe Nilai dan Tipe Referensi

Variasi pada parameter jenis generik hanya didukung untuk tipe referensi. Misalnya, DVariant(Of Int)tidak dapat dikonversi secara implisit ke DVariant(Of Object) atau DVariant(Of Long), karena bilangan bulat adalah jenis nilai.

Contoh berikut menunjukkan bahwa varians pada parameter tipe generik tidak didukung untuk tipe nilai.

' The type T is covariant.
Public Delegate Function DVariant(Of Out T)() As T
' The type T is invariant.
Public Delegate Function DInvariant(Of T)() As T
Sub Test()
    Dim i As Integer = 0
    Dim dInt As DInvariant(Of Integer) = Function() i
    Dim dVariantInt As DVariant(Of Integer) = Function() i

    ' All of the following statements generate a compiler error
    ' because type variance in generic parameters is not supported
    ' for value types, even if generic type parameters are declared variant.
    ' Dim dObject As DInvariant(Of Object) = dInt
    ' Dim dLong As DInvariant(Of Long) = dInt
    ' Dim dVariantObject As DInvariant(Of Object) = dInt
    ' Dim dVariantLong As DInvariant(Of Long) = dInt
End Sub

Konversi Delegasi Yang Dilonggarkan di Visual Basic

Konversi delegasi yang lebih fleksibel memungkinkan kemampuan dalam mencocokkan tanda tangan metode dengan jenis delegasi. Misalnya, ini memungkinkan Anda menghilangkan spesifikasi parameter dan menghilangkan nilai pengembalian fungsi saat Anda menetapkan metode ke delegasi. Untuk informasi selengkapnya, lihat Konversi Delegasi yang Dimudahkan.

Lihat juga