c# 8.0起接口可定义带实现的默认方法,用于安全演化接口;必须public、非static,实现类可继承、override或sealed override,不重写则自动使用默认实现。

什么是 C# 默认接口方法
从 C# 8.0 开始,接口可以包含带有实现的成员(即“默认接口方法”),这打破了过去接口只能声明、不能实现的限制。它不是为了替代抽象类,而是为了解决接口演化问题:在不破坏已有实现类的前提下,向接口添加新方法。
关键点:default interface method 必须是 public(不能是 private 或 protected),且不能是 static(C# 8–11 中不允许;C# 11+ 才支持 static abstract 和 static virtual 接口方法,但那是另一回事)。
如何定义带默认实现的接口方法
语法上就是在接口里写一个完整的方法体,不加 abstract,也不加 virtual —— 它天然就是可被重写的(除非实现类显式用 sealed 修饰重写)。
- 必须使用 C# 8.0+ 编译器,且项目 SDK 版本 ≥
netcoreapp3.0或net5.0及以上 - 接口方法签名后直接跟
{ ... },例如:void Log() { Console.WriteLine("default"); } - 可以访问接口中的
static成员(C# 8+ 支持接口中定义static字段和方法),但不能访问实例状态(因为没有this上下文) - 如果实现类未提供自己的版本,调用的就是接口里的默认实现
实现类是否必须重写默认接口方法
不需要。实现类可以完全忽略默认方法,直接继承行为;也可以选择 override 它(需用 public override 显式声明);还可以用 sealed override 阻止进一步重写。
常见误区:override 不是可选修饰符——如果你写了实现,就必须加 override,否则编译报错:'ClassName.MethodName()' does not implement interface member 'IInterface.MethodName()'。
示例:
interface ILogger
{
void Log() => Console.WriteLine("default log");
}
<p>class ConsoleLogger : ILogger
{
public override void Log() => Console.WriteLine("console log"); // ✅ 必须加 override
}</p><p>class NullLogger : ILogger
{
// ✅ 什么都不写,就用接口默认实现
}默认接口方法的调用歧义与显式实现
当一个类实现多个接口,且这些接口都提供了同名默认方法时,编译器会报错:Ambiguity between 'I1.M()' and 'I2.M()'。此时必须在类中显式提供实现,或使用显式接口实现来消歧。
- 显式实现写法:
void I1.M() { ... }和void I2.M() { ... },各自独立 - 若只希望某一个默认行为生效,可在类中写
public override void M()并在里面调用特定接口的默认实现:((I1)this).M(); - 注意:不能在默认接口方法体内用
this调用其他接口默认方法(因为this在接口中不可用) - 多层继承链中,接口默认方法不会“向上查找”,它只属于定义它的那个接口
真正容易被忽略的是:默认接口方法无法访问实现类的字段或属性,也不能调用 base(因为没有基类概念)。它看起来像“实现”,实际更像“契约附带的兜底逻辑”。










