다음을 통해 공유


대리자 차이(Visual Basic)

.NET Framework 3.5에서는 C# 및 Visual Basic의 모든 대리자에서 대리자 형식과 메서드 시그니처를 일치시키는 분산 지원을 도입했습니다. 즉, 일치하는 서명이 있는 메서드뿐만 아니라 더 많은 파생 형식(공변성)을 반환하거나 대리자 형식에서 지정한 것보다 파생 형식(반공변성)이 적은 매개 변수를 허용하는 메서드에도 할당할 수 있습니다. 여기에는 제네릭 대리자와 제네릭이 아닌 대리자가 모두 포함됩니다.

예를 들어 제네릭과 제네릭이 아닌 두 개의 클래스와 두 개의 대리자가 있는 다음 코드를 고려해 보세요.

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

또는 SampleDelegate 형식의 SampleDelegate(Of A, R) 대리자를 만들 때 다음 메서드 중 하나를 해당 대리자에게 할당할 수 있습니다.

' 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

다음 코드 예제에서는 메서드 서명과 대리자 형식 간의 암시적 변환을 보여 줍니다.

' 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

자세한 예제는 대리자에서 가변성 사용(Visual Basic)Func 및 Action 제네릭 대리자(Visual Basic)에 대한 분산 사용(Visual Basic)을 참조하세요.

제네릭 형식 매개 변수의 분산

.NET Framework 4 이상에서는 대리자 간에 암시적 변환을 활성화할 수 있으며, 제네릭 형식 매개 변수로 지정된 서로 다른 형식을 가진 제네릭 대리자가, 분산에 필요한 경우 해당 형식들이 서로 상속되는 경우에 서로 할당될 수 있습니다.

암시적 변환을 사용하도록 설정하려면 대리자의 제네릭 매개 변수를 키워드 `in` 또는 `out`을 사용하여 공변 또는 반공변으로 명시적으로 선언해야 합니다.

다음 코드 예제에서는 공변 제네릭 형식 매개 변수가 있는 대리자를 만드는 방법을 보여줍니다.

' 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

변수 지원만 사용하여 메서드 시그니처를 대리자 형식과 일치시키고 c0 및 c1 키워드를 사용하지 않는 경우, 때로는 동일한 람다 식 또는 메서드로 대리자의 인스턴스를 생성할 수는 있지만, 한 대리자를 다른 대리자에게 할당할 수는 없습니다.

다음 코드 예제에서 SampleGenericDelegate(Of String)SampleGenericDelegate(Of Object)을 상속받지만, StringObject로 명시적으로 변환할 수 없습니다. 제네릭 매개 변수 T 를 키워드로 out 표시하여 이 문제를 해결할 수 있습니다.

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

.NET Framework에 변형 형식 매개 변수가 있는 제네릭 대리자

.NET Framework 4에는 여러 기존 제네릭 대리자에서 제네릭 형식 매개 변수에 대한 분산 지원이 도입되었습니다.

자세한 내용 및 예제는 Func 및 Action 제네릭 대리자(Visual Basic)에 대한 분산 사용을 참조하세요.

제네릭 대리자에서 변형 형식 매개변수 선언

제네릭 대리자가 공변 또는 반공변 제네릭 형식 매개 변수를 갖는 경우 변형 제네릭 대리자라고 할 수 있습니다.

키워드 out를 사용하여 제네릭 대리자에서 제네릭 형식 매개 변수의 공변성을 선언할 수 있습니다. 공변 형식은 메서드 반환 형식으로만 사용할 수 있으며 메서드 인수의 형식으로는 사용할 수 없습니다. 다음 코드 예제에서는 공변 제네릭 대리자를 선언하는 방법을 보여줍니다.

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

제네릭 대리자에서 in 키워드를 사용하여 제네릭 타입 매개변수를 반변성으로 선언할 수 있습니다. 반공변성 형식은 메서드 반환 형식이 아닌 메서드 인수의 형식으로만 사용할 수 있습니다. 다음 코드 예제에서는 반공변 제네릭 대리자를 선언하는 방법을 보여줍니다.

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

중요합니다

ByRef Visual Basic의 매개 변수는 변형으로 표시할 수 없습니다.

동일한 대리자에서 분산 및 공변성 모두를 지원할 수도 있지만 다른 형식 매개 변수에 대해서도 지원합니다. 이 방법은 다음 예제에서 확인할 수 있습니다.

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

Variant 제네릭 대리자 인스턴스화 및 호출

고정 대리자를 인스턴스화하고 호출하는 것처럼 변형 대리자를 인스턴스화하고 호출할 수 있습니다. 다음 예제에서는 대리자가 람다 식으로 인스턴스화됩니다.

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

변형된 제네릭 대리자 결합하기

변형 대리자를 결합하면 안 됩니다. 이 메서드는 Combine 변형 대리자 변환을 지원하지 않으며 대리자가 정확히 동일한 형식이어야 합니다. 이 경우 다음 코드 예제와 같이 메서드(C# 및 Visual Basic)를 사용 Combine 하거나 연산자(C#)를 사용하여 + 대리자를 결합할 때 런타임 예외가 발생할 수 있습니다.

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)

값 및 참조 형식에 대한 제네릭 형식 매개 변수의 분산

제네릭 형식 매개 변수에 대한 분산은 참조 형식에 대해서만 지원됩니다. 예를 들어 DVariant(Of Int)는 정수가 값 형식이기 때문에 DVariant(Of Object) 또는 DVariant(Of Long)로 암시적 변환이 불가능합니다.

다음 예제에서는 제네릭 형식 매개 변수의 분산이 값 형식에 대해 지원되지 않는 것을 보여 줍니다.

' 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

Visual Basic에서 유연한 대리자 변환

대리자 변환을 완화하면 메서드 시그니처를 대리자 형식과 더 유연하게 일치할 수 있습니다. 예를 들어 대리자에서 메서드를 할당할 때 매개 변수 사양을 생략하고 함수 반환 값을 생략할 수 있습니다. 자세한 내용은 완화된 대리자 변환을 참조하세요.

참고하십시오