接口是契约,必须用interface声明,成员仅限无实现的签名,不能含字段或构造函数;实现时成员须为public,同名冲突需显式实现;类可多实现接口但不可多重继承,结构体也能实现接口。

接口不是模板,也不是基类;它是契约。你写 class 实现某个 IComparable<t></t>,就等于签了份协议:必须提供 CompareTo 方法,且签名不能错——否则编译器立刻报错,不讲情面。
定义接口时哪些语法是硬性限制
接口用 interface 关键字声明,成员只能是方法、属性、事件、索引器的签名,不能带实现体(C# 8.0+ 虽支持默认实现,但那是例外,不是默认行为)。
-
interface内不能出现字段、构造函数、析构函数、static字段或const常量(哪怕只读也不行) - 所有成员自动为
public,显式写public会编译失败 - 不能用
virtual、sealed、override等修饰符 - 名称建议以
I开头(如IEquatable<t></t>),这不是语法要求,但影响可读性和团队约定
实现接口时为什么 public 不能省
接口本身不带访问修饰符,但实现类里的对应成员必须是 public,否则编译器认为“没实现”。隐式实现时漏写 public 是新手最常踩的坑之一。
- 错误写法:
bool Equals(Car car) { ... }→ 缺少public,编译失败 - 正确写法:
public bool Equals(Car car) { ... } - 如果类同时实现多个接口且有同名方法(比如两个接口都有
Paint()),又不想共用一个实现,就得用显式实现:void IControl.Paint() { ... }和void ISurface.Paint() { ... } - 显式实现的方法不能加
public,也不能直接通过类实例调用,必须转型后调用:((IControl)obj).Paint()
什么时候必须用显式接口实现
不是为了炫技,而是为了解决真实冲突。典型场景有两个:
- 两个接口定义了同名同签名成员(如都叫
Paint()),但语义不同,需要各自独立实现 - 两个接口一个定义了属性
int P { get; },另一个定义了方法int P(),名字一样但类型不同,隐式实现会冲突 - 显式实现后,该成员对类自身不可见,避免意外调用;也防止子类无意中重写它
- 注意:显式实现的方法返回类型、参数顺序、是否带
ref/out必须和接口完全一致,连可空引用类型(string?)都不能松动
接口继承和多实现的实际约束
C# 不允许类多重继承,但一个类可以实现多个接口,这是它的核心价值。不过要注意继承链上的“契约叠加”:
-
interface IA { void M(); },interface IB : IA { void N(); },那么实现IB的类必须同时实现M()和N() - 接口可以继承多个接口:
interface IC : IA, IB { },此时实现IC就等于承诺实现全部父接口成员 - 结构(
struct)不能继承类,但能实现接口——这是给值类型添加多态能力的唯一方式 - 泛型接口(如
IEquatable<t></t>)在实现时,类型参数必须匹配,class Car : IEquatable<car></car>不能写成IEquatable<object></object>
接口的难点不在语法,而在设计意图的落地:每个 void 方法背后,都藏着调用方对行为的一致预期。一旦实现偏离契约(比如 Equals 没处理 null,或 CompareTo 返回值不符合三值逻辑),运行时出问题往往比编译错误更难定位。











