繁体   English   中英

创建通用类型的字典

[英]Creating Dictionaries of generic types

在我的示例中,我有许多类( OrangePearApple等等),它们扩展了基类Fruit

我正在创建一个模型类,其中包含映射到其整数id的每种Fruit字典。 我想避免做很多这样的字段变量:

Dictionary<int, Orange> _oranges = new Dictionary<int, Orange>();

我以为我可以创建一个“通用”字典,在其中将其他字典映射到Fruit类型:

Dictionary<Type, Dictionary<int, Fruit>> _fruits = new Dictionary<Type, Dictionary<int, Fruit>>();

要插入此结构中,我使用如下方法:

public void Insert(Fruit fruit)
{
    _fruits[fruit.GetType()][fruit.Id] = fruit;
}

当我尝试检索存储的值时出现问题,如下所示:

public IEnumerable<T> GetFruits<T>() where T : Fruit
{
    return (IEnumerable<T>) _fruits[typeof(T)].Values.ToArray();
}

这将被称为GetFruits<Orange>() 强制转换失败,并显示以下错误:

System.InvalidCastException:'无法将类型为'Example.Fruit []'的对象转换为类型为'System.Collections.Generic.IEnumerable`1 [Example.Orange]'。

我该怎么做?

我认为您只需要使用Cast<T>

return _fruits[typeof(T)].Values.Cast<T>();

使用(IEnumerable<T>)进行强制转换不起作用,因为它将强制转换整个内容。 您可能已经知道这一点: List<object>无法转换为List<int> 同样的现象在这里发生。

因此,我们应该使用Cast<T> 此方法会将可枚举的每个元素转换为指定的类型,并返回结果可枚举。

您可以使用OfType方法:

var _fruits = new Dictionary<Type, Dictionary<int, Fruit>>();

public IEnumerable<T> GetFruits<T>() where T : Fruit
{
    return _fruits.OfType<T>().ToArray();
}

为什么你的错误是因为类型的原因Values在最里面的字典_fruits天生就是地图的基类的Fruit

Dictionary<int, Fruit>

具体来说, Values属性定义为ICollection<T>

在运行时,不允许您直接将ValuesIEnumerable<T>ICollection<Fruit> ,例如IEnumerable<Orange>

要解决此问题,您将需要有效地遍历Values集合并按类型向下转换(可能还进行过滤)。

(即使您“知道”您的代码仅允许Oranges进入fruits[typeof(Orange)]字典中,但从类型系统的角度来看,类型仍为ICollection<Fruit>

根据其他答案,您可以使用多种方法进行此转换和过滤:

  • 已过滤的foreach, foreach(T item in Values)
  • .Cast<T> -但是,如果以某种方式找到其他水果,则将抛出该错误
  • .OfType<T> -这将排除类型错误的项目。

这里讨论了这些方法的更多细节

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM