공변성(Covariance) 및 반공변성(Contravariance)(C# 및 Visual Basic)

C# 및 Visual Basic에서는 공 분산 및 반공변성(Contravariance)을 통해 배열 형식, 대리자 형식 및 제네릭 형식 인수에 대한 암시적 참조 변환이 가능합니다. 공 분산은 할당 호환성을 유지하고 반공변성(Contravariance)은 할당 호환성을 반대로 바꿉니다.

다음 코드에서는 할당 호환성, 공 분산 및 반공변성(Contravariance) 간 차이점을 보여 줍니다.

' Assignment compatibility. 
Dim str As String = "test"
' An object of a more derived type is assigned to an object of a less derived type. 
Dim obj As Object = str

' Covariance. 
Dim strings As IEnumerable(Of String) = New List(Of String)()
' An object that is instantiated with a more derived type argument 
' is assigned to an object instantiated with a less derived type argument. 
' Assignment compatibility is preserved. 
Dim objects As IEnumerable(Of Object) = strings

' Contravariance.           
' Assume that there is the following method in the class: 
' Shared Sub SetObject(ByVal o As Object)
' End Sub
Dim actObject As Action(Of Object) = AddressOf SetObject

' An object that is instantiated with a less derived type argument 
' is assigned to an object instantiated with a more derived type argument. 
' Assignment compatibility is reversed. 
Dim actString As Action(Of String) = actObject
// Assignment compatibility. 
string str = "test";
// An object of a more derived type is assigned to an object of a less derived type. 
object obj = str;

// Covariance. 
IEnumerable<string> strings = new List<string>();
// An object that is instantiated with a more derived type argument 
// is assigned to an object instantiated with a less derived type argument. 
// Assignment compatibility is preserved. 
IEnumerable<object> objects = strings;

// Contravariance.           
// Assume that the following method is in the class: 
// static void SetObject(object o) { } 
Action<object> actObject = SetObject;
// An object that is instantiated with a less derived type argument 
// is assigned to an object instantiated with a more derived type argument. 
// Assignment compatibility is reversed. 
Action<string> actString = actObject;

배열에 공 분산을 사용하면 더 많이 파생된 형식의 배열을 더 적게 파생된 형식의 배열로 암시적으로 변환할 수 있습니다. 그러나 다음 코드 예제와 같이 이 작업은 형식이 안전하지 않습니다.

Dim array() As Object = New String(10) {}
' The following statement produces a run-time exception.
' array(0) = 10
object[] array = new String[10];
// The following statement produces a run-time exception.
// array[0] = 10;

메서드 그룹에 대한 공 분산 및 반공변성(Contravariance) 지원을 통해 메서드 시그니처를 대리자 형식과 일치시킬 수 있습니다. 따라서 일치하는 시그니처가 있는 메서드뿐 아니라 대리자 형식에 지정된 것보다 더 많은 파생 형식을 반환하거나(공변성) 더 적은 파생 형식을 받아들이는(반공변성) 메서드도 대리자에 할당할 수 있습니다. 자세한 내용은 대리자의 가변성(C# 및 Visual Basic)대리자의 가변성 사용(C# 및 Visual Basic)을 참조하십시오.

다음 코드 예제에서는 메서드 그룹에 대한 공 분산 및 반공변성(Contravariance) 지원을 보여 줍니다.

Shared Function GetObject() As Object
    Return Nothing
End Function

Shared Sub SetObject(ByVal obj As Object)
End Sub

Shared Function GetString() As String
    Return ""
End Function

Shared Sub SetString(ByVal str As String)

End Sub

Shared Sub Test()
    ' Covariance. A delegate specifies a return type as object,
    ' but you can assign a method that returns a string.
    Dim del As Func(Of Object) = AddressOf GetString

    ' Contravariance. A delegate specifies a parameter type as string,
    ' but you can assign a method that takes an object.
    Dim del2 As Action(Of String) = AddressOf SetObject
End Sub
static object GetObject() { return null; }
static void SetObject(object obj) { }

static string GetString() { return ""; }
static void SetString(string str) { }

static void Test()
{
    // Covariance. A delegate specifies a return type as object,
    // but you can assign a method that returns a string.
    Func<object> del = GetString;

    // Contravariance. A delegate specifies a parameter type as string,
    // but you can assign a method that takes an object.
    Action<string> del2 = SetObject;
}

.NET Framework 4 및 Visual Studio 2010에서는 C#과 Visual Basic이 둘 다 제네릭 인터페이스와 대리자에서 공 분산과 반공변성(Contravariance)을 지원하고 제네릭 형식 매개 변수의 암시적 변환을 허용합니다. 자세한 내용은 제네릭 인터페이스의 가변성(C# 및 Visual Basic)대리자의 가변성(C# 및 Visual Basic)을 참조하십시오.

다음 코드 예제에서는 제네릭 인터페이스에 대한 암시적 참조 변환을 보여 줍니다.

Dim strings As IEnumerable(Of String) = New List(Of String)
Dim objects As IEnumerable(Of Object) = strings
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;

제네릭 매개 변수가 공변(covariant) 또는 반공변(contravariant)으로 선언된 경우에는 제네릭 인터페이스나 대리자를 variant 인터페이스라고 합니다. C#과 Visual Basic 둘 다에서는 사용자 고유의 variant 인터페이스 및 대리자를 만들 수 있습니다. 자세한 내용은 Variant 제네릭 인터페이스 만들기(C# 및 Visual Basic)대리자의 가변성(C# 및 Visual Basic)을 참조하십시오.

관련 항목

제목

설명

제네릭 인터페이스의 가변성(C# 및 Visual Basic)

제네릭 인터페이스의 공 분산 및 반공변성(Contravariance)에 대해 설명하고 .NET Framework의 variant 제네릭 인터페이스 목록을 제공합니다.

Variant 제네릭 인터페이스 만들기(C# 및 Visual Basic)

사용자 지정 variant 인터페이스를 만드는 방법을 보여 줍니다.

제네릭 컬렉션용 인터페이스의 가변성 사용(C# 및 Visual Basic)

IEnumerable<T>IComparable<T> 인터페이스에서의 공 분산 및 반공변성(Contravariance) 지원이 코드를 다시 사용하는 데 어떻게 도움이 되는지 보여 줍니다.

대리자의 가변성(C# 및 Visual Basic)

제네릭 및 제네릭이 아닌 대리자의 공 분산과 반공변성(Contravariance)에 대해 설명하고 .NET Framework의 variant 제네릭 대리자 목록을 제공합니다.

대리자의 가변성 사용(C# 및 Visual Basic)

제네릭이 아닌 대리자에서 공 분산 및 반공변성(Contravariance) 지원을 사용하여 메서드 시그니처를 대리자 형식과 일치시키는 방법을 보여 줍니다.

Func 및 Action 제네릭 대리자에 가변성 사용(C# 및 Visual Basic)

Func 및 Action 대리자에서의 공 분산 및 반공변성(Contravariance) 지원이 코드를 다시 사용하는 데 어떻게 도움이 되는지 보여 줍니다.