2011-01-27 57 views
0

比方說,我已經被存儲在具有基於對象的不同實現以下類:類型參數,約束和協方差/逆變

public class ListOfPersistent<T> : 
    IList<T> where T : Persistent {... implementation ...} 

public class ListOfNonPersistent<T> : 
    IList<T> {... implementation ...} 

而且我想在上面使用的另一個版本一個班做這樣的事情:

public class PersistentList<T> : IList<T> { 
    protected PersistentList() { 
    if (list != null) { 
     return; 
    } 

    if (Extensions.IsPersistent<T>()) { 
     list = new ListOfPersistent<T>(); 

    } else { 
     list = new ListOfNonPersistent<T>(); 
    } 
    } 

    protected IList<T> list; 
    .... 
} 

當然上面沒有編譯,因爲限制第一級,沒有第二類型。有什麼辦法可以:告訴編譯器它不應該檢查這個特定情況下的約束(list = new ListOfPersistent<T>()),因爲我知道它會是這種類型的,或者做一些協變/逆變魔術,所以代碼編譯沒有任何問題?

回答

1

協變和逆變將不會幫助你,因爲IList<T>是不變的。

我個人認爲你的班級設計存在缺陷。您不應該想要實例化一個ListOfPersistent<T>,然後將其放置在類型爲IList<T>的變量不兼容的變量中。不幸的是,我不能提出一個好的選擇,因爲我不知道你打算如何使用這些課程或你的總體目標是什麼;但我可以讓一個建議,並聲明這是哈克和也許應該,如果你真的知道你在做什麼,只能用於:

public static class ListUtils 
{ 
    public static object CreateListOfPersistent(Type elementType) 
    { 
     if (!typeof(Persistent).IsAssignableFrom(elementType)) 
      throw new ArgumentException("elementType must derive from Persistent.", "elementType"); 
     var listType = typeof(ListOfPersistent<>).MakeGenericType(elementType); 
     return Activator.CreateInstance(listType); 
    } 
} 

// ... 

if (Extensions.IsPersistent<T>()) 
    list = (IList<T>) ListUtils.CreateListOfPersistent(typeof(T)); 
else 
    list = new ListOfNonPersistent<T>(); 
+0

兩個班做同樣的事情,但由於內工作是完全不同的,其中一個取決於類型是持久性的,這就是爲什麼有兩個類。當然,如果......在其中一門課上,我可以做很多事情,但這很難保持,並且不是很快。基本上,PersistentList只是一個裝飾器,因爲它沒有任何功能,只是使用IList的下劃線功能,這又取決於T的類型是否爲Persistent,需要兩種不同的實現。 – CheloXL 2011-01-28 01:58:17