Delen via


Variant generic Interfaces maken (Visual Basic)

U kunt algemene typeparameters in interfaces declareren als covariant of contravariant. Met covariantie kunnen interfacemethoden meer afgeleide retourtypen hebben dan die zijn gedefinieerd door de algemene typeparameters. Met Contravariantie kunnen interfacemethoden argumenttypen hebben die minder zijn afgeleid dan die zijn opgegeven door de algemene parameters. Een algemene interface met covariant of contravariant algemene typeparameters wordt variant genoemd.

Notitie

.NET Framework 4 heeft variantieondersteuning geïntroduceerd voor verschillende bestaande algemene interfaces. Zie Variantie in Generic Interfaces (Visual Basic) voor de lijst met variantinterfaces in .NET Framework.

Het declareren van algemene variantinterfaces

U kunt variant generic interfaces declareren met behulp van de in en out trefwoorden voor algemene typeparameters.

Belangrijk

ByRef parameters in Visual Basic kunnen geen variant zijn. Waardetypen bieden ook geen ondersteuning voor variantie.

U kunt een covariant van een algemene typeparameter declareren met behulp van het out trefwoord. Het covarianttype moet aan de volgende voorwaarden voldoen:

  • Het type wordt alleen gebruikt als een retourtype interfacemethoden en niet gebruikt als een type methodeargumenten. Dit wordt geïllustreerd in het volgende voorbeeld, waarin het type R covariant wordt gedeclareerd.

    Interface ICovariant(Of Out R)
        Function GetSomething() As R
        ' The following statement generates a compiler error.
        ' Sub SetSomething(ByVal sampleArg As R)
    End Interface
    

    Er is één uitzondering op deze regel. Als u een algemene gemachtigde met contravariant als methodeparameter hebt, kunt u het type gebruiken als een algemene typeparameter voor de gemachtigde. Dit wordt geïllustreerd door het type R in het volgende voorbeeld. Zie Variantie in Gemachtigden (Visual Basic) en Variantie gebruiken voor Func en Action Generic Delegates (Visual Basic) voor meer informatie.

    Interface ICovariant(Of Out R)
        Sub DoSomething(ByVal callback As Action(Of R))
    End Interface
    
  • Het type wordt niet gebruikt als een algemene beperking voor de interfacemethoden. Dit wordt geïllustreerd in de volgende code.

    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
    

U kunt een algemeen type parameter contravariant declareren met behulp van het in trefwoord. Het contravarianttype kan alleen worden gebruikt als een type methodeargumenten en niet als een retourtype interfacemethoden. Het type contravariant kan ook worden gebruikt voor algemene beperkingen. De volgende code laat zien hoe u een contravariant-interface declareert en een algemene beperking gebruikt voor een van de methoden.

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

Het is ook mogelijk om covariantie en contravariantie in dezelfde interface te ondersteunen, maar voor verschillende typeparameters, zoals wordt weergegeven in het volgende codevoorbeeld.

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

In Visual Basic kunt u geen gebeurtenissen declareren in variantinterfaces zonder het type gedelegeerde op te geven. Een variantinterface kan ook geen geneste klassen, opsommingen of structuren hebben, maar wel geneste interfaces hebben. Dit wordt geïllustreerd in de volgende code.

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

Algemene variantinterfaces implementeren

U implementeert variant-algemene interfaces in klassen met behulp van dezelfde syntaxis die wordt gebruikt voor invariante interfaces. In het volgende codevoorbeeld ziet u hoe u een covariant-interface in een algemene klasse implementeert.

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

Klassen die variantinterfaces implementeren, zijn invariant. Denk bijvoorbeeld aan de volgende code.

 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

Uitbreiding van algemene variantinterfaces

Wanneer u een algemene variantinterface uitbreidt, moet u de in en out trefwoorden gebruiken om expliciet op te geven of de afgeleide interface variantie ondersteunt. De compiler leidt niet af van de variantie van de interface die wordt uitgebreid. Denk bijvoorbeeld aan de volgende interfaces.

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

In de Invariant(Of T) interface is de algemene typeparameter T invariant, terwijl in IExtCovariant (Of Out T)de typeparameter covariant is, hoewel beide interfaces dezelfde interface uitbreiden. Dezelfde regel wordt toegepast op parameters van het algemene type contravariant.

U kunt een interface maken die zowel de interface uitbreidt als de algemene typeparameter T covariant is en de interface waar deze contravariant is als de parameter voor het algemene type T invariant is in de uitbreidingsinterface. Dit wordt geïllustreerd in het volgende codevoorbeeld.

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

Als een algemene typeparameter T echter covariant in één interface wordt gedeclareerd, kunt u deze niet declareren in de uitbreidingsinterface of omgekeerd. Dit wordt geïllustreerd in het volgende codevoorbeeld.

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

Dubbelzinnigheid vermijden

Wanneer u generieke variantinterfaces implementeert, kan afwijking soms leiden tot dubbelzinnigheid. Dit moet worden vermeden.

Als u bijvoorbeeld expliciet dezelfde algemene variantinterface met verschillende algemene typeparameters in één klasse implementeert, kan dit dubbelzinnigheid creëren. De compiler produceert in dit geval geen fout, maar wordt niet opgegeven welke interface-implementatie tijdens runtime wordt gekozen. Dit kan leiden tot subtiele fouten in uw code. Kijk eens naar het volgende codevoorbeeld.

Notitie

Met Option Strict OffVisual Basic wordt een compilerwaarschuwing gegenereerd wanneer er sprake is van een dubbelzinnige interface-implementatie. Met Option Strict OnVisual Basic wordt een compilerfout gegenereerd.

' 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

In dit voorbeeld wordt niet aangegeven hoe de pets.GetEnumerator methode kiest tussen Cat en Dog. Dit kan problemen in uw code veroorzaken.

Zie ook