C#8接口

目录

介绍

接口的今天

默认接口方法

钻石问题

接口中的修饰符

总结

参考


介绍

众所周知,C8.0几天前就已发布。这个版本的C#提供了许多令人兴奋的功能。接口也发生了大量的变化,因此在本文中,我们将尝试探索新功能,并尝试了解如何在项目中使用它们。

接口的今天

作为开发人员,我们都使用接口,无论是创建松散耦合的组件还是定义应由具体类实现的契约。今天的接口永远不会出现方法身体,没有修饰符。实现者类负责提供方法体并为其分配一些修饰符。如果类没有实现该方法,编译器会捕获它并提供错误,说我们需要实现该接口。

在整个应用程序中,我们将使用Logger类的示例并相应地进行更改。

using System;
public interface ILogger
{
void Log(string Info);
}
public class TextLogger : ILogger
{
 public void Log(string Info)=> Console.Write("In base Logger");
}

我们定义了一个拥有一个Log()方法的ILogger接口。我们有一个叫做实现接口ILoggerTextLogger类。考虑到当前的设计状态,这是完全正常的。现在,当我们想要扩展ILogger并且需要在其中添加更多信息时,会出现问题,如下所示:

public interface ILogger
{
void Log(string info);
void Log(string typeofInformation,string info)
}

现在我们将遇到一个问题,因为这个新方法必须由使用此接口的类实现,编译器将向我们显示错误,直到完成如下所示:

现在考虑到这个接口被多个类使用,这将打破许多变化,并且根据使用此接口的位置在实现中进行这些更改将非常痛苦。我们需要实现这个方法,以便我们的代码编译。为了克服这个问题,C8想出了接口中的默认方法。

默认接口方法

C8.0中获得此功能的主要原因是为接口方法提供默认实现,那么我们该如何做呢?我们来看下面的例子:

using System; 
public interface ILogger
{ void Log(string info); 
//Default implementation void LogInfo(string typeofInformation,
//string info)=>Console.Write(typeofInformation+ " " + info); 
}
public class TextLogger : ILogger { 
public void Log(string info)=> Console.Write("In base Logger"); 
}

在这里,我们可以在接口本身看到,我们已经为该函数提供了实现。这里,我们的类TextLogger不需要实现这个方法,也不会有任何编译时错误。现在,为了在我们的应用程序中使用此接口,让我们改变我们的main方法,让我们看看我们如何使用它。

class Program
    {
        static void Main(string[] args)
        {
           ILogger _logger = new TextLogger();
           _logger.LogInfo("Test","test"); // It will call the Default method of the interface
        }  
      }}

我们需要检查的另一件事是,只有在将类作为接口进行上下文处理时,默认方法才有效。如果我们不这样做,那么默认方法实现将无法使用:

在上面的截图中,我们可以看到从类创建对象时,我们可以看到默认方法无法使用。如果我们仔细研究这个特性,我们可以看到这可能导致众所周知的多重继承问题,这个问题被称为钻石问题。根据设计,C#不会遇到任何问题,因为类和接口没有多重继承,没有方法的实现,但是使用默认方法,这将会改变。让我们看看如何在C8.0中处理它。

钻石问题

钻石问题是语言中的一个大问题,因为C#类不支持这种多重继承的结果,但是接口可以在某种程度上引入这个问题。让我们看看C#如何处理它们。下图说明了钻石问题:

上图很好地描述了钻石问题。现在,让我们看看默认接口如何产生这个问题以及C#如何处理它。让我们设计如下接口:

Interface First
{
    void WritetoConsole() => Console.Write("In First");
}

interface Second:First{
 void First.WritetoConsole()=>Console.Write("In Second");
}

interface Third:First{
  void First.WritetoConsole()=>Console.Write("In Third");
}

class FinalClass : Second,Third
{
}

在编写此代码时,我们将遇到编译时错误:

错误消息将是接口成员First.WritetoConsole()'没有最具体的实现。Second.First.WritetoConsole()“ Third.First.WritetoConsole()都不是最特殊的。(CS8705DefaultInterfaceDemo]。为了解决错误本身所描述的这个问题,我们需要在执行时提供最具体的覆盖,Dotnet设计团队已经具体告诉它,如下,接口成员的类实现应该总是赢得接口中的默认实现,即使它是从基类继承的。默认实现总是只在类没有任何成员实现时才会回滚。让我们看看我们如何提供默认实现并解决这个钻石问题。

using System;
interface First
{
    void WritetoConsole() => Console.Write("In First");
}

interface Second:First{
 void First.WritetoConsole()=>Console.Write("In Second");
}

interface Third:First{
  void First.WritetoConsole()=>Console.Write("In Third");
}

class FinalClass : Second,Third
{
  void First.WritetoConsole(){
  Console.Write("From Final class");
}
}

接口中的修饰符

传统上,直到C8.0的到来,我们无法在接口中使用修饰符。在C8.0中,我们可以使用它们,至今修饰符像privateprotectedinternalpublicvirtual是允许的。在设计上,所有默认接口的方法都是virtual,除非我们将它们设置为privatesealed。没有正文的所有成员在默认情况下都被视为抽象,因此必须在具体类中实现。

using System;
interface IInterfaceModifiers
{
  //By Default default method is private
  virtual void DefaultMethod()=>Console.WriteLine("Default method");
  //Private Default Method
  private void privatedefaultmethod()=>Console.WriteLine(" private Default method");
  //Protected Default Method
  protected void ProtectedDefaultMethod()=>Console.WriteLine(" protected Default method");
  // Public Default Method
  public void PublicDefaultMethod()=>Console.WriteLine(" public Default method");
  virtual void VirtualDefaultMethod()=>Console.WriteLine("Virtual Default method");
  abstract void AbstractDefaultMethod();
}
<hr>
class InterfaceModifierDemo : IInterfaceModifiers
{  
  public void AbstractDefaultMethod() => Console.WriteLine("Abstract virtual method");}

namespace DeaultInterfaceDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            IInterfaceModifiers i= new InterfaceModifierDemo();
            i.AbstractDefaultMethod();
            i.DefaultMethod();
            i.PublicDefaultMethod();
            i.VirtualDefaultMethod();
        }
    }
}

当我们运行上面的代码时,我们可以在控制台上看到以下输出:

Abstract virtual method
Default method
public Default method
Virtual Default method

除此之外,我在这个例子中遇到的观察很少。当我们使一个方法成为virtual时,我们可以在接口本身中重写该方法,并且我们不能在实现类中重写它。当我们创建一个protected方法时,它在继承接口中可用,而不是实现类。默认情况下,接口的成员是abstract,这使得实现类必须正确实现它们。

总结

我们已经看到了C8.0中最具争议但最激动人心的特性。它将改变我们在设计中使用接口的方式,这肯定会帮助开发人员产生更少的重大变化,但它也会提出自己的性能和设计视角的挑战。要添加的另一件事是,此功能目前在.NET框架中不可用,但包含在.NET CoreCore CLR以及MONO中。

参考

 

原文地址:https://www.codeproject.com/Articles/5161143/Csharp-8-Interfaces

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值