C# 接口
本章将介绍 C# 中的接口(Interface),包括接口定义、实现、以及接口的特性和最佳实践。
接口概述
什么是接口?
接口定义了契约,它指定了类必须实现的方法、属性、事件和索引器,但不提供实现。接口是一种抽象类型,用于定义类应该具有的行为。
// 接口定义
interface IComparable
{
int CompareTo(object obj);
}
interface IEnumerable
{
IEnumerator GetEnumerator();
}
接口 vs 抽象类
| 特性 | 接口 | 抽象类 |
|---|---|---|
| 多继承 | 支持多个接口 | 仅支持单一继承 |
| 实现 | 可以包含默认实现(C# 8+) | 可以包含抽象成员 |
| 字段 | 不能有实例字段 | 可以有实例字段 |
| 构造函数 | 没有构造函数 | 可以有构造函数 |
| 访问修饰符 | 成员默认 public | 可以有各种修饰符 |
接口的定义
基本语法
// 定义接口
interface IPlayer
{
// 方法
void Play();
void Pause();
// 属性
string Name { get; set; }
bool IsPlaying { get; }
// 事件
event EventHandler<PlayerEventArgs> StateChanged;
}
接口命名约定
// 接口前缀 I
interface IDisposable { }
interface IComparable { }
interface IEnumerable { }
interface ICollection { }
接口成员
interface IAnimal
{
// 方法(不能有实现,除非 C# 8+ default 成员)
void Speak();
// 属性
string Name { get; set; }
int Age { get; }
// 索引器
string this[int index] { get; set; }
// 事件
event EventHandler? Born;
}
接口的实现
显式实现
// 接口定义
interface IWriteable
{
void Write(string content);
}
interface IReadable
{
string Read();
}
// 类实现多个接口
class FileHandler : IWriteable, IReadable
{
private string _content = "";
// 实现 IWriteable
public void Write(string content)
{
_content = content;
}
// 实现 IReadable
public string Read()
{
return _content;
}
}
显式接口实现
interface IFirst
{
void Method();
}
interface ISecond
{
void Method();
}
// 使用显式实现避免冲突
class MyClass : IFirst, ISecond
{
// 实现 IFirst.Method
void IFirst.Method()
{
Console.WriteLine("IFirst.Method");
}
// 实现 ISecond.Method
void ISecond.Method()
{
Console.WriteLine("ISecond.Method");
}
}
// 使用
MyClass obj = new MyClass();
((IFirst)obj).Method(); // 输出: IFirst.Method
((ISecond)obj).Method(); // 输出: ISecond.Method
实现接口属性
interface IIdentifiable
{
string Id { get; }
string Name { get; set; }
}
class Person : IIdentifiable
{
public string Id { get; private set; }
public string Name { get; set; }
public Person(string id, string name)
{
Id = id;
Name = name;
}
}
实现接口事件
interface IObserver
{
void OnUpdate(string message);
}
class Publisher
{
public event EventHandler<string>? MessageSent;
public void SendMessage(string message)
{
Console.WriteLine($"发送: {message}");
MessageSent?.Invoke(this, message);
}
}
class Subscriber : IObserver
{
public void OnUpdate(string message)
{
Console.WriteLine($"收到: {message}");
}
}
接口的默认实现(C# 8+)
默认成员
interface ILogger
{
void Log(string message)
{
Console.WriteLine($"[LOG] {message}");
}
void Error(string message)
{
Console.WriteLine($"[ERROR] {message}");
}
}
// 可以直接使用默认实现
class ConsoleLogger : ILogger
{
// 可以选择重写或不重写
}
ConsoleLogger logger = new ConsoleLogger();
logger.Log("Hello"); // 使用默认实现
静态成员
interface IHelper
{
static string Version = "1.0.0";
static void PrintVersion()
{
Console.WriteLine($"Version: {Version}");
}
}
接口与多态
依赖接口而非实现
// 不好的设计
class OrderService
{
private SqlServerDatabase _db = new SqlServerDatabase();
public void Save(Order order)
{
_db.Save(order);
}
}
// 好的设计:依赖接口
class OrderService
{
private readonly IDatabase _db;
public OrderService(IDatabase database)
{
_db = database;
}
public void Save(Order order)
{
_db.Save(order);
}
}
依赖注入示例
// 定义接口
interface IDatabase
{
void Save(object data);
object Get(int id);
}
// 实现接口
class SqlServer : IDatabase
{
public void Save(object data)
{
Console.WriteLine("保存到 SQL Server");
}
public object Get(int id)
{
return new { };
}
}
class MongoDB : IDatabase
{
public void Save(object data)
{
Console.WriteLine("保存到 MongoDB");
}
public object Get(int id)
{
return new { };
}
}
// 使用
class Service
{
private readonly IDatabase _database;
public Service(IDatabase database)
{
_database = database;
}
}
// 运行时注入不同实现
var service1 = new Service(new SqlServer());
var service2 = new Service(new MongoDB());
接口的继承
interface IReadable
{
string Read();
}
interface IWritable
{
void Write(string content);
}
// 接口继承接口
interface IFile : IReadable, IWritable
{
void Delete();
}
// 类实现接口
class File : IFile
{
public string Read() => "file content";
public void Write(string content) => Console.WriteLine(content);
public void Delete() => Console.WriteLine("deleted");
}
接口与协变/逆变
协变(C# 4+)
interface IProducer<out T>
{
T Produce();
}
class Animal { }
class Dog : Animal { }
class Producer : IProducer<Dog>
{
public Dog Produce() => new Dog();
}
// 协变允许
IProducer<Animal> producer = new Producer();
逆变(C# 4+)
interface IConsumer<in T>
{
void Consume(T item);
}
class Animal { }
class Dog : Animal { }
class Consumer : IConsumer<Dog>
{
public void Consume(Dog dog) => Console.WriteLine("consumed");
}
// 逆变允许
IConsumer<Animal> consumer = new Consumer();
常用 .NET 接口
IEnumerable 和 IEnumerator
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
interface IEnumerator<out T>
{
bool MoveNext();
T Current { get; }
void Reset();
}
IDisposable
interface IDisposable
{
void Dispose();
}
// 使用 using
using (var resource = new Resource())
{
// 使用资源
} // 自动调用 Dispose
IComparable 和 IComparer
interface IComparable<in T>
{
int CompareTo(T other);
}
class Person : IComparable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(Person other)
{
return Age.CompareTo(other.Age);
}
}
标记接口
// 空接口作为标记
interface ISerializable { }
class Data : ISerializable { }
// 检查
if (obj is ISerializable)
{
// 可以序列化
}
小结
- 接口定义:定义契约,不提供实现
- 接口实现:使用类实现一个或多个接口
- 显式实现:避免方法名冲突
- 默认实现:C# 8+ 支持带默认实现的接口
- 依赖注入:通过接口实现松耦合
- 协变/逆变:泛型接口的类型安全性
练习
- 创建一个
IComparable接口的实现类 - 设计一个简单的依赖注入容器
- 使用接口实现策略模式
- 实现一个支持排序和筛选的集合类