C#2.0新增功能06 協變和逆變

  • 2019 年 10 月 4 日
  • 筆記

在 C# 中,協變和逆變能夠實現數組類型、委託類型和泛型類型參數的隱式引用轉換。 協變保留分配兼容性,逆變則與之相反。

以下程式碼演示分配兼容性、協變和逆變之間的差異。

// 分配兼容性.  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#)

以下程式碼示例演示對方法組的協變和逆變支援。

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 泛型中的協變和逆變》

以下程式碼示例演示泛型介面的隱式引用轉換。

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

如果泛型介面或委託的泛型參數被聲明為協變或逆變,該泛型介面或委託則被稱為「變體」。 憑藉 C#,能夠創建自己的變體介面和委託。 有關詳細資訊,請參閱創建變體泛型介面 (C#)委託中的變體 (C#)

相關主題

Title

說明

泛型介面中的變體 (C#)

討論泛型介面中的協變和逆變,提供 .NET Framework 中的變體泛型介面列表。

創建變體泛型介面 (C#)

演示如何創建自定義變體介面。

在泛型集合的介面中使用變體 (C#)

演示 IEnumerable<T> 介面和 IComparable<T> 介面中對協變和逆變的支援如何幫助重複使用程式碼。

委託中的變體 (C#)

討論泛型委託和非泛型委託中的協變和逆變,並提供 .NET Framework 中的變體泛型委託列表。

使用委託中的變體 (C#)

演示如何使用非泛型委託中的協變和逆變支援以將方法簽名與委託類型相匹配。

對 Func 和 Action 泛型委託使用變體 (C#)

演示 Func 委託和 Action 委託中對協變和逆變的支援如何幫助重複使用程式碼。