Ковариация и контравариация (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 и IComparable для облегчения повторного использования кода.

Вариативность в делегатах (C# и Visual Basic)

Описание использования ковариации и контравариации в универсальных и неуниверсальных методах-делегатах и приведение списка вариативных универсальных методов-делегатов в платформе .NET Framework.

Использование вариативности в делегатах (C# и Visual Basic)

Описание способа использования поддержки ковариации и контравариации в неуниверсальных методах-делегатах при сопоставлении сигнатуры метода с типами делегатов.

Использование вариативности в универсальных методах-делегатах Func и Action (C# и Visual Basic)

Описание использования поддержки ковариации и контравариации в делегатах Func и Action для повторного использования кода.