C# Covariance puzzle,我遇到过

标签 c# generics covariance

我刚刚遇到一个关于泛型和协变的有趣问题,长话短说,我花了 30 分钟尝试声明一个类型,直到我放弃。

为了清楚起见:我已经有了解决方法,目前不需要我的项目帮助。我之所以问这个问题是因为我是异常复杂的泛型类型的粉丝。如果您也是,那就尽情享受吧。

我试图定义这个方法来获取全局 IDictionary ,它管理所有 T 类型的对象通过他们的 ID。 (ID 仅在相同类型的对象之间是唯一的)。

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

避免检查T对于 BaseClass 的每个导数(其中有很多)我想定义一个全局词典词典,以查找正确的列表。

我试过这样的:

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

有经验的 Generics 用户可能会发现此实现的问题:IDictionary<TKey, TValue>接口(interface)不是协变的。

(非协变意味着,IDictionary<int, DerivedClass> 不继承自 IDictionary<int, BaseClass> 。因此,前一种类型的对象不能放入我的字典 allCaches )

我最终只使用了 IDictionary<int, BaseClass>对于我所有的缓存,并在我读取它们时手动回退存储的元素。

我想知道,谁能想到我的方法的实现 getCache<T>()它使用最少的转换并且不会手动分支所有派生自 BaseClass 的类型?

最佳答案

我会使用通用静态类型来代替 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>是不同的,它们是两个不同的类,每次通用参数更改时都会重新定义它们的所有成员。

关于C# Covariance puzzle,我遇到过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38529852/

相关文章:

java - 有没有办法使用类变量创建泛型实例?

arrays - Swift:扩展 [<SomeType<T>?] 来生成 [<T>?] 可能吗?

c# - 将子类的枚举器强制转换为父类的枚举器是否错误?

c# - 简单队列算法

c# - 实现包含抽象/接口(interface)类型参数的抽象/接口(interface)方法

java - 泛型树,自界泛型

c++ - 在其派生类中更改基类方法的返回类型

c# - 如何覆盖子类中抽象类中成员的类型

c# - 更改字符串颜色

c# - 找不到引用 RibbonComboBox 的绑定(bind)源