C# 接口(Interface)
本章节是关于 C# 接口(Interface) 的全面、系统、专业级讲解,涵盖定义、用途、语法、规则、示例、常见模式、最佳实践和权威文档链接,适合开发工程师深度学习。
1. 接口是什么?
接口(interface)是 C# 中一种 定义行为契约(contract) 的机制,规定了实现它的类或结构体 必须实现哪些方法、属性、事件或索引器,但 不提供具体实现(除非是默认接口实现)。
🎯 本质:只定义“做什么”,不定义“怎么做”。
2. 接口的关键特性
| 特性 | 说明 |
|---|---|
使用 interface 关键字定义 | 不包含字段,只包含成员签名 |
| 无实现代码(C# 8.0+ 可提供默认实现) | 仅定义方法、属性、事件、索引器 |
| 多个接口可被同一类实现 | 支持多接口继承 |
| 接口之间可以继承 | 类似类之间的继承 |
3. 接口的语法结构
定义接口
public interface IAnimal {
void Speak();
string Name { get; set; }
}
实现接口
public class Dog : IAnimal {
public string Name { get; set; }
public void Speak() {
Console.WriteLine("Woof!");
}
}
4. 多接口实现
public interface IFly {
void Fly();
}
public interface ISwim {
void Swim();
}
public class Duck : IFly, ISwim {
public void Fly() => Console.WriteLine("Duck flying");
public void Swim() => Console.WriteLine("Duck swimming");
}
5. 显式接口实现(避免命名冲突)
public interface ILogger {
void Log();
}
public class FileLogger : ILogger {
void ILogger.Log() {
Console.WriteLine("Logging to file");
}
}
使用方式:
ILogger logger = new FileLogger();
logger.Log(); // OK
// fileLogger.Log(); // ❌ 不可直接调用
6. 接口 vs 抽象类
| 比较项 | 接口 | 抽象类 |
|---|---|---|
| 是否有实现 | 无(除非 C# 8+ 默认实现) | 可以有 |
| 是否可多继承 | ✅ 支持 | ❌ 不支持 |
| 适合场景 | 不相关类共享功能 | 一组类共享基本行为 |
| 构造函数 | ❌ 无 | ✅ 有 |
| 字段支持 | ❌ 无 | ✅ 有 |
7. 接口实际应用场景
| 场景 | 描述 |
|---|---|
| 策略模式 | 不同算法实现同一接口 |
| 依赖注入 | 实现松耦合结构 |
| 多态性 | 接口变量可指向任何实现类 |
| 单元测试 | 利用接口替换真实实现做 Mock |
8. 接口默认实现(C# 8+)
public interface ILogger {
void Log(string message);
void LogInfo(string message) {
Log("INFO: " + message); // 默认实现
}
}
⚠️ 默认实现的主要用途是:向旧接口新增成员而不破坏现有实现
9. 使用接口的最佳实践
- ✅ 接口命名以
I开头(如IShape) - ✅ 只定义行为,不实现逻辑(除非默认实现)
- ✅ 接口细化:接口隔离原则(ISP):多个小接口 > 一个大接口
- ✅ 用接口做参数、返回类型、依赖注入类型(编程面向接口)
- ✅ 在测试中,使用接口实现依赖替换(Mocking)
10. 权威参考资料
- 🔗 Microsoft Learn – Interfaces
- 🔗 C# Language Reference: interface
- 🔗 Interface and Abstract Class Comparison
11. 示例项目结构(简化)
public interface IRepository<T> {
void Add(T item);
T GetById(int id);
}
public class SqlRepository<T> : IRepository<T> {
public void Add(T item) { /* 写入数据库 */ }
public T GetById(int id) => default(T); // 假数据
}
public class Service {
private IRepository<User> _repo;
public Service(IRepository<User> repo) {
_repo = repo;
}
}
更多详细内容,请关注其他相关文章!