2016-07-22 52 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; 
}