接口只定义契约,不包含实现、状态或构造逻辑;成员默认public且不可加访问修饰符;命名须以i开头;应遵循接口隔离原则;默认方法仅用于安全演进,不可替代抽象类。

接口不是抽象类的简化版,也不是“轻量级基类”——它只管契约,不碰实现、不存状态、不参与构造。用错场景或写法,反而会增加维护成本。
接口成员不能加任何访问修饰符
所有接口成员(方法、属性、事件、索引器)默认就是 public,显式写 public 会直接报错 CS0106;写 private、protected 或 internal 同样非法。
- 错误写法:
public interface ILogger { public void Log(string msg); } - 正确写法:
public interface ILogger { void Log(string msg); string Name { get; } } - 哪怕在
internal interface里,成员也必须省略修饰符——接口本身可设可见性,但成员不可
接口命名必须以 I 开头且语义明确
这不是风格偏好,而是 C# 生态的强制约定。IDE、分析器、团队协作都依赖这个信号来快速识别契约类型。
- 推荐:
IEnumerable、IAsyncDisposable、ISaveable - 避免:
LoggerInterface、SaveManager、IDB(缩写模糊) - 结构体也要实现接口?没问题——但命名规则不变,
IComparable就是为int、DateTime这类值类型设计的
别把接口当工具箱:警惕“上帝接口”
一个接口塞进十多个方法,看起来“统一”,实则违反接口隔离原则(ISP),导致实现类被迫实现一堆空方法或抛 NotSupportedException。
- 反例:
IDevice同时含TurnOn()、SetTemperature()、PlayAudio() - 正解:拆成
ISwitchable、ITemperatureControllable、IPlayable,按需组合 - 类可以同时实现多个接口:
class SmartSpeaker : ISwitchable, ITemperatureControllable, IPlayable
.NET 8+ 默认接口方法不是“加功能”的捷径
默认方法允许接口带实现,但它的定位是“安全演进”和“轻量 fallback”,不是替代抽象类或服务层逻辑。
- 适合:
Log()打印时间戳 + 消息的通用格式化逻辑 - 不适合:
SaveToDatabase()或调用 DI 容器、读配置、发 HTTP 请求等有上下文依赖的操作 - 多接口同名默认方法冲突时,编译器不会帮你选——必须在实现类中显式重写,否则编译失败
最容易被忽略的一点:接口不声明字段、不提供构造函数、不支持 base 调用、不能被 new 实例化。一旦开始想“这个接口要不要加个 _cache 字段”,就该停下来问问自己——这还是契约吗?











