在 C# 中,協變和逆變可以實現數組類型、委託類型和泛型類型參數的隱式引用轉換。 協變保留分配兼容性,逆變則與之相反。html
如下代碼演示分配兼容性、協變和逆變之間的差別。api
// 分配兼容性. string str = "test"; // 將派生類型更高的對象分配給派生類型更低的對象 object obj = str; IEnumerable<string> strings = new List<string>(); // 用派生類型參數實例化的對象被分配給用派生類型參數實例化的對象。// 分配兼容性保持不變。 IEnumerable<object> objects = strings; // 逆變. // 假設如下方法在類中:static void SetObject(object o) { } Action<object> actObject = SetObject; // 使用派生程度較低的類型參數實例化的對象被分配給使用派生程度較高的類型參數實例化的對象。// 分配兼容性被反轉. Action<string> actString = actObject;
對方法組的協變和逆變支持容許將方法簽名與委託類型相匹配。 這樣,不只能夠將具備匹配簽名的方法分配給委託,還能夠分配與委託類型指定的派生類型相比,返回派生程度更大的類型的方法(協變)或接受具備派生程度更小的類型的參數的方法(逆變)。 有關詳細信息,請參閱委託中的變體 (C#) 和使用委託中的變體 (C#)。數組
如下代碼示例演示對方法組的協變和逆變支持。app
static object GetObject() { return null; } static void SetObject(object obj) { } static string GetString() { return ""; } static void SetString(string str) { } static void Test() { // 協變. 委託將返回類型指定爲對象,但能夠指定返回字符串的方法。 Func<object> del = GetString; // 逆變. 委託將參數類型指定爲字符串,但能夠指定接受對象的方法。 Action<string> del2 = SetObject; }
在 .NET Framework 4 或較新的 C# 中,支持在泛型接口和委託中使用協變和逆變,並容許隱式轉換泛型類型參數。 有關詳細信息,請參閱泛型接口中的變體 (C#) 和委託中的變體 (C#)。《C#4.0新增功能03 泛型中的協變和逆變》ide
如下代碼示例演示泛型接口的隱式引用轉換。ui
IEnumerable<String> strings = new List<String>(); IEnumerable<Object> objects = strings;
若是泛型接口或委託的泛型參數被聲明爲協變或逆變,該泛型接口或委託則被稱爲「變體」。 憑藉 C#,可以建立本身的變體接口和委託。 有關詳細信息,請參閱建立變體泛型接口 (C#) 和委託中的變體 (C#)。spa
Title | 說明 |
---|---|
泛型接口中的變體 (C#) | 討論泛型接口中的協變和逆變,提供 .NET Framework 中的變體泛型接口列表。 |
建立變體泛型接口 (C#) | 演示如何建立自定義變體接口。 |
在泛型集合的接口中使用變體 (C#) | 演示 IEnumerable<T> 接口和 IComparable<T> 接口中對協變和逆變的支持如何幫助重複使用代碼。 |
委託中的變體 (C#) | 討論泛型委託和非泛型委託中的協變和逆變,並提供 .NET Framework 中的變體泛型委託列表。 |
使用委託中的變體 (C#) | 演示如何使用非泛型委託中的協變和逆變支持以將方法簽名與委託類型相匹配。 |
對 Func 和 Action 泛型委託使用變體 (C#) | 演示 Func 委託和 Action 委託中對協變和逆變的支持如何幫助重複使用代碼。 |