如何在C#8.0中使用默认接口方法

C#8.0中有趣的新功能之一是对默认接口方法(也称为虚拟扩展方法)的支持。 本文介绍了默认接口方法以及如何在C#8.0中使用它们的讨论。

在C#8.0之前,C#中的接口不能包含方法定义。 您只能在接口中包括方法声明,并且默认情况下,接口的成员是公共的和抽象的。 此外,在C#8.0之前,接口不能包含字段,也不能具有私有成员,受保护成员或内部成员。 如果在接口中引入了新成员(即方法声明),则必须对实现该接口的所有类进行更新。

使用C#8.0,您现在可以在接口中具有方法的默认实现。 接口成员也可以是私有的,受保护的和静态的。 不能在扩展接口的类中访问接口的受保护成员。 而是只能在派生接口中访问它们。 接口成员也可以是虚拟的和抽象的。 但是,接口的虚拟成员可以被派生的接口覆盖,但不能被扩展接口的类覆盖。 请注意,您仍然不能在接口中包含实例成员。

为什么要使用默认接口方法?

默认接口方法是接口中包含具体实现的方法。 如果扩展接口的类未实现该方法,则将从接口使用该方法的默认实现。 这是一个有用的功能,因为它可以帮助开发人员在不破坏现有功能(即该接口的现有实现)的情况下将方法添加到接口的未来版本中。

考虑以下接口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方法提供默认实现,如下面的代码段所示。

 public interface ILogger
    {
        public void Log(string message);
        public void Log(string message, LogLevel logLevel)
        {
            Console.WriteLine("Log method of ILogger called.");
            Console.WriteLine("Log Level: "+ logLevel.ToString());
            Console.WriteLine(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
        }
    }

默认接口方法不继承

现在,如下面的代码片段所示,创建FileLogger类的实例,并调用我们新添加到ILogger接口的Log方法。

FileLogger fileLogger = new FileLogger();
fileLogger.Log("This is a test message.", LogLevel.Debug);
默认界面方法c锐利8 IDG

默认接口方法不继承。

因此,这证明了扩展类没有继承默认接口方法,即,扩展接口的类不了解默认接口方法。

默认界面方法和钻石问题

现在的百万美元问题是,默认接口方法如何避免“菱形问题”,即它如何使用接口解决多重继承问题? 我们来看一个例子。 考虑下面的代码清单。

    public interface A
    {
        public void Display();
    }
    public interface B : A
    {
        public void Display()
        {
            Console.WriteLine("Interface B.");
        }
    }
    public interface C : A
    {
        public void Display()
        {
            Console.WriteLine("Interface C.");
        }
    }
    public class MyClass : B, C
    {
    }

当您编译上述程序时,将出现一个编译错误,指出MyClass类未实现接口成员A.Display(),正确的是。 因为Display方法在接口A中缺少默认实现,所以我们必须在MyClass类中提供一个实现才能满足编译器的要求。

来做吧。 这是更新的代码供您参考。

    public interface A
    {
        public void Display();
    }
    public interface B : A
    {
        public void Display()
        {
            Console.WriteLine("Interface B.");
        }
    }
    public interface C : A
    {
        public void Display()
        {
            Console.WriteLine("Interface C.");
        }
    }
    public class MyClass : B, C
    {
        public void Display()
        {
            Console.WriteLine("MyClass.");
        }
    }

现在,创建类MyClass的实例,并调用Display方法,如下面的代码片段所示。

static void Main(string[] args)
        {
            A obj = new MyClass();
            obj.Display();
            Console.Read();
        }

这次将调用哪种显示方法? 为避免歧义,将应用最具体的覆盖规则。 因此,将调用类MyClass的Display方法。

C#8.0中的抽象类与接口

C#8.0中的抽象类和接口是否相同? 并不是的。 尽管抽象类和接口现在看起来不止一种相似,但两者之间还是存在细微差别。 您仍然不能从一个以上的类中扩展一个类。 并且与抽象类不同,接口不能具有实例成员。 而且,您仍然可以实现多个接口。

默认接口方法使开发人员可以利用traits编程技术,该技术使您可以重用与不相关类型有关的方法。 假设您已经建立了一个可供许多开发人员使用的库,并且您想发布该库的新版本。 如果您的接口添加了新成员,则可以定义其实现,以便可以继续利用库中的类型,而无需更改代码库。

From: https://www.infoworld.com/article/3455239/how-to-use-default-interface-methods-in-csharp-8.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值