Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat mendeklarasikan parameter jenis generik dalam antarmuka sebagai kovarian atau kontravarian. Kovarian memungkinkan metode antarmuka untuk memiliki jenis pengembalian yang lebih turunan daripada yang ditentukan oleh parameter jenis generik. Kontravarian memungkinkan metode antarmuka untuk memiliki jenis argumen yang kurang diturunkan dari yang ditentukan oleh parameter generik. Antarmuka generik yang memiliki parameter jenis generik kovarian atau kontravarian disebut varian.
Nota
.NET Framework 4 memperkenalkan dukungan varians untuk beberapa antarmuka generik yang ada. Untuk daftar antarmuka varian di .NET Framework, lihat Varians di Antarmuka Generik (Visual Basic).
Mendeklarasikan Varian Antarmuka Generik
Anda dapat mendeklarasikan antarmuka generik varian dengan menggunakan in
kata kunci dan out
untuk parameter jenis generik.
Penting
ByRef
parameter di Visual Basic tidak boleh berupa varian. Jenis nilai juga tidak mendukung varians.
Anda dapat mendeklarasikan kovarian parameter jenis generik dengan menggunakan out
kata kunci. Jenis kovarian harus memenuhi kondisi berikut:
Jenis hanya digunakan sebagai jenis pengembalian metode antarmuka dan tidak digunakan sebagai jenis argumen metode. Ini diilustrasikan dalam contoh berikut, di mana jenis
R
dinyatakan kovarian.Interface ICovariant(Of Out R) Function GetSomething() As R ' The following statement generates a compiler error. ' Sub SetSomething(ByVal sampleArg As R) End Interface
Ada satu pengecualian untuk aturan ini. Jika Anda memiliki delegasi generik kontravarian sebagai parameter metode, Anda dapat menggunakan jenis sebagai parameter tipe untuk delegasi generik tersebut. Ini diilustrasikan oleh jenis
R
dalam contoh berikut. Untuk informasi selengkapnya, lihat Varians di Delegasi (Visual Basic) dan Menggunakan Varians untuk Delegasi Generik Func dan Aksi (Visual Basic).Interface ICovariant(Of Out R) Sub DoSomething(ByVal callback As Action(Of R)) End Interface
Jenis ini tidak digunakan sebagai batasan generik untuk metode antarmuka. Ini diilustrasikan dalam kode berikut.
Interface ICovariant(Of Out R) ' The following statement generates a compiler error ' because you can use only contravariant or invariant types ' in generic constraints. ' Sub DoSomething(Of T As R)() End Interface
Anda dapat mendeklarasikan parameter jenis generik kontravarian dengan menggunakan in
kata kunci. Jenis kontravarian hanya dapat digunakan sebagai jenis argumen metode dan bukan sebagai jenis pengembalian metode antarmuka. Jenis kontravarian juga dapat digunakan untuk batasan generik. Kode berikut menunjukkan cara mendeklarasikan antarmuka kontravarian dan menggunakan batasan generik untuk salah satu metodenya.
Interface IContravariant(Of In A)
Sub SetSomething(ByVal sampleArg As A)
Sub DoSomething(Of T As A)()
' The following statement generates a compiler error.
' Function GetSomething() As A
End Interface
Dimungkinkan juga untuk mendukung kovariansi dan kontravarians dalam antarmuka yang sama, tetapi untuk parameter jenis yang berbeda, seperti yang ditunjukkan dalam contoh kode berikut.
Interface IVariant(Of Out R, In A)
Function GetSomething() As R
Sub SetSomething(ByVal sampleArg As A)
Function GetSetSomething(ByVal sampleArg As A) As R
End Interface
Di Visual Basic, Anda tidak dapat mendeklarasikan peristiwa dalam antarmuka varian tanpa menentukan jenis delegasi. Selain itu, antarmuka varian tidak dapat memiliki kelas, enum, atau struktur berlapis, tetapi dapat memiliki antarmuka berlapis. Ini diilustrasikan dalam kode berikut.
Interface ICovariant(Of Out R)
' The following statement generates a compiler error.
' Event SampleEvent()
' The following statement specifies the delegate type and
' does not generate an error.
Event AnotherEvent As EventHandler
' The following statements generate compiler errors,
' because a variant interface cannot have
' nested enums, classes, or structures.
'Enum SampleEnum : test : End Enum
'Class SampleClass : End Class
'Structure SampleStructure : Dim value As Integer : End Structure
' Variant interfaces can have nested interfaces.
Interface INested : End Interface
End Interface
Menerapkan Antarmuka Generik Varian
Anda menerapkan antarmuka generik varian di kelas dengan menggunakan sintaks yang sama yang digunakan untuk antarmuka invarian. Contoh kode berikut menunjukkan cara mengimplementasikan antarmuka kovarian di kelas generik.
Interface ICovariant(Of Out R)
Function GetSomething() As R
End Interface
Class SampleImplementation(Of R)
Implements ICovariant(Of R)
Public Function GetSomething() As R _
Implements ICovariant(Of R).GetSomething
' Some code.
End Function
End Class
Kelas yang mengimplementasikan antarmuka varian adalah tidak bervariasi. Misalnya, pertimbangkan kode berikut.
The interface is covariant.
Dim ibutton As ICovariant(Of Button) =
New SampleImplementation(Of Button)
Dim iobj As ICovariant(Of Object) = ibutton
' The class is invariant.
Dim button As SampleImplementation(Of Button) =
New SampleImplementation(Of Button)
' The following statement generates a compiler error
' because classes are invariant.
' Dim obj As SampleImplementation(Of Object) = button
Memperluas Varian Antarmuka Generik
Ketika Anda memperluas antarmuka generik varian, Anda harus menggunakan kata kunci in
dan out
untuk menentukan secara eksplisit apakah antarmuka turunan mendukung varians. Kompilator tidak menyimpulkan perbedaan dari antarmuka yang diekstensikan. Misalnya, pertimbangkan antarmuka berikut.
Interface ICovariant(Of Out T)
End Interface
Interface IInvariant(Of T)
Inherits ICovariant(Of T)
End Interface
Interface IExtCovariant(Of Out T)
Inherits ICovariant(Of T)
End Interface
Dalam antarmuka Invariant(Of T)
, parameter jenis generik T
bersifat invariant, sedangkan dalam IExtCovariant (Of Out T)
, parameter jenis bersifat kovarian, meskipun kedua antarmuka memperluas antarmuka yang sama. Aturan yang sama diterapkan ke parameter jenis generik kontravarian.
Anda dapat membuat antarmuka yang memperluas antarmuka di mana parameter jenis generik T
bersifat kovarian dan antarmuka di mana parameter tersebut bersifat kontravarian, asalkan dalam antarmuka yang memperluas parameter jenis generik T
tetap bersifat invariant. Ini diilustrasikan dalam contoh kode berikut.
Interface ICovariant(Of Out T)
End Interface
Interface IContravariant(Of In T)
End Interface
Interface IInvariant(Of T)
Inherits ICovariant(Of T), IContravariant(Of T)
End Interface
Namun, jika parameter T
jenis generik dinyatakan kovarian dalam satu antarmuka, Anda tidak dapat menyatakannya kontravarian dalam antarmuka yang diperluas, atau sebaliknya. Ini diilustrasikan dalam contoh kode berikut.
Interface ICovariant(Of Out T)
End Interface
' The following statements generate a compiler error.
' Interface ICoContraVariant(Of In T)
' Inherits ICovariant(Of T)
' End Interface
Menghindari Ambiguitas
Ketika Anda menerapkan antarmuka generik varian, varians terkadang dapat menyebabkan ambiguitas. Ini harus dihindari.
Misalnya, jika Anda secara eksplisit menerapkan antarmuka generik varian yang sama dengan parameter jenis generik yang berbeda dalam satu kelas, itu dapat membuat ambiguitas. Pengkompilasi tidak menghasilkan kesalahan dalam kasus ini, tetapi tidak ditentukan implementasi antarmuka mana yang akan dipilih pada waktu proses. Ini dapat menyebabkan bug halus dalam kode Anda. Perhatikan contoh kode berikut.
Nota
Dengan Option Strict Off
, Visual Basic menghasilkan peringatan kompilator ketika ada implementasi antarmuka yang ambigu. Dengan Option Strict On
, Visual Basic menghasilkan kesalahan pengkompilasi.
' Simple class hierarchy.
Class Animal
End Class
Class Cat
Inherits Animal
End Class
Class Dog
Inherits Animal
End Class
' This class introduces ambiguity
' because IEnumerable(Of Out T) is covariant.
Class Pets
Implements IEnumerable(Of Cat), IEnumerable(Of Dog)
Public Function GetEnumerator() As IEnumerator(Of Cat) _
Implements IEnumerable(Of Cat).GetEnumerator
Console.WriteLine("Cat")
' Some code.
End Function
Public Function GetEnumerator1() As IEnumerator(Of Dog) _
Implements IEnumerable(Of Dog).GetEnumerator
Console.WriteLine("Dog")
' Some code.
End Function
Public Function GetEnumerator2() As IEnumerator _
Implements IEnumerable.GetEnumerator
' Some code.
End Function
End Class
Sub Main()
Dim pets As IEnumerable(Of Animal) = New Pets()
pets.GetEnumerator()
End Sub
Dalam contoh ini, tidak ditentukan bagaimana pets.GetEnumerator
metode memilih antara Cat
dan Dog
. Ini dapat menyebabkan masalah dalam kode Anda.