[英]Creating Dictionaries of generic types
在我的示例中,我有许多类( Orange
, Pear
, Apple
等等),它们扩展了基类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>
。
在运行时,不允许您直接将Values
为IEnumerable<T>
的ICollection<Fruit>
,例如IEnumerable<Orange>
。
要解决此问题,您将需要有效地遍历Values
集合并按类型向下转换(可能还进行过滤)。
(即使您“知道”您的代码仅允许Oranges
进入fruits[typeof(Orange)]
字典中,但从类型系统的角度来看,类型仍为ICollection<Fruit>
)
根据其他答案,您可以使用多种方法进行此转换和过滤:
foreach(T item in Values)
.Cast<T>
-但是,如果以某种方式找到其他水果,则将抛出该错误 .OfType<T>
-这将排除类型错误的项目。 这里讨论了这些方法的更多细节
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.