다음을 통해 공유


변형 형식 일반 인터페이스 만들기(Visual Basic)

인터페이스에서 제네릭 형식 매개 변수를 공변 또는 반공변으로 선언할 수 있습니다. 공변성 에서는 인터페이스 메서드가 제네릭 형식 매개 변수에 정의된 것보다 더 많은 파생 반환 형식을 가질 수 있습니다. 반공변성(Contravariance )을 사용하면 인터페이스 메서드가 제네릭 매개 변수에 지정된 것보다 덜 파생된 인수 형식을 가질 수 있습니다. 공변 또는 반공변 제네릭 형식 매개 변수가 있는 제네릭 인터페이스를 variant라고 합니다.

비고

.NET Framework 4에는 여러 기존 제네릭 인터페이스에 대한 분산 지원이 도입되었습니다. .NET Framework의 변형 인터페이스 목록은 제네릭 인터페이스의 분산(Visual Basic)을 참조하세요.

Variant 제네릭 인터페이스 선언

제네릭 형식 매개 변수에 대해 inout 키워드를 사용하여 변형 제네릭 인터페이스를 선언할 수 있습니다.

중요합니다

ByRef Visual Basic의 매개 변수는 변형일 수 없습니다. 값 형식도 분산을 지원하지 않습니다.

키워드를 사용하여 제네릭 형식 매개 변수 공변을 선언할 out 수 있습니다. 공변 형식은 다음 조건을 충족해야 합니다.

  • 형식은 인터페이스 메서드의 반환 형식으로만 사용되며 메서드 인수의 형식으로 사용되지 않습니다. 다음은 형식 R 이 공변성으로 선언되는 다음 예제에 설명되어 있습니다.

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

    이 규칙에는 한 가지 예외가 있습니다. 메서드 매개 변수로 반공변 제네릭 대리자가 있는 경우 형식을 대리자의 제네릭 형식 매개 변수로 사용할 수 있습니다. 이는 다음 예제의 형식 R 에 의해 설명됩니다. 자세한 내용은 델리게이트에서의 분산(Visual Basic)Func와 Action 제네릭 델리게이트(Visual Basic)에서의 분산 사용을 참조하세요.

    Interface ICovariant(Of Out R)
        Sub DoSomething(ByVal callback As Action(Of R))
    End Interface
    
  • 형식은 인터페이스 메서드에 대한 제네릭 제약 조건으로 사용되지 않습니다. 다음 코드에 설명되어 있습니다.

    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
    

키워드를 사용하여 제네릭 형식 매개 변수 반공변을 선언할 in 수 있습니다. 반공변성 형식은 메서드 인수의 형식으로만 사용할 수 있으며 인터페이스 메서드의 반환 형식으로 사용할 수 없습니다. 반공변성 형식은 제네릭 제약 조건에도 사용할 수 있습니다. 다음 코드에서는 반공변 인터페이스를 선언하고 해당 메서드 중 하나에 대해 제네릭 제약 조건을 사용하는 방법을 보여 줍니다.

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

다음 코드 예제와 같이 동일한 인터페이스에서 공변성 및 반공변성 모두를 지원할 수 있지만 다른 형식 매개 변수에 대해서도 지원할 수 있습니다.

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

Visual Basic에서는 대리자 형식을 지정하지 않고는 변형 인터페이스에서 이벤트를 선언할 수 없습니다. 또한 변형 인터페이스에는 중첩 클래스, 열거형 또는 구조체가 있을 수 없지만 중첩된 인터페이스가 있을 수 있습니다. 다음 코드에 설명되어 있습니다.

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

변형 제네릭 인터페이스 구현

고정 인터페이스에 사용되는 것과 동일한 구문을 사용하여 클래스에서 변형 제네릭 인터페이스를 구현합니다. 다음 코드 예제에서는 제네릭 클래스에서 공변 인터페이스를 구현하는 방법을 보여줍니다.

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

변형 인터페이스를 구현하는 클래스는 고정되어 있습니다. 예를 들어 다음 코드를 고려합니다.

 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

변형 제네릭 인터페이스 확장

제네릭 변형 인터페이스를 확장할 때, 파생 인터페이스가 변동성을 지원하는지 여부를 명시적으로 지정하려면 inout 키워드를 사용해야 합니다. 컴파일러는 확장 중인 인터페이스의 분산을 유추하지 않습니다. 예를 들어 다음 인터페이스를 고려합니다.

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

Invariant(Of T) 인터페이스에서 제네릭 형식 매개 변수 T 는 고정된 반면 IExtCovariant (Of Out T)형식 매개 변수는 공변이지만 두 인터페이스는 동일한 인터페이스를 확장합니다. 반공변 제네릭 형식 매개 변수에 동일한 규칙이 적용됩니다.

제네릭 형식 매개 변수 T가 확장 인터페이스에서 불변일 경우, 제네릭 형식 매개 변수 T가 공변인 인터페이스와 반공변인 인터페이스를 모두 확장하는 인터페이스를 만들 수 있습니다. 다음 코드 예제에 설명되어 있습니다.

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

그러나 제네릭 형식 매개 변수 T 가 한 인터페이스에서 공변성으로 선언된 경우 확장 인터페이스에서 반공변성으로 선언하거나 그 반대로 선언할 수 없습니다. 다음 코드 예제에 설명되어 있습니다.

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

모호성 방지

변형 제네릭 인터페이스를 구현할 때 분산으로 인해 모호성이 발생할 수 있습니다. 이 작업은 피해야 합니다.

예를 들어 한 클래스에서 서로 다른 제네릭 형식 매개 변수를 사용하여 동일한 변형 제네릭 인터페이스를 명시적으로 구현하는 경우 모호성을 만들 수 있습니다. 이 경우 컴파일러는 오류를 생성하지 않지만 런타임에 어떤 인터페이스 구현을 선택할지는 지정되지 않습니다. 이로 인해 코드에서 미묘한 버그가 발생할 수 있습니다. 다음 코드 예제를 생각해보세요.

비고

Visual Option Strict OffBasic에서는 모호한 인터페이스 구현이 있을 때 컴파일러 경고를 생성합니다. Option Strict On을(를) 사용하면 Visual Basic에서 컴파일러 오류가 발생합니다.

' 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

이 예제에서는 pets.GetEnumerator 메서드가 CatDog 중에서 어떻게 선택하는지 지정되지 않았습니다. 이로 인해 코드에 문제가 발생할 수 있습니다.

참고하십시오