创建List<IValueMapper<MyRecord>>遇CS1503错误,如何实现目标集合?
问题:如何创建包含MyMapper的List<IValueMapper>?
问题场景
现有以下接口与类定义:
public interface IValueMapper<TData>{ } public class MyMapper : IValueMapper<IMyType> { } public class MyRecord : BaseType, IMyType
尝试创建目标列表时触发编译器错误CS1503:
var mappers = new List<IValueMapper<MyRecord>>{new MyMapper() };
原因分析
C#中泛型接口默认是不变量,即IValueMapper<IMyType>和IValueMapper<MyRecord>被视为完全独立的类型,即便MyRecord实现了IMyType,也无法直接进行类型转换。
可行解决方案
方案一:将接口改为协变接口
在泛型参数前添加out关键字,把IValueMapper<TData>声明为协变接口:
public interface IValueMapper<out TData> { }
协变规则允许将泛型接口的宽泛类型(IMyType)实例转换为更具体的类型(MyRecord),此时原列表创建代码可直接正常编译。
方案二:创建适配包装类(无法修改接口时使用)
如果不能修改原接口定义,可以编写一个包装类,将MyMapper适配为IValueMapper<MyRecord>:
public class MyRecordMapperWrapper : IValueMapper<MyRecord> { private readonly MyMapper _innerMapper; public MyRecordMapperWrapper(MyMapper innerMapper) { _innerMapper = innerMapper; } // 若IValueMapper有成员方法,需在此委托给_innerMapper实现 }
之后通过包装类创建列表:
var mappers = new List<IValueMapper<MyRecord>>{ new MyRecordMapperWrapper(new MyMapper()) };
方案三:强制类型转换(不推荐)
如果IValueMapper<TData>没有任何成员方法,可通过两次强制转换绕过编译器检查,但这种方式不安全,后续接口添加成员后可能引发运行时错误:
var mappers = new List<IValueMapper<MyRecord>>{ (IValueMapper<MyRecord>)(object)new MyMapper() };
内容的提问来源于stack exchange,提问作者Maya Stern
相关产品推荐
相关产品推荐

