Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az interfészek általános típusparamétereit kovariantként vagy contravariantként deklarálhatja. A kovariancia lehetővé teszi, hogy a felületi metódusok az általános típusparaméterek által definiáltnál több származtatott visszatérési típussal rendelkezzenek. A contravariance lehetővé teszi, hogy az illesztő metódusok az általános paraméterek által megadottnál kevésbé származtatott argumentumtípusokkal rendelkezzenek. A kovariant vagy contravariant általános típusparaméterekkel rendelkező általános felületet variant-nak nevezzük.
Megjegyzés:
A .NET-keretrendszer 4 bemutatta a variancia támogatását számos meglévő általános interfészhez. A .NET-keretrendszerben található változatillesztők listájáért lásd: Variancia az általános felületekben (Visual Basic).
Változó generikus interfészek deklarálása
Általános típusú variáns felületeket a in és out kulcsszavak használatával deklarálhatja.
Fontos
ByRef a Visual Basic paraméterei nem variálhatók. Az értéktípusok a varianciát sem támogatják.
A kulcsszó használatával out kovariant típusú általános paramétert deklarálhat. A kovariant típusnak meg kell felelnie a következő feltételeknek:
A típus csak az interfészmetódusok visszatérési típusaként használatos, és nem használható metódusargumentumok típusaként. Ezt a következő példában szemlélteti, amelyben a típus
Rkovariantnak van deklarálva.Interface ICovariant(Of Out R) Function GetSomething() As R ' The following statement generates a compiler error. ' Sub SetSomething(ByVal sampleArg As R) End InterfaceA szabály alól egyetlen kivétel van. Ha van egy kontravariáns általános delegáltja, mint metódusparaméter, a típust általános típusparaméterként használhatja a delegáltnál. Ezt az alábbi példában szereplő típus
Rszemlélteti. További információ: Variance in Delegates (Visual Basic) és Using Variance for Func and Action Generic Delegates (Visual Basic).Interface ICovariant(Of Out R) Sub DoSomething(ByVal callback As Action(Of R)) End InterfaceA típus nem általános korlátozásként használatos az interfészmetelyekhez. Ezt az alábbi kód szemlélteti.
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
A in kulcsszó használatával deklarálhat egy általános típusparamétert kontravariánsként. A contravariant típus csak metódusargumentumok típusaként használható, az interfészmetódusok visszatérési típusaként nem. A contravariant típus általános korlátozásokhoz is használható. Az alábbi kód bemutatja, hogyan deklarálhat egy contravariant felületet, és hogyan használhat általános kényszert az egyik metódusához.
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
A kovariancia és a contravariance ugyanazon a felületen is támogatott, de különböző típusparaméterek esetén is, ahogy az alábbi kódpéldában látható.
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
A Visual Basicben nem deklarálhat eseményeket a variáns felületeken a delegált típus megadása nélkül. A változatillesztők nem tartalmazhatnak beágyazott osztályokat, számokat vagy struktúrákat, de beágyazott illesztőkkel is rendelkezhetnek. Ezt az alábbi kód szemlélteti.
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
Variant Generic Interfaces implementálása
A variáns általános felületeket az osztályokban az invariáns felületekhez használt szintaxissal implementálhatja. Az alábbi példakód bemutatja, hogyan implementálhat kovariantikus felületet egy általános osztályban.
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
A variáns interfészeket megvalósító osztályok invariánsak. Vegyük például az alábbi kódot.
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
Variant Generic Interfaces kiterjesztése
Amikor egy variáns generikus interfészt kiterjeszt, a in és out kulcsszavakat kell használnia annak explicit meghatározásához, hogy a származtatott interfész támogatja-e a varianciát. A fordító nem vonja le a varianciát a kiterjesztett interfészről. Vegyük például az alábbi felületeket.
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
Az interfészben az Invariant(Of T) általános típusparaméter T invariáns, míg IExtCovariant (Of Out T)a típusparaméter kovariáns, bár mindkét interfész ugyanazt a felületet bővíti. Ugyanez a szabály vonatkozik a contravariant általános típusparaméterekre.
Létrehozhat egy interfészt, amely kiterjeszti mind az általános típusparaméter T kovariant felületét, mind a contravariant felületet, ha a bővítő felületen az általános típusparaméter T invariáns. Ezt az alábbi példakód szemlélteti.
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
Ha azonban egy általános típusú paraméter T kovariantnak van deklarálva egy felületen, akkor nem deklarálhatja azt a kiterjesztett felületen, vagy fordítva. Ezt az alábbi példakód szemlélteti.
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
A kétértelműség elkerülése
A variant generic interfészek implementálása esetén a variancia néha kétértelműséghez vezethet. Ezt el kell kerülni.
Ha például explicit módon implementálja ugyanazt a variáns általános felületet különböző általános típusparaméterekkel egy osztályban, az kétértelműséget okozhat. A fordító ebben az esetben nem okoz hibát, de nincs megadva, hogy melyik felület implementációja lesz kiválasztva futásidőben. Ez apró hibákhoz vezethet a kódban. Tekintse meg a következő kód példáját.
Megjegyzés:
A Option Strict Off Visual Basic fordítói figyelmeztetést hoz létre, ha homályos interfész implementáció van. A Option Strict On használatával a Visual Basic fordítóhibát generál.
' 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
Ebben a példában nincs meghatározva, hogyan választ a pets.GetEnumerator metódus Cat és Dog között. Ez problémákat okozhat a kódban.