使用接口组合的奇怪的界面多态性

Sco*_*Muc 5 .net c# polymorphism explicit interface

我在一个正在研究的项目中得到了类似下面代码的东西.我觉得我被允许这样做真的很奇怪,但是现在我开始想知道我最有可能是一个建筑师,这让我想到了这一点.

我的问题是:

  • 究竟是什么叫做?
  • 这有什么现实世界的用途?
  • 为什么有人想要这样做?

这是我的界面:

namespace ThisAndThat
{
    public interface ICanDoThis
    {
        string Do();
    }

    public interface ICanDoThat
    {
        string Do();
    }

    public interface ICanDoThisAndThat : ICanDoThis, ICanDoThat
    {
        new string Do();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的具体课程:

namespace ThisAndThat
{
    public class CanDoThisAndThat : ICanDoThisAndThat
    {
        public string Do()
        {
            return "I Can Do This And That!";
        }

        string ICanDoThis.Do()
        {
            return "I Can Do This!";
        }

        string ICanDoThat.Do()
        {
            return "I Can Do That!";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的通过考试:

using Xunit;

namespace ThisAndThat.Tests
{
    public class ThisAndThatTests
    {
        [Fact]
        public void I_Can_Do_This_And_That()
        {
            ICanDoThisAndThat sut = new CanDoThisAndThat();

            Assert.Equal("I Can Do This And That!", sut.Do());
        }

        [Fact]
        public void I_Can_Do_This()
        {
            ICanDoThis sut = new CanDoThisAndThat();

            Assert.Equal("I Can Do This!", sut.Do());
        }

        [Fact]
        public void I_Can_Do_That()
        {
            ICanDoThat sut = new CanDoThisAndThat();

            Assert.Equal("I Can Do That!", sut.Do());
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

Dre*_*kes 5

这段代码绝对没有错(前提是它不会让你的用户感到困惑),而且它不是一个我熟悉的任何名字的模式. CanDoThisAndThat实现两个接口,因此客户端可以以任何一种方式使用它.

.NET允许以这种方式实现接口 - 称为显式接口实现.

在以下情况下显式接口实现很有用:

  1. 两个接口具有相同的成员定义
  2. 您需要实现一个接口,但不希望公开特定成员可用于未使用接口类型声明引用的客户端代码

.NET框架中的案例2的示例是ICollection.SyncLock. List<T>实现ICollection但是以下代码将无法编译,因为该成员故意被"隐藏",因为BCL的设计者不再提倡以这种方式锁定集合:

List<object> list = new List<object>();

lock (list.SyncRoot) // compiler fails here
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

此格式的任何遗留代码仍然有效,因为引用的类型是ICollection显式的:

ICollection list = new List<object>();

lock (list.SyncRoot) // no problem
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)