泛型接口与类的向上转型失效问题求助
解决泛型向上转型的协变问题
这是个很常见的泛型协变坑点!默认情况下C#的泛型接口是不变的——哪怕Square是IShape的实现类,MyObject<Square>和IObject<IShape>之间也没有默认的类型兼容关系,所以你直接赋值会报错。不过不用强制转换,我们只需要给泛型接口加个小修饰就能搞定。
核心解决方案:给接口添加协变修饰符out
你的IObject<T>接口里只有一个只读的Value属性,没有任何需要传入T类型参数的成员(比如setter、接受T的方法),完全满足协变的使用条件。只需要把接口改成这样:
public interface IObject<out T> { T Value { get; } }
为什么这能解决问题?
协变(用out标记泛型参数)的作用就是允许你把派生类型的泛型实例赋值给基类型的泛型接口——简单说就是支持你想要的那种向上转型,而且是安全的,因为接口只会向外输出T类型的值,不会接收输入,不会有类型安全问题。
验证修改后的代码
现在你原来的两段赋值代码都能直接正常运行,不需要任何强制转换:
// MyObject的情况 var square = new Square(5); IObject<IShape> gShape = new MyObject<Square>(square); // SquareObject的情况 IObject<IShape> shapeObj = new SquareObject(square);
额外说明
- 协变只能用在泛型接口和泛型委托上,普通泛型类没法直接标记协变,所以我们修改的是
IObject<T>接口而不是MyObject<T>类 - 如果你的接口里有接受
T作为参数的成员(比如void SetValue(T value)),那协变就不适用了,这时候可能要考虑逆变或者其他设计方式
内容的提问来源于stack exchange,提问作者Saadi
相关产品推荐
相关产品推荐

