2015-01-26 37 views
2

我遇到了創建查詢類的通用列表的問題。這些查詢類是從具有自引用類型約束的基本抽象泛型類派生的。C#具有自引用約束的通用抽象類

的剝離下來基類和派生類有:

public abstract class AbstractQuery<TQuery, TResult> 
    where TQuery : AbstractQuery<TQuery, TResult> 
{ 
    public IEnumerable<TResult> Query() 
    { 
     return new List<TResult>(); 
    } 
} 

public class FirstQuery : AbstractQuery<FirstQuery, object> { } 

public class SecondQuery : AbstractQuery<SecondQuery, object> { } 

應用程序代碼要在每個創建這些查詢的列表並執行查詢的方法,如:

 var queryList = new List<AbstractQuery<AbstractQuery, object>> 
      { 
       new FirstQuery(), 
       new SecondQuery() 
      }; 

     foreach (var query in queryList) 
     { 
      query.Query(); 
     } 

這部分不會生成,因爲List類型當然是無效的。所以我的問題是我可以使用什麼類型的列表讓這個代碼正常工作?

作爲一個方面說明,我們通過添加一個IQuery接口和AbstractQuery實現的Query方法簽名來解決這個問題,但仍然想知道最初的方式是否可行。是的,在實際代碼中有自我引用約束的原因 - 它需要一些反射代碼。

回答

5

您試圖將AbstractQuery<TQuery, TResult>視爲與TQuery共協變。關於泛型參數,類不能是協變的。只有接口(甚至在那種情況下,只有在某些情況下)才允許它們的通用參數變體(協變或逆變)。這就是爲什麼它可以工作,如果你使用接口,而不是抽象類。