You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

疑问:.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:13:14