CLR枚举如何实现泛型向下转换?自定义类型能否复刻该逻辑?
问题解答
1. List支持转换的原因
List<T>能实现这种转换,核心原因是**IEnumerable<T>是协变泛型接口**。
在C#中,泛型接口如果用out关键字标记类型参数,就支持协变:当MyResultObject实现了IMyResultObject时,IEnumerable<MyResultObject>可以直接隐式转换为IEnumerable<IMyResultObject>。CLR内置的IEnumerable<T>定义如下:
public interface IEnumerable<out T> : IEnumerable { // 接口成员 }
List<T>实现了IEnumerable<T>,因此继承了这种协变能力,所以能直接完成类型转换。
2. 为自定义类型实现相同逻辑的方法
要让IEnumerableSubset<T>支持协变转换,只需将其定义为协变泛型接口,给类型参数添加out关键字:
public interface IEnumerableSubset<out T> : IEnumerable<T> { int Total { get; } }
修改后,IEnumerableSubset<MyResultObject>就能直接隐式转换为IEnumerableSubset<IMyResultObject>,之前的编译错误会自动消失。
关键注意点
- 协变接口的类型参数只能用于输出位置:比如方法返回值、只读属性类型,不能用于方法参数、可写属性类型。你的
IEnumerableSubset<T>只有只读的Total属性,且继承的IEnumerable<T>本身是协变的,完全满足协变要求。 ListSubset<T>无需额外修改,只要它实现了协变接口,就自动支持对应的类型转换。
内容的提问来源于stack exchange,提问作者GreysonTyrus
相关产品推荐
相关产品推荐

