C#接口静态方法在泛型中未正确解析至派生类问题咨询
C# 静态接口方法在泛型约束下的调用差异是预期行为吗?
代码示例
namespace TestConsole.TestStaticMethodOverride2; internal class Program { static void Main(string[] args) { FooDerivedImplicit.Do(); Console.WriteLine(); FooDerivedExplicit.Do(); Console.WriteLine(); GenericCallStatic<FooDerivedImplicit>.Call(); Console.WriteLine(); GenericCallStatic<FooDerivedExplicit>.Call(); Console.WriteLine(); } } public interface IFoo { public static virtual void Do() => Console.WriteLine("IFoo:Do"); } public class FooBase : IFoo { public static void Do() => Console.WriteLine("FooBase:Do"); } public class FooDerivedImplicit() : FooBase // Implicitly IFoo { public static new void Do() => Console.WriteLine("FooDerivedImplicit:Do"); } public class FooDerivedExplicit() : FooBase, IFoo // Explicitly says is IFoo { public static new void Do() => Console.WriteLine("FooDerivedExplicit:Do"); } public static class GenericCallStatic<T> where T : IFoo { public static void Call() => T.Do(); }
输出结果
FooDerivedImplicit:Do FooDerivedExplicit:Do FooBase:Do FooDerivedExplicit:Do
这是预期行为,核心原因在于C#对静态接口方法的绑定规则,以及显式声明接口实现的作用:
关键逻辑解析
静态接口方法的绑定归属
静态接口方法的实现是和直接声明实现接口的类型绑定的,不会通过继承自动传递给派生类:FooBase直接实现了IFoo,它的Do()会被编译器标记为IFoo静态方法的实现。FooDerivedImplicit仅继承FooBase,没有显式写: IFoo,所以它的new Do()只是覆盖了基类的静态方法,并没有被关联到IFoo的接口方法上。
泛型约束下的调用规则
当泛型类通过where T : IFoo调用T.Do()时,编译器会寻找T对应的接口静态方法实现:- 对
FooDerivedImplicit,因为它没有显式声明实现IFoo,编译器会向上找到最近的、直接实现IFoo的类型(也就是FooBase),所以调用的是FooBase.Do()。 - 对
FooDerivedExplicit,显式声明了: IFoo,编译器会将它的new Do()认定为IFoo静态方法的实现,因此调用派生类自己的版本。
- 对
基类未实现接口方法的场景
当FooBase不实现Do()时,FooDerivedImplicit既没有显式声明实现IFoo,也没有提供自己的静态接口方法实现,所以泛型调用时会 fallback 到IFoo的默认静态方法。
内容的提问来源于stack exchange,提问作者user30642770
相关产品推荐
相关产品推荐

