协变和逆变 (C#)Covariance and Contravariance (C#)

在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。In C#, covariance and contravariance enable implicit reference conversion for array types, delegate types, and generic type arguments. 协变保留分配兼容性,逆变则与之相反。Covariance preserves assignment compatibility and contravariance reverses it.

以下代码演示分配兼容性、协变和逆变之间的差异。The following code demonstrates the difference between assignment compatibility, covariance, and contravariance.

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

数组的协变使派生程度更大的类型的数组能够隐式转换为派生程度更小的类型的数组。Covariance for arrays enables implicit conversion of an array of a more derived type to an array of a less derived type. 但是此操作不是类型安全的操作,如以下代码示例所示。But this operation is not type safe, as shown in the following code example.

object[] array = new String[10];  
// The following statement produces a run-time exception.  
// array[0] = 10;  

对方法组的协变和逆变支持允许将方法签名与委托类型相匹配。Covariance and contravariance support for method groups allows for matching method signatures with delegate types. 这样,不仅可以将具有匹配签名的方法分配给委托,还可以分配与委托类型指定的派生类型相比,返回派生程度更大的类型的方法(协变)或接受具有派生程度更小的类型的参数的方法(逆变)。This enables you to assign to delegates not only methods that have matching signatures, but also methods that return more derived types (covariance) or that accept parameters that have less derived types (contravariance) than that specified by the delegate type. 有关详细信息,请参阅委托中的变体 (C#)使用委托中的变体 (C#)For more information, see Variance in Delegates (C#) and Using Variance in Delegates (C#).

以下代码示例演示对方法组的协变和逆变支持。The following code example shows covariance and contravariance support for method groups.

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 或较新的 C# 中,支持在泛型接口和委托中使用协变和逆变,并允许隐式转换泛型类型参数。In .NET Framework 4 or newer C# supports covariance and contravariance in generic interfaces and delegates and allows for implicit conversion of generic type parameters. 有关详细信息,请参阅泛型接口中的变体 (C#)委托中的变体 (C#)For more information, see Variance in Generic Interfaces (C#) and Variance in Delegates (C#).

以下代码示例演示泛型接口的隐式引用转换。The following code example shows implicit reference conversion for generic interfaces.

IEnumerable<String> strings = new List<String>();  
IEnumerable<Object> objects = strings;  

如果泛型接口或委托的泛型参数被声明为协变或逆变,该泛型接口或委托则被称为“变体”。A generic interface or delegate is called variant if its generic parameters are declared covariant or contravariant. 凭借 C#,能够创建自己的变体接口和委托。C# enables you to create your own variant interfaces and delegates. 有关详细信息,请参阅创建变体泛型接口 (C#)委托中的变体 (C#)For more information, see Creating Variant Generic Interfaces (C#) and Variance in Delegates (C#).

标题Title 描述Description
泛型接口中的变体 (C#)Variance in Generic Interfaces (C#) 讨论泛型接口中的协变和逆变,提供 .NET Framework 中的变体泛型接口列表。Discusses covariance and contravariance in generic interfaces and provides a list of variant generic interfaces in the .NET Framework.
创建变体泛型接口 (C#)Creating Variant Generic Interfaces (C#) 演示如何创建自定义变体接口。Shows how to create custom variant interfaces.
在泛型集合的接口中使用变体 (C#)Using Variance in Interfaces for Generic Collections (C#) 演示 IEnumerable<T> 接口和 IComparable<T> 接口中对协变和逆变的支持如何帮助重复使用代码。Shows how covariance and contravariance support in the IEnumerable<T> and IComparable<T> interfaces can help you reuse code.
委托中的变体 (C#)Variance in Delegates (C#) 讨论泛型委托和非泛型委托中的协变和逆变,并提供 .NET Framework 中的变体泛型委托列表。Discusses covariance and contravariance in generic and non-generic delegates and provides a list of variant generic delegates in the .NET Framework.
使用委托中的变体 (C#)Using Variance in Delegates (C#) 演示如何使用非泛型委托中的协变和逆变支持以将方法签名与委托类型相匹配。Shows how to use covariance and contravariance support in non-generic delegates to match method signatures with delegate types.
对 Func 和 Action 泛型委托使用变体 (C#)Using Variance for Func and Action Generic Delegates (C#) 演示 Func 委托和 Action 委托中对协变和逆变的支持如何帮助重复使用代码。Shows how covariance and contravariance support in the Func and Action delegates can help you reuse code.