泛型接口转换报错:IDerivedInterface无法转为IBaseInterface<IModel>求助
// model interface and implmentation public interface IModel { } public class Model : IModel{} // generic interface which constraint T from IModel public interface IBaseInterface<T> where T:IModel{ } public interface IDerivedInterface : IBaseInterface<Model>{} public class Test { void FuncTest<T>() where T:IBaseInterface<IModel> { } void CallFunc() { // error: ... see below FuncTest<IDerivedInterface>(); } }
报错信息
The type 'IDerivedInterface' must be convertible to 'IBaseInterface<IModel>' in order to use it as parameter 'T' in the generic method 'void Test.FuncTest<T>()'
用户疑问
Model实现了IModel接口,IDerivedInterface继承了IBaseInterface
核心原因是C#默认的泛型接口是不变的——哪怕Model是IModel的实现类,IBaseInterface<Model>和IBaseInterface<IModel>之间也不存在自动转换关系。
要让IBaseInterface<T>支持从IBaseInterface<Model>到IBaseInterface<IModel>的向上转换(协变),需要在定义泛型接口时用out关键字标记类型参数T,同时满足协变的核心约束:类型参数T只能作为接口方法的返回值,不能作为方法的输入参数。
修改后的IBaseInterface定义如下:
public interface IBaseInterface<out T> where T : IModel { }
修改后,IBaseInterface<Model>就能安全转换为IBaseInterface<IModel>,FuncTest<IDerivedInterface>()的调用也不会再报错。
为什么默认不支持?因为如果泛型接口允许T作为输入参数,协变会导致类型不安全。比如假设IBaseInterface<T>有方法void SetModel(T model),若允许IBaseInterface<Model>转成IBaseInterface<IModel>,就可以传入其他实现IModel的类(比如OtherModel : IModel),但实际接口实现只能处理Model类型,这会直接引发类型错误。只有当类型参数仅用于输出场景时,协变才能保证类型安全。
内容的提问来源于stack exchange,提问作者zhenghao li

