2013-06-30 48 views
0

爲什麼下面的代碼會引發編譯錯誤?根據C#4.0協方差應該不允許這樣的轉換。 列表employeeList = managerList;C#中的協變編譯錯誤

class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Manager> managerList = new List<Manager>() 
      { 
       new Manager{ FirstName="ASFD", LastName="DSS", NoOfReportees=4}, 
       new Manager{ FirstName="rrr", LastName="dsasde", NoOfReportees=22} 
      }; 
      List<Employee> employeeList = managerList; 
     } 
    } 
    public class Employee 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
    } 
    public class Manager:Employee 
    { 
     public int NoOfReportees { get; set; } 
    } 
+0

只有接口才允許協方差。 '列表'沒有界面。 'IList '既不是共變體也不是反變體,因爲你必須讀寫元素。 –

+0

'列表'不是什麼需要成爲一個接口。試着讓員工執行IPerson –

+0

我想我對協方差有一個錯誤的理解。讓我看看我是否得到了一些很好的教程 – ckv

回答

2

想想這樣說:如果作業被允許,你可以這樣做:

List<Manager> managerList = new List<Manager>() 
{ 
    new Manager{ FirstName="ASFD", LastName="DSS", NoOfReportees=4}, 
    new Manager{ FirstName="rrr", LastName="dsasde", NoOfReportees=22} 
}; 
List<Employee> employeeList = managerList; 
employeeList.Add(new Employee{ FirstName = "John", LastName = "Doe"}); 

和現在您的managerList將包含一個不是Manager的項目,違反了列表的約束條件。

如果它會滿足您的需求,你可以,但是,這樣做:

List<Employee> employeeList = new List<Employee>(managerList); 

,因爲它不違反原始列表。

0

List<T>是不變的。你需要IEnumerable<T>這是covariant

請參閱解釋here通過Eric Lippert與動物園的比喻解釋得這麼好 -

一個List<Mammal>不能轉換爲List<Animal>因爲你 可以把一個蜥蜴成動物名單。 A List<Mammal>不能被 轉換爲List<Giraffe>,因爲 列表中可能有一隻老虎。

因此List<T>必須是不變的在T.

然而,List<Mammal>可以轉換爲IEnumerable<Animal>(作爲 C#4.0),因爲存在對IEnumerable<Animal>沒有方法,增加了一個 蜥蜴。 IEnumerable<T>在T中是協變的。

0

協變接口必須使用out關鍵字明確聲明。如果您使用的是.NET 4.5,有IReadOnlyCollection<T>接口

IReadOnlyCollection<Employee> employeeList = managerList; 

指出的是,這是合乎邏輯的,因爲我們可以閱讀List<Manager>Employee但我們不能添加Employee它只讀的。

+0

不僅僅是'IReadOnlyCollection ',甚至還有一個['IReadOnlyList](http://msdn.microsoft.com/en-us/library/hh192385.aspx)在它的類型論證中是協變的。 –