泛型继承和转换
本文关键字:转换 继承 泛型 | 更新日期: 2023-09-27 18:33:20
我有以下类:
class Item { }
class MeetingItem : Item { }
class ItemGroup<T> { }
现在,这可以毫无问题地工作:
Item something;
something = new MeetingItem();
但是,这将失败:
ItemGroup<Item> itemGroup;
itemGroup = new ItemGroup<MeetingItem>(); // Fails here
我收到"无法隐式转换类型'ItemGroup<MeetingItem>
'到'ItemGroup<Item>
'"错误。 这不正是我上面正在做的事情(将某些内容分配给类型项目,然后实例化到会议项目(?
我最终将拥有的是 ItemGroup 类中的 Items 集合以及其他一些成员。 然后,我将拥有一个包含不同类型的派生项的项组集合。 理想情况下,我希望将 Item 作为一个抽象类(也许是一个接口,我可能需要根据我需要实现的内容将其保留为类(。
我对任何重构想法都持开放态度。
谢谢。
编辑以添加我的解决方案,而无需通用项组:我决定放弃泛型...有点... 我拼凑了这个:
public class ItemGroup {
public Type ItemType => this.Items.GetType().GetGenericArguments()[0];
public IList Items { get; set; }
public ItemGroup(Type itemType) {
var genericListType = typeof(List<>).MakeGenericType(itemType);
Items = (IList)Activator.CreateInstance(genericListType);
}
}
所以,我现在可以做这样的事情:
List<ItemGroup> groups = new List<ItemGroup>();
groups.Add(new ItemGroup(typeof(MeetingItem));
然后我可以通过以下方式测试特定的项目类型:
groups[0].ItemType == typeof(MeetingItem)
这似乎有点笨拙,但它有效。 我有点担心 ItemType 属性的性能,并且我对任何重构想法都持开放态度。
这是一个方差问题。
考虑一个简单的界面,如下所示:
interface MyInterface<T>
{
T GetStuff();
void SetStuff(T value);
}
现在,你有MyInterface<A>
和MyInterface<B>
,其中B
继承自A
。
返回B
而不是A
总是安全的。但是,返回A
而不是B
是不安全的。因此,从GetStuff
来看,应该可以将MyInterface<B>
投射到MyInterface<A>
,但反之则不然。
通过B
而不是A
总是安全的。但是,通过A
而不是B
是不安全的。因此,从SetStuff
来看,应该可以将MyInterface<A>
投射到MyInterface<B>
,但反之则不然。
问题应该是显而易见的——你不能同时满足两者。这两种方法都没有安全转换。
如果可以避免在单个界面中同时存在这两种方式,则可以使用 out
/in
关键字来指定接口支持哪种方差,仅此而已。查看 .NET 框架中的类:
IEnumerable<object> enumerable = Enumerable.Empty<string>(); // Safe,
// enumerable is covariant
ICollection<object> collection = new Collection<string>(); // Error,
// collection isn't covariant
Func<object> func = () => "Hi!"; // Safe, Func<T> is covariant
Action<object> func = (string val) => { ... }; // Error, Action<T> isn't covariant
另一方面,逆变
:Func<string> func = () => new object(); // Error, Func<T> isn't contravariant
Action<string> func = (object val) => { ... }; // Safe, Action<T> is contravariant