C# 使用接口组合的怪异接口多态性

C# 使用接口组合的怪异接口多态性,c#,.net,interface,polymorphism,explicit,C#,.net,Interface,Polymorphism,Explicit,在我正在进行的一个项目中,我最终得到了如下代码。我觉得我被允许这么做真的很奇怪,但现在我开始想,我这方面最有可能的建筑缺陷是什么导致了我这么做 我的问题是: 这到底叫什么 这在现实世界中有什么用途 为什么会有人想这样做 以下是我的界面: namespace ThisAndThat { public interface ICanDoThis { string Do(); } public interface ICanDoThat {

在我正在进行的一个项目中,我最终得到了如下代码。我觉得我被允许这么做真的很奇怪,但现在我开始想,我这方面最有可能的建筑缺陷是什么导致了我这么做

我的问题是:

  • 这到底叫什么
  • 这在现实世界中有什么用途
  • 为什么会有人想这样做
以下是我的界面:

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

    public interface ICanDoThat
    {
        string Do();
    }

    public interface ICanDoThisAndThat : ICanDoThis, ICanDoThat
    {
        new string Do();
    }
}
这是我的具体课程:

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!";
        }
    }
}
以及我通过的测试:

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());
        }

    }
}
每种类型都有一个属性(如果您想通过反射查看它,可以使用该属性进行检索)。这基本上是说,“当调用接口Y上的方法X时,这个方法Z就是要调用的方法。”请注意,尽管C#中不支持它,但映射目标方法可能与接口方法名称有不同的名称!(我相信VB明确支持这一点。)

在本例中,您有三个方法,三个方法中的每一个都对应于所涉及的一个接口中的一个方法

当编译器通过接口发出对虚拟方法的调用时,生成的IL表示类似“调用此对象上的IFoo.Bar”,然后使用接口映射解析IFoo.Bar


如果您有只在返回类型上不同的签名,或者您正在实现两个异构接口,这两个接口碰巧具有相同的方法名,但应该执行不同的操作,那么您有时可能需要使用它。无论你在哪里都可以避免,尽管这样做!这会导致代码非常混乱。

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

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

在以下情况下,显式接口实现非常有用:

  • 两个接口具有相同的成员定义
  • 您需要实现一个接口,但不想公开某个特定成员可用于未使用接口类型声明引用的客户端代码
  • NET framework中案例2的一个示例是
    ICollection.SyncLock
    <代码>列表实现了
    ICollection
    ,但以下代码将不会编译,因为成员已被故意“隐藏”,因为BCL的设计者不再主张以这种方式锁定集合:

    List<object> list = new List<object>();
    
    lock (list.SyncRoot) // compiler fails here
    {
        // ...
    }
    

    谢谢,给你们答案是因为你们提供了发生的事情的确切名称。由于你们的答案中有很多错误,所以投了否决票。首先,
    candothisand类实现了三个接口,而不是两个<代码>ICANDothis,该
    声明,在实现时,您还必须实现另外两个接口。此外,SyncRoot并没有被实现明确定义为隐藏它以阻止使用,它的定义通常是为了将很少使用的成员排除在站点之外,或者如果实现了接口这一事实并不重要。请看和。文档中没有说明不应使用SyncLock,也没有将其标记为过时,这是当某些内容不应再使用时真正要做的事情。@Andy SyncRoot属性被Microsoft高级工程师视为有问题的设计已有一段时间了。看看布拉德·艾布拉姆斯(Brad Abrams)的作品,他在书中明确表示:“请放心,我们不会在构建这些收藏的通用版本时犯同样的错误。”@richteb,也不是一个明确的谴责。那个博客是从2003年开始的,但SyncRoot至今还没有被淘汰。不管怎么说,将其明确化的原因不是为了隐藏它。在1.1中就是这样做的,这是我能找到的最古老的框架文档。我只能假设它也在1.0中显式实现,更可能允许我们提供自己的SyncRoot实现。声称这样做是为了阻止使用是错误的。
    ICollection list = new List<object>();
    
    lock (list.SyncRoot) // no problem
    {
        // ...
    }