C# 8 中新增了一个非常有趣的特性,叫做 默认接口方法 (又称虚拟扩展方法),这篇文章将会讨论 C# 8 中的默认接口方法以及如何使用。
在 C# 8 之前,接口不能包含方法定义,只能在接口中定义方法签名,还有一个就是接口的成员默认是 public 和 abstract , 在 C# 8 之前,接口不能包含字段,也不能包含private, protected, 或者 internal 的方法成员。如果你在接口中引入了一个新成员,默认情况下你必须更新实现该接口的所有子类。
在 C# 8 中可以在接口定义方法的默认实现,而且还可以定义接口成员为 private,protect,甚至是 static,还有一点挺奇葩的,一个接口的 protect 成员是不能被实现类所访问的,相反,它只能在子接口中被访问,接口的 virtual 成员可以由派生接口 override,但不能被派生类 override,还有一点请注意,接口目前还不能定义 实例成员。
为什么要使用默认接口方法
所谓的 默认接口方法 指的是接口中定义了一个默认实现的方法, 如果实现该接口的类没有实现默认接口方法的话,那么这个 默认接口方法 只能从接口上进行访问,这是一个很有用的特性,因为它可以帮助开发人员在不破坏现有功能的情况下向接口的未来版本添加新方法。
考虑下面的 ILogger 定义。
public interface ILogger
{
public void Log(string message);
}
下面的两个类扩展了ILogger接口并实现了Log()方法。
public class FileLogger : ILogger
{
public void Log(string message)
{
//Some code
}
}
public class DbLogger : ILogger
{
public void Log(string message)
{
//Some code
}
}
现在假设你想在ILogger接口中新增一个方法,该方法接受两个参数:一个 文本 一个 日志级别,下面的代码片段展示了日志级别的枚举类。
public enum LogLevel
{
Info, Debug, Warning, Error
}
修改后的 ILogger 接口如下:
public interface ILogger
{
public void Log(string message);
public void Log(string message, LogLevel logLevel);
}
好了,现在问题来了,因为 ILogger 中新增了一个 Log 方法,你必须要在所有实现该接口的所有子类中实现 Log(string message, LogLevel logLevel) 方法,这就很尴尬了,如果不这样做的话,编译器肯定是不会放行的,在现实情况下,这个接口实现类可能在多个 dll 中,甚至在多个团队中,可想而知,这个工作量是非常大并且非常痛苦的。