必须显式启用 c# 8.0+ 语言版本,否则接口默认方法编译失败;正确语法为 public void method() { },不可用 default、private 等关键字;实现类重写需用 public override,多接口同名方法须显式实现;默认方法可访问接口成员但不可访问实现类私有成员。

必须显式启用 C# 8.0+ 语言版本,否则哪怕写了方法体也会编译失败——这不是语法写错,而是编译器直接不认。
确认项目已启用 C# 8.0 或更高版本
VS 或 CLI 编译时提示 CS8701: Default interface methods are not supported in C# 7.3 and before,根本原因不是 SDK 版本低,而是项目没告诉编译器“请用新语法”。
- 检查
.csproj文件是否包含<langversion>8.0</langversion>(或9.0、12.0) - ASP.NET Core 模板常默认锁定
7.3,需手动覆盖 - 若用
Directory.Build.props统一控制,确认它被实际加载(可通过dotnet msbuild -preprocess验证) - 仅安装 .NET 6/8/9 SDK 不等于自动启用新语言特性
接口中写默认方法的正确语法
C# 接口默认方法不加 default 关键字(那是 Java 的写法),也不允许 private、internal 等修饰符——所有接口成员天然 public,显式写 public 是合法且推荐的。
- ✅ 正确:
public void Log(string message) { Console.WriteLine(message); } - ❌ 错误:
default void Log(...)→ 编译报错CS1043 - ❌ 错误:
private void Helper() { }→ 接口里不能有私有成员 - ❌ 错误:
void Error(string m) { }(无访问修饰符但带实现体)→ 虽能过编译,但易混淆,建议统一写public
实现类调用或重写默认方法的规则
类只要声明 : IMyInterface,就能直接调用默认方法;但想改逻辑,必须用 public override,漏掉 override 会触发 CS0506。
- 不重写:直接可用,比如
logger.Log("ok")会执行接口里的Console.WriteLine - 要重写:必须写
public override void Log(string m),不能只写public void Log(...)(那会被视为隐式隐藏,编译失败) - 若基类已实现该接口(如抽象类
BaseLogger : ILogger提供了Log),派生类继承的是基类实现,不是接口默认实现 - 多接口同名默认方法(如
IAudit.Log和ILogger.Log)→ 必须在实现类中显式提供public override void Log(...)消除歧义
默认方法能访问什么?不能做什么?
默认方法体里可以访问 this,也能调用接口中其他成员(包括属性、其他默认方法),但不能访问实现类的字段或私有方法——它始终运行在接口契约层面。
- ✅ 可用:
public double Area { get; }+public double Perimeter => Math.Sqrt(Area * 4); - ✅ 可用:调用另一个默认方法,如
Log($"start: {DateTime.Now}")在Start()默认实现里 - ❌ 不可用:
private string _cache;→ 接口不能有字段 - ❌ 不可用:
this.SomePrivateHelper()→ 实现类的私有成员对接口不可见
最容易被忽略的是:默认方法不是“可选补丁”,而是编译期绑定的契约一部分;一旦启用,它就参与虚方法表生成,影响运行时多态行为——尤其在组合多个接口、或与抽象基类混用时,行为优先级容易误判。











