C#中从特定泛型子类型转换为通用泛型父类型的问题
你尝试将实现了IParent<AChild>的Child类实例,赋值给IParent<AParent>类型的变量,示例代码如下:
public class AParent { } public class AChild : AParent { } public interface IParent<T> { public void func(T input); } public class Child : IParent<AChild> { public void func(AChild input) { } } public static void test() { IParent<AParent> parent = new Child(); // 编译报错 }
编译时收到错误提示:
Cannot implicitly convert type 'Child' to 'IParent
'. An explicit conversion exists (are you missing a cast?)
你尝试给泛型参数T添加in/out关键字但未解决问题,下面解释核心原因和可行方案:
为什么默认不可行?
这个转换被编译器阻止,是类型安全的强制要求。假设允许这种隐式转换,你可以通过parent变量调用func(new AParent()),但实际Child类的func只能接收AChild类型的参数——AParent是AChild的父类,无法直接转换为AChild,这会导致运行时类型错误,因此编译器提前拦截了这个风险。
关于in/out关键字的正确用法
你之前尝试的in/out是泛型接口的方差修饰符,但用错了方向:
out T(协变):要求T只出现在输出位置(比如方法返回值),此时允许将IParent<子类>隐式转换为IParent<父类>——因为返回子类的方法,必然能返回父类类型。in T(逆变):要求T只出现在输入位置(比如方法参数),此时允许将IParent<父类>隐式转换为IParent<子类>——因为能处理父类的方法,必然能处理子类。
你的场景中,T只出现在输入位置,所以in T的逆变规则不支持你要的IParent<AChild>转IParent<AParent>,反而支持反向转换。
可行的解决方案
调整接口设计(推荐)
如果业务逻辑允许,把T放到输出位置,使用协变:public interface IParent<out T> { public T func(); } public class Child : IParent<AChild> { public AChild func() { return new AChild(); } } public static void test() { IParent<AParent> parent = new Child(); // 此时可以正常编译 }显式强制转换(不推荐)
如果你确定不会调用func传入非AChild类型的参数,可以用显式转换,但这会放弃编译器的类型检查,带来运行时风险:public static void test() { IParent<AParent> parent = (IParent<AParent>)new Child(); // 注意:如果调用parent.func(new AParent()),会抛出InvalidCastException }添加泛型参数约束
如果IParent<T>的T可以限制为AParent的子类,可以在接口定义时添加约束,缩小类型范围(但无法直接解决转换问题):public interface IParent<T> where T : AParent { public void func(T input); }
内容的提问来源于stack exchange,提问作者Montana

