疑问:.NET 8/C#协变泛型接口是否存在方法调用错误?
这是否属于.NET 8/C#的BUG?
以下代码在.NET 8/C#中运行时出现不符合预期的结果:
internal class Program { interface IGetString { string GetString(); } class A : IGetString { public string GetString() => "A"; } class B : IGetString { public string GetString() => "B"; } interface ICreate<out T> { T Create(); } class C : ICreate<A>, ICreate<B> { A ICreate<A>.Create() { return new A(); } B ICreate<B>.Create() { return new B(); } } static string X(ICreate<IGetString> creator) { return creator.Create().GetString(); } static void Main() { ICreate<B> createB = new C(); var s = X(createB); Console.WriteLine("Result: " + s); } }
问题详情
- 预期输出:
B - 实际输出:
A - 异常行为:变量
createB被显式声明为ICreate<B>类型,但调用X(createB)时,实际执行的是类C中第一个实现的接口ICreate<A>的Create方法;若调换C类的接口实现顺序(如改为class C : ICreate<B>, ICreate<A>),输出结果会变为B。 - 不合理之处:编译器未在无法明确绑定目标接口方法时触发编译错误,而是默认选择类中首个实现的同构接口方法,完全违背开发者的直觉预期。
临时解决方案
改用泛型约束版本的X方法,可避免大部分场景下的错误:
static string X<T>(ICreate<T> creator) where T : IGetString { return creator.Create().GetString(); }
但需注意:若显式指定泛型参数为IGetString(即调用X<IGetString>(createB)),问题会复现,仍会调用错误的接口方法。
与同类问题的区别
此问题不同于常见的“泛型协变与多接口实现”问题——本场景中实例已被显式声明为ICreate<B>类型,却依然错误绑定到ICreate<A>的方法,而非因隐式转换导致的歧义。
结论
这属于C#协变泛型在多接口实现场景下的BUG。按照语言设计的预期,协变转换应保留原接口的方法绑定逻辑,而非随机选择类中首个匹配的接口方法。当前行为既无编译阶段的警告提示,也不符合开发者的合理预期,属于需要修复的设计缺陷。
内容的提问来源于stack exchange,提问作者Sergey Gussak
相关产品推荐
相关产品推荐

