探索C#中的接口实现:隐式 vs. 显式

作者:微信公众号:【架构师老卢】
1-26 15:21
52

概述:C#中的接口实现可以是隐式或显式的。隐式实现是常见的,但显式实现提供了更多控制权,尤其适用于特定情况,如接口方法不想公开在类上的情况。显式实现的调用需要通过接口访问,这可以在特定需求下提供更好的灵活性和可维护性。

介绍

在 C# 中,可以隐式或显式方式实现接口。在大多数情况下,我们使用的是隐式接口实现,即您有一个具有相同接口签名的方法。

internal interface IMyInterface
{
    void SayHello();
}
internal class ImplicitImplementation : IMyInterface
{
    public void SayHello() 
    {
        Console.WriteLine("ImplicitImplementation says hello.");
    }
}

显式接口实现是通过在接口方法前面加上接口名称和句点来定义的。该方法只能通过指定的接口访问。

internal class ExplicitImplementation : IMyInterface
{
    void IMyInterface.SayHello() 
    {
        Console.WriteLine("ExplicitImplementation says hello.");
    }
}

请注意,该方法没有公共访问修饰符,因为它只能通过接口访问。

IMyInterface v1 = new ExplicitImplementation();
v1.SayHello();

何时必须使用显式接口实现?

在以下情况下,必须使用显式接口实现:

类实现两个具有相同方法签名的接口。

internal interface IControl
{
    void Paint();
}

internal interface ICanvas
{
    void Paint();
}
internal class MyControl : IControl, ICanvas
{
    void IControl.Paint()
    {
        Console.WriteLine("IControl.Paint()");
    }
    void ICanvas.Paint()
    {
        Console.WriteLine("ICanvas.Paint()");
    }
}

var control = new MyControl();
((IControl)control).Paint();
((ICanvas)control).Paint();
  1. 您不想在类类型上公开接口方法。您希望用户将类型强制转换为接口以访问该方法。
internal class ExplicitImplementation : IMyInterface
{
    void IMyInterface.SayHello() 
    {
        Console.WriteLine("ExplicitImplementation says hello.");
    }
}

// The following two lines would cause compile error
// 'ExplicitImplementation' does not contain a definition for 'SayHello'
ExplicitImplementation v1 = new ExplicitImplementation();
v1.SayHello();

// The following lines are OK
IMyInterface v1 = new ExplicitImplementation();
v1.SayHello();

在上面的代码中,SayHello() 方法无法通过对象实例访问。您必须将其转换为接口才能访问它。

当涉及继承时,事情会变得复杂。假设您的基类和子类都必须实现相同的接口(隐式或显式),在不同的场景中调用哪个实现?有很多组合。我们在这里只讨论两种情况。

基类和子类都使用隐式接口实现
internal class ImplicitImplementation : IMyInterface
{
    public void SayHello() 
    {
        Console.WriteLine("ImplicitImplementation says hello.");
    }
}
internal class ImplicitImplementationSubClass : ImplicitImplementation, IMyInterface
{
    public void SayHello() 
    {
        Console.WriteLine("ImplicitImplementationSubClass says hello.");
    }
}

ImplicitImplementation v3 = new ImplicitImplementation();
v3.SayHello();

ImplicitImplementation v4 = new ImplicitImplementationSubClass();
v4.SayHello();

IMyInterface v5 = new ImplicitImplementationSubClass();
v5.SayHello();

// Output

ImplicitImplementation says hello. ImplicitImplementation says hello. ImplicitImplementationSubClass says hello.

这里的输出有点有趣:第一个是显而易见的。第二个和第三个值得解释。

对于第二个 (v4),运行时调用基类 ImplicitImplementation 中的接口实现,因为当基类和子类都隐式实现相同的接口时,子类实现会隐藏基类实现。

对于第三个 (v5),运行时调用子类中的接口实现,因为 v5 实例是从子类构造并强制转换为接口的。

基类和子类都使用显式接口实现
internal class ExplicitImplementation : IMyInterface
{
    void IMyInterface.SayHello() 
    {
        Console.WriteLine("ExplicitImplementation says hello.");
    }
}
internal class ExplicitImplementationSubClass : ExplicitImplementation, IMyInterface
{
    void IMyInterface.SayHello()
    {
        Console.WriteLine("ExplicitImplementationSubClass says hello explicitly.");
    }
    public void SayHello()
    {
        Console.WriteLine("ExplicitImplementationSubClass says hello implicitly.");
    }
}

IMyInterface v1 = new ExplicitImplementation();
v1.SayHello();

IMyInterface v2 = new ExplicitImplementationSubClass();
v2.SayHello();

ExplicitImplementationSubClass v2_1 = new ExplicitImplementationSubClass();
v2_1.SayHello();

/// Output

ExplicitImplementation says hello. ExplicitImplementationSubClass says hello explicitly. ExplicitImplementationSubClass says hello implicitly.

这里的输出更清晰易懂。显式接口实现只能通过接口访问。根据强制转换为接口的真实对象实例,运行时将触发该对象实例的接口实现。

您可以隐式和显式实现接口。运行时将调用正确的实现,具体取决于您是使用接口还是类对象来调用它。第三个输出 (v2_1) 演示了从类对象调用时,运行时将选择隐式接口实现。

相关留言评论
昵称:
邮箱:
阅读排行