2010-04-30 97 views
1

這裏是我面對的情景:.NET 4.0泛型不變,協變,反變

public abstract class Record { } 

public abstract class TableRecord : Record { } 

public abstract class LookupTableRecord : TableRecord { } 

public sealed class UserRecord : LookupTableRecord { } 

public interface IDataAccessLayer<TRecord> 
    where TRecord : Record { } 

public interface ITableDataAccessLayer<TTableRecord> : IDataAccessLayer<TTableRecord> 
    where TTableRecord : TableRecord { } 

public interface ILookupTableDataAccessLayer<TLookupTableRecord> : ITableDataAccessLayer<TLookupTableRecord> 
    where TLookupTableRecord : LookupTableRecord { } 

public abstract class DataAccessLayer<TRecord> : IDataAccessLayer<TRecord> 
    where TRecord : Record, new() { } 

public abstract class TableDataAccessLayer<TTableRecord> : DataAccessLayer<TTableRecord>, ITableDataAccessLayer<TTableRecord> 
    where TTableRecord : TableRecord, new() { } 

public abstract class LookupTableDataAccessLayer<TLookupTableRecord> : TableDataAccessLayer<TLookupTableRecord>, ILookupTableDataAccessLayer<TLookupTableRecord> 
    where TLookupTableRecord : LookupTableRecord, new() { } 

public sealed class UserDataAccessLayer : LookupTableDataAccessLayer<UserRecord> { } 

現在,當我嘗試投UserDataAccessLayer它的通用基礎類型ITableDataAccessLayer<TableRecord>,編譯器抱怨說,它不能隱式轉換類型。

當我嘗試在通用參數界面聲明中使用inout關鍵字,編譯器會抱怨無效方差:類型參數必須是有效目不暇接。

我有以下的抽象類:

public abstract class FileProcessor : IDisposable 
{ 
    protected abstract ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer(); 
} 

和樣本的具體實現如下:

public class UserFileProcessor : FileProcessor 
{ 
      protected override ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer() 
     { 
      return new UserDataAccessLayer(); 
     } 
} 

回報新UserDataAccessLayer();是編譯器抱怨的地方。

+0

請發佈一個簡短但完整的程序來展示問題,這樣您也可以獲得具體的答案。 – 2010-04-30 09:15:54

+0

嗨Lasse,我已根據您的建議對我的帖子進行了修改。任何幫助將不勝感激。 – 2010-04-30 09:26:16

+0

我希望看到整個UserDataAccessLayer定義,所有方法,但堅持,讓我添加一個答案,然後你可以看到是否有幫助。 – 2010-04-30 09:59:43

回答

0

據我所知,如果你想使用協方差,你需要爲接口指定out關鍵字。

http://geekswithblogs.net/NewThingsILearned/archive/2009/09/30/covariance-in-.net-4.0.aspx

+0

我試着在通用接口上設置通用參數。但隨後的編譯器給了我一個不同的錯誤: 無效方差:類型參數「TTableRecord」必須是有效目不暇接......上請 – 2010-04-30 09:08:14

+0

發佈完整的錯誤消息。 – Snake 2010-04-30 09:08:39

+0

如果我將out關鍵字應用於通用ITableDataAccessLayer接口聲明中的TTableRecord通用參數,則會出現以下錯誤: 無效的方差:類型參數'TTableRecord'必須在'Csss.Data.DataAccessLayers.ITableDataAccessLayer < TTableRecord> .Delete(TTableRecord,bool)'。 'TTableRecord'是協變的。 – 2010-04-30 09:38:53

0

與合作和反方的問題是,它規定了相當多的涉及的類型的限制,所以它可能並不適用於所有情況。

我設法讓你的代碼通過進行以下修改編譯:

public interface IDataAccessLayer<out TRecord> 
    where TRecord : Record { } 

public interface ITableDataAccessLayer<out TTableRecord> : IDataAccessLayer<TTableRecord> 
    where TTableRecord : TableRecord { } 

注:

  • 出添加IDataAccessLayer和ITableDataAccessLayer

然而,這手段您不僅僅限於在這些類型的輸出位置使用TTableRecord,這意味着:

  • 類型爲只讀屬性(不寫屬性)
  • 返回類型方法
  • out參數類型的方法

您可以無法使用它:

  • 可寫屬性
  • ref或non-out/ref參數t o方法

很有可能,沒有辦法讓共同和反對方差在這裏幫助你。

+0

Hi Lasse 不起作用。向ITableDataAccessLayer添加一個方法,該方法使用類型TTableRecord作爲參數或返回類型。 – 2010-04-30 12:18:08

+0

還有什麼我可以做一個混凝土類型向基礎泛型類型? – 2010-04-30 12:34:25

+0

正如我所說,它有很多限制,我懷疑你可以做你想做的。 – 2010-04-30 13:42:56