强制转换和泛型约束
本文关键字:泛型 约束 转换 | 更新日期: 2023-09-27 18:22:23
我有这个事件类:
sealed class AnEvent : EventArgs
{
IEnumerable<ItemWrapper<AnAbstractClass>> Items { get; set; }
}
这是这样用的:
class ItemsProcessor
{
delegate void OnItemsProcessedHandler(object sender, AnEvent e);
event OnItemsProcessedHandler OnItemsProcessed;
//...
}
我使用这个包装类:
sealed class ItemWrapper<T>
where T: AnAbstractClass
{
T Item { get; set; }
Metadata Metadata { get; set; }
ItemWrapper(T item, Metadata metadata)
{
Item = item;
Metadata = metadata;
}
}
我在ItemsProcessor
课上有这个方法:
internal void DoSomethingWithList<T>(IEnumerable<T> items)
where T: AnAbstractClass, new()
{
IEnumerable<ItemWrapper<T>> processedItems = WrapItems<T>(items);
OnItemsProcessed(this, new AnEvent() { Items = processedItems }); //error here
}
问题出在此代码示例的最后一行;当我尝试使用本地IEnumerable
设置属性Items
AnEvent
时。编译器拒绝继续告诉我它不能隐式地将IEnumerable<ItemWrapper<T>>
转换为IEnumerable<ItemWrapper<AnAbstractClass>>
。我认为应该没问题,因为我为此方法添加了约束where T: AnAbstractClass, new()
,但即使显式强制转换(使用带括号的经典强制转换或使用Convert<>
(,我也得到了一个InvalidCastException
。
我目前对方法DoSomethingWithList
的解决方法是:
var temp = processedItems.Select(x =>
{
return new ItemWrapper<AnAbstractClass>(x.Item, x.Metadata);
});
OnItemsProcessed(this, new AnEvent() { Items = temp });
所以它现在工作正常,但我想知道为什么如果不使用这个必须迭代列表中所有项目的LINQ
转换,它就不能工作?对我来说很明显,您应该能够毫无错误地转换它,因为我添加了约束,即使使用显式强制转换以使编译器接受我的代码,也会引发异常......任何人都可以指出我这里出了什么问题?
abstract class AnAbstractClass
{
}
class ItemClass : AnAbstractClass
{
}
如果您想尝试,可以轻松复制粘贴的WrapItems
快速实现:
IEnumerable<ItemWrapper<T>> WrapItems<T>(IEnumerable<T> items)
where T : AnAbstractClass, new()
{
List<ItemWrapper<T>> ret = new List<ItemWrapper<T>>();
foreach (var item in items)
{
ret.Add(new ItemWrapper<T>(item, new Metadata()));
}
return ret;
}
如果将ItemWrapper
更改为
sealed class ItemWrapper
{
AnAbstractClass Item { get; set; }
Metadata Metadata { get; set; }
ItemWrapper(AnAbstractClass item, Metadata metadata)
{
Item = item;
Metadata = metadata;
}
}
你失去了什么?