使用泛型接口实现工厂方法时出现类型转换错误如何解决?
问题根因
报错是C#泛型的不变性规则导致的,和你选用的工厂模式没有关系。默认情况下泛型接口的类型参数是不变的,即使ItemPicture是Item的子类,IItemManager<ItemPicture>也不会被识别为IItemManager<Item>的子类,直接强制转换就会抛出类型不匹配异常。
修复步骤
1. 给泛型接口添加协变修饰符
你的IItemManager<T>只有返回T类型的方法,没有接收T作为输入参数的逻辑,完全符合协变的使用条件,给类型参数加上out修饰符声明协变即可:
// 注意统一接口名为IItemManager<T>,你原代码定义时漏了I前缀 public interface IItemManager<out T> { IList<T> FGetByGroup(string idgroup); }
2. 修正代码笔误
你原代码里还有两处笔误,不修正会触发其他编译错误:
ItemManagerPictures类中FGetByGroup方法的返回值类型IList<ItemFoto>应为IList<ItemPicture>,和接口约束的类型一致- 泛型管理器接口定义和实现、调用的名称要统一,都用
IItemManager<T>
3. 原有逻辑直接可用
添加协变修饰符后,IItemManager<ItemPicture>和IItemManager<ItemVideo>就可以安全转换为IItemManager<Item>类型,你写的工厂类转换逻辑、控制器调用逻辑都可以按预期运行,不需要额外改动。
扩展场景处理
如果后续你需要给IItemManager<T>添加接收T作为输入参数的方法(比如void Add(T item)),就无法使用协变,此时可以用非泛型基础接口的方案实现:
- 定义非泛型基础接口
IItemManager,声明返回IList<Item>的FGetByGroup方法 - 泛型
IItemManager<T>继承该非泛型接口,显式实现非泛型的方法 - 工厂返回非泛型
IItemManager类型,即可直接调用
内容的提问来源于stack exchange,提问作者Alex Nungon
相关产品推荐
相关产品推荐

