接口声明的核心约束
禁止包含的成员类型
- ❌ 数据成员(字段、常量)
- ❌ 静态成员(静态方法/属性)
理由:接口仅定义契约,不涉及实现或状态存储。
允许的成员类型(仅非静态函数成员)
- ✅ 方法(void Save())
- ✅ 属性(string Name { get; set; })
- ✅ 事件(event EventHandler OnSaved)
- ✅ 索引器(object this[int index] { get; set; })
成员声明规范
- 所有成员声明必须省略实现代码,以分号结尾
// 正确声明
void Save();
string Name { get; set; }// 错误声明(含实现体)
void Save() { } // 编译错误!
命名与访问控制规则
命名规范
强制前缀:接口名必须以大写字母 I 开头
public interface ISaveable { ... } // 正确
public interface Saveable { ... } // 不符合约定
访问修饰符策略
对象 | 允许修饰符 | 默认访问性 |
---|---|---|
接口本身 | public, protected, internal, private | 根据上下文 |
接口成员 | 禁止任何修饰符(隐式 public) | public |
public interface ILogger
{// 隐式public,不可添加修饰符void Log(string message); // private void Error(); // 非法声明!
}
高级特性与示例
分部接口声明
支持通过 partial 关键字拆分接口定义(适用于大型接口)
// File1.cs
public partial interface IDataProcessor
{void Validate();
}// File2.cs
public partial interface IDataProcessor
{void Process();
}
完整声明示例
public interface IStorable
{// 属性声明 int Status { get; set; } // 方法声明void Read(); void Write(string data); // 事件声明 event Action OnModified; // 索引器声明byte this[int index] { get; set; }
}
设计原则与陷阱规避
为何强制省略实现?
- 确保接口专注行为契约而非具体逻辑
- 避免与抽象类的职责混淆(抽象类可包含部分实现)
典型误用场景
- 尝试在接口中声明字段 → 改用属性封装状态
- 为接口成员添加 public → 冗余且导致编译错误
最佳实践建议
- 单一职责:每个接口聚焦单一功能(如 ISerializable, IDisposable)
- 命名语义化:I 前缀后使用形容词/行为名词(如 IComparable, IEnumerable)
关键总结
- 接口是纯契约:无状态、无静态成员、无实现代码
- 成员隐式公开 → 禁止显式访问修饰符
- 命名需以 I 开头 → 强化类型语义
- 善用分部接口 → 提升大型项目可维护性