2016-07-22 12 views
3

ジェネリックスと共分散に関する興味深い問題が発生しました。長いストーリーは短いので、私があきらめるまでタイプを宣言しようと30分を要しました。C#共変動パズル、私は遭遇しました

わかりやすく:私はすでにこの問題の回避策を持っており、現在私のプロジェクトには助けが必要ありません。私は不思議な複雑なジェネリック型のファンなので、この質問をしました。あなたもそうなら、お楽しみください。

のすべてのオブジェクトをIDで管理するグローバルIDictionaryをフェッチするために、このメソッドを定義しようとしていました。 (IDは同じタイプのオブジェクト間で一意です)。

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

BaseClassの全ての誘導体について Tをチェックしないようにするには、私は正しいリストをルックアップするために、辞書のグローバル辞書を定義したい(その多くがあります)。

私はこのような何かを試してみました:ジェネリック医薬品の

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

Expieriencedユーザーがこの実装に問題が表示される場合がありますIDictionary<TKey, TValue>インタフェースは共変ではありません。

(未共変手段、IDictionary<int, DerivedClass>IDictionary<int, BaseClass>から継承されません。その結果、前者のタイプのオブジェクトは、私の辞書allCachesに配置することはできません)

私は、ちょうどすべての私のキャッシュのためIDictionary<int, BaseClass>を使用して、終わりました私がそれらを読むとき、記憶された要素を手動でキャストバックする。

最小のキャスティングを使用し、BaseClassから派生したすべてのタイプに対して手動で分岐しない、私のメソッドgetCache<T>()の実装について誰も考えることができますか?

+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>を共有する2つの異なるタイプであることを忘れないでください。 Tony The Pony's SO answer on Open and Closed Generic Types

Class<float>Class<int>の静的メンバが異なっている理由ですで説明したように汎用型を閉じているClass<int>Class<float>に対し、オープンジェネリック型であるよう

Class<T>などの一切実行時の型はありませんが、これらは2つですジェネリックパラメータが変更されるたびにすべてのメンバを再定義する別個のクラス

+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; 
} 
関連する問題