为何无法将实现具体泛型接口的类型转换为IService<IMarker>?
错误原因
- 泛型接口默认不变:
IService<T>未声明协变特性,即便ResultA是IMarker的实现类,IService<ResultA>也无法隐式转换为IService<IMarker>。C#泛型接口默认是不变的,只有显式声明协变(out)或逆变(in)后,才能支持特定方向的类型转换。 - 返回类型不支持协变:即使给接口添加协变标记,
List<T>作为可变集合(支持增删元素)也不满足协变的输出安全要求,无法直接用于协变接口的返回值。
解决办法
1. 将IService<T>改为协变接口,替换返回类型为协变集合
给IService<T>的类型参数添加out关键字标记协变,同时把返回类型从List<T>改为IEnumerable<T>(IEnumerable<T>是支持协变的只读集合接口):
public interface IService<out T> where T : IMarker { public IEnumerable<T> DoStuff(); }
2. 适配实现类的返回类型
所有实现IService<T>的类,将DoStuff的返回类型改为IEnumerable<T>,实际返回仍可使用List<T>(因为List<T>实现了IEnumerable<T>):
public class CatService : ICatService { public IEnumerable<ResultA> DoStuff() { return new List<ResultA>(); } } public class DogService : IDogService { public IEnumerable<ResultB> DoStuff() { return new List<ResultB>(); } }
3. 修正Dog类的构造函数参数
Dog类构造函数错误传入了ICatService,应改为对应IDogService:
public class Dog : Animal { public Dog(IDogService svc) : base(svc) { } }
4. 保持原有依赖注册逻辑
services.AddTransient<ICatService, CatService>(); services.AddTransient<IDogService, DogService>();
修改后,ICatService(即IService<ResultA>)即可隐式转换为IService<IMarker>,编译错误会被解决,同时保留了各接口的独立性。
内容的提问来源于stack exchange,提问作者TryHard
相关产品推荐
相关产品推荐

