2014-09-11 17 views
3

我已經創建了一個接口和類,如下所示:需要一個通用的轉換爲它的接口

public interface IRecord 
{ 
} 
public class Person : IRecord 
{ 
} 
public class Company : IRecord 
{ 
} 
public class Contact : IRecord 
{ 
} 
public class Table<T> where T : IRecord 
{ 
} 

我也有一個靜態類來管理表。我希望能夠基於一個switch語句來獲得一個特定的表:

public class DataBase 
{ 
    public static Table<Person> Persons { get; set; } 
    public static Table<Contact> Contacts { get; set; } 
    public static Table<Company> Companies { get; set; } 

    public static Table<IRecord> GetTable(eDataType type) 
    { 
     switch (type) 
     { 
      case eDataType.company: 
       return Companies; 
      case eDataType.contact: 
       return Contacts; 
      case eDataType.person: 
       return Persons; 
     } 
     return null; 
    } 
} 

然而,回線全部拋出編譯錯誤:

Cannot implicitly convert type 'Table<Company>' to 'Table<IRecord>' 

我可以修改我的代碼返回正確的表格?

回答

3

處理此問題的一種方法是添加非泛型基類。它甚至可以是abstract,如果你想確保沒有人可以嘗試和實例化它。

public abstract class TableBase 
{ 
} 

然後,你可以有:

public class Table<T> : TableBase where T : IRecord 
{ 
} 

而現在這樣的工作:

public static TableBase GetTable(eDataType type) 
{ 
    switch (type) 
    { 
     case eDataType.company: 
      return Companies; 
     case eDataType.contact: 
      return Contacts; 
     case eDataType.person: 
      return Persons; 
    } 
    return null; 
} 
+0

謝謝,馬特,這正是我一直在尋找的! – 2014-09-11 06:55:47

6

你不能這樣做,因爲Table<Company>不是Table<IRecord>,即使Company執行IRecord。這是因爲Table<T>不是covariant(無論如何,類不能是協變的,只有接口和委託可以)。

爲了解釋原因,我們假設您的Table<T>類具有Insert(T record)方法;如果您能夠將Table<Company>視爲Table<IRecord>,則可以在表中插入PersonContact,這顯然是不正確的。

現在,問題是,你將如何使用返回的表嗎?如果你只打算讀它,你可以定義一個接口協變像這樣:

public interface ITable<out T> where T : IRecord 
{ 
} 

然後讓Table<T>實現此接口,並更改GetTable返回ITable<IRecord>而不是Table<IRecord>

請注意,接口在輸出位置只能有T(即不能有,例如,有一個方法以T作爲參數),或者它不會被允許是協變的。

相關問題