2016-07-22 76 views
3

我剛剛遇到一個有趣的問題,涉及泛型和協方差,長話短說,花了30分鐘試圖聲明一個類型,直到我放棄。C#協方差難題,我遇到

爲了清楚起見:我已經有了一個解決方法,目前不需要我的項目幫助。我只是問這個問題,因爲我是一個反常複雜的泛型類型的粉絲。如果你也是,享受。

我試圖定義此方法來獲取全局IDictionary,它通過它們的ID管理所有類型爲T的對象。 (ID僅在相同類型的對象中是唯一的)。

IDictionary<int, T> getCache<T>() where T : BaseClass { } 

爲了避免檢查TBaseClass每衍生物(其中有很多)我想定義字典的全局字典,查找正確的列表。

我想是這樣的:

Dictionary<Type, IDictionary<int, Baseclass>> allCaches; 

泛型的Expierienced用戶可能會看到的問題,此履行情況:IDictionary<TKey, TValue>接口是不是協變。

(不是協變的手段,IDictionary<int, DerivedClass>不從IDictionary<int, BaseClass>繼承。其結果是,前者的對象不能被放置在我的字典allCaches

我結束了,只是用我所有的緩存的IDictionary<int, BaseClass>,並且當我讀取它們時手動將所存儲的元素轉回。

我想知道,任何人都可以想到我的方法getCache<T>()使用最少的鑄造和不手動分支從BaseClass派生的所有類型實現的?

+1

我想你會需要依賴類型來做到這一點,而不是鑄造,所以沒有。 – Lee

回答

1

我會用一個通用的靜態類型替代提供了Dictionary<Type,T>我可以和那些單身的人一起生活。

public static class Caches 
{ 
    public static class For<T> 
    { 
     public static IDictionary<int,T> Cache{get;}=new Dictionary<int,T>(); 
    } 

    public static Set<T>(int key,T value)=> For<T>.Cache[k]=v; 
} 

// and to use the dictionary 
public void DoStuff(int i, string value){ 
    Caches.For<string>.Cache[i]=value; 
    // or if you define generic methods in Caches like Set 
    Caches.Set(i,value); 
} 

記住Class<int>Class<float>兩種不同類型的誰共享相同的泛型類型定義Class<T>

沒有爲Class<T>運行時類型,因爲它是一個開放式泛型類型,而Class<int>Class<float>關閉泛型類型爲Tony The Pony's SO answer on Open and Closed Generic Types

這就是爲什麼Class<float>Class<int>靜態成員是不同的解釋,這是兩個每當泛型參數發生變化時,都會重新定義所有成員。

+0

我不能爲我的特定問題使用單身人士,但可能會將其用於我的項目的其他部分。肯定沒有想到,謝謝你的提議。 – TheHowlingHoaschd

0

我會傾向於忽略該值的類型在你的緩存的字典「和將其丟在回:

private readonly Dictionary<Type, object> allCaches = new Dictionary<Type, object>(); 

public IDictionary<int, T> GetCache<T>() where T : BaseClass 
{ 
    object cache; 

    if (!allCaches.TryGetValue(typeof(T), out cache)) 
    { 
     cache = new Dictionary<int, T>(); 
     allCaches.Add(typeof(T), cache); 
    } 

    return (IDictionary<int, T>) cache; 
}