共変性と反変性 (C# および Visual Basic)

C# および Visual Basic では、共変性と反変性により、配列型、デリゲート型、およびジェネリック型引数の暗黙の参照変換が可能になっています。 共変性は代入互換性を維持し、反変性はこれを反転させます。

次のコードは、代入互換性、共変性、および反変性の違いを示しています。

' 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;

メソッド グループの共変性と反変性のサポートにより、メソッド シグネチャをデリゲート型と一致させることができます。 これにより、一致するシグネチャを持つメソッドだけでなく、デリゲート型で指定された型よりも強い派生型 (共変性) を返すメソッドや、弱い派生型 (反変性) のパラメーターを受け取るメソッドを、デリゲートに割り当てることができます。 詳細については、「デリゲートの分散 (C# および Visual Basic)」および「デリゲートの分散の使用 (C# および Visual Basic)」を参照してください。

次のコード例は、メソッド グループの共変性と反変性のサポートを示しています。

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 の両方で、ジェネリック インターフェイスや汎用デリゲートでの共変性と反変性がサポートされ、ジェネリック型パラメーターの暗黙の型変換が可能になっています。 詳細については、「ジェネリック インターフェイスの分散 (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;

ジェネリック インターフェイスや汎用デリゲートは、そのジェネリック パラメーターが共変または反変として宣言されている場合、バリアントと呼ばれます。 C# と Visual Basic のどちらでも、独自のバリアント インターフェイスやバリアント デリゲートを作成できます。 詳細については、「バリアント ジェネリック インターフェイスの作成 (C# および Visual Basic)」および「デリゲートの分散 (C# および Visual Basic)」を参照してください。

関連トピック

タイトル

説明

ジェネリック インターフェイスの分散 (C# および Visual Basic)

ジェネリック インターフェイスの共変性と反変性について説明し、.NET Framework のバリアント ジェネリック インターフェイスの一覧を示します。

バリアント ジェネリック インターフェイスの作成 (C# および Visual Basic)

カスタムのバリアント インターフェイスを作成する方法を示します。

ジェネリック コレクションに対するインターフェイスでの分散の使用 (C# および Visual Basic)

IEnumerable<T> インターフェイスと IComparable<T> インターフェイスにおける共変性と反変性のサポートが、コードの再利用にどのように役立つかについて説明します。

デリゲートの分散 (C# および Visual Basic)

汎用デリゲートと非汎用デリゲートの共変性と反変性について説明し、.NET Framework のバリアント汎用デリゲートの一覧を示します。

デリゲートの分散の使用 (C# および Visual Basic)

非汎用デリゲートにおける共変性と反変性のサポートを使用して、メソッド シグネチャをデリゲート型に一致させる方法について説明します。

Func および Action 汎用デリゲートでの分散の使用 (C# および Visual Basic)

Func デリゲートと Action デリゲートにおける共変性と反変性のサポートが、コードの再利用にどのように役立つかについて説明します。