Megosztás a következőn keresztül:


Variancia a meghatalmazottakban (Visual Basic)

.NET-keretrendszer 3.5-ös verzióban bevezettük a variancia-támogatást a C# és a Visual Basic összes delegáltjának delegálttípusával rendelkező metódusaláírásokhoz. Ez azt jelenti, hogy a meghatalmazottakhoz nem csak az egyező aláírással rendelkező metódusokat rendelheti hozzá, hanem olyan metódusokat is, amelyek több származtatott típust (kovarianciát) adnak vissza, vagy olyan paramétereket fogadnak el, amelyek kevésbé származtatott típusok (kontravarianciával) rendelkeznek, mint a delegált típus által megadottak. Ide tartoznak az általános és a nem általános meghatalmazottak is.

Vegyük például a következő kódot, amelynek két osztálya és két meghatalmazottja van: általános és nem általános.

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

Az ilyen vagy SampleDelegate(Of A, R) típusú meghatalmazottak SampleDelegate létrehozásakor az alábbi módszerek bármelyikét hozzárendelheti ezekhez a meghatalmazottakhoz.

' 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

Az alábbi példakód a metódus aláírása és a delegált típusa közötti implicit konverziót szemlélteti.

' 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

További példákért tekintse meg a Variance használata a meghatalmazottakban (Visual Basic) és a Variance használata Func és Action Generic Meghatalmazottakhoz (Visual Basic) című témakört.

Variancia az általános típusparaméterekben

A 4. és újabb .NET-keretrendszer engedélyezheti a meghatalmazottak közötti implicit konverziót, így az általános típusparaméterek által meghatározott különböző típusú általános meghatalmazottak egymáshoz rendelhetők, ha a típusok a variancia által megkövetelt módon öröklődnek egymástól.

Az implicit átalakítás engedélyezéséhez explicit módon kell deklarálnia az általános paramétereket egy meghatalmazottban kovariantként vagy contravariantként a vagy out a in kulcsszó használatával.

Az alábbi példakód bemutatja, hogyan hozhat létre olyan meghatalmazottat, aki kovariáns általános típusparaméterrel rendelkezik.

' 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

Ha csak a variancia-támogatást használja a metódusaadékok delegálási típusokkal való egyeztetéséhez, és nem használja a kulcsszavakat és out a in delegáltakat, előfordulhat, hogy néha azonos lambda-kifejezésekkel vagy metódusokkal is példányosíthatja a meghatalmazottakat, de nem rendelhet hozzá egy meghatalmazottat egy másikhoz.

A következő kód példában SampleGenericDelegate(Of String) nem konvertálható explicit módon SampleGenericDelegate(Of Object), bár String örökli Object. Ezt a problémát az általános paraméter T kulcsszóval való megjelölésével out háríthatja el.

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

Általános meghatalmazottak, amelyek a .NET-keretrendszer variánstípus-paraméterekkel rendelkeznek

.NET-keretrendszer 4 számos meglévő általános meghatalmazott esetében bevezette az általános típusparaméterek varianciájának támogatását:

További információkért és példákért lásd : Variance for Func and Action Generic Delegates (Visual Basic).

Variant type parameters deklarálása általános meghatalmazottakban

Ha egy általános delegált rendelkezik kovariant vagy contravariant általános típusparaméterekkel, akkor ezt nevezhetjük variáns általános delegáltnak.

Egy általános típusú paraméter kovariantot deklarálhat egy általános meghatalmazottban a out kulcsszó használatával. A kovariant típus csak metódus-visszatérési típusként használható, metódusargumentum-típusként nem. Az alábbi példakód bemutatja, hogyan deklarálhat kovariantikus általános meghatalmazottat.

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

A kulcsszó használatával deklarálhat egy általános típusparamétert contravariant-ként egy in általános delegáltban. A contravariant típus csak metódusargumentumok típusaként használható, metódusvisszautasítási típusként nem. Az alábbi példakód bemutatja, hogyan deklarálhat egy contravariant általános meghatalmazottat.

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

Fontos

ByRef a Visual Basicben a paraméterek nem jelölhetők meg variánsként.

A varianciát és a kovarianciát is támogathatja ugyanabban a delegáltban, de különböző típusparaméterek esetén. Ez az alábbi példában látható.

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

Variant Generic-meghatalmazottak példányosítása és meghívása

A változatdelegáltak példányosítása és meghívása ugyanúgy lehetséges, mint az invariáns meghatalmazottak példányosítása és meghívása. Az alábbi példában a meghatalmazottat egy lambda kifejezés hozza létre.

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

Variant Generic Delegates kombinálása

A változatdelegáltak nem kombinálhatók. A Combine metódus nem támogatja a változatdelegáltak konvertálását, és elvárja, hogy a meghatalmazottak pontosan azonos típusúak legyenek. Ez futásidejű kivételhez vezethet, ha a meghatalmazottakat a Combine metódussal (C# és Visual Basic) vagy az + operátorral (C#-ban) kombinálja, ahogyan az az alábbi kód példájában is látható.

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)

Érték- és referenciatípusok általános típusparamétereinek varianciája

Az általános típusparaméterek varianciája csak referenciatípusok esetén támogatott. Nem lehet például implicit módon átalakítani vagy DVariant(Of Long)átalakítaniDVariant(Of Object), DVariant(Of Int)mert az egész szám értéktípus.

Az alábbi példa azt mutatja be, hogy az általános típusparaméterek varianciája nem támogatott az értéktípusok esetében.

' 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

Nyugodt delegálás konvertálása a Visual Basicben

A nyugodt delegálás nagyobb rugalmasságot tesz lehetővé a metódus-aláírások delegálási típusokkal való egyeztetésében. Például lehetővé teszi, hogy kihagyja a paraméterek specifikációit, és kihagyja a függvény visszatérési értékeit, amikor metódust rendel egy delegálthoz. További információ: Nyugodt meghatalmazotti átalakítás.

Lásd még