【问题标题】:Casting an interface to another interface that it does not inherit将一个接口转换为另一个它不继承的接口
【发布时间】:2012-05-12 05:37:28
【问题描述】:

我希望这里有人可以解释我所做的错误假设。在 C# 4.0 中,我有 2 个接口和一个实现它们的类。在一个方法中,我用第一个接口的类型声明了一个变量,使用实现这两个接口的类对其进行实例化,并可以以某种方式成功地将其转换为第二个接口,如下面的代码:

    public interface IFirstInterface 
    {
        void Method1();
    }

    public interface ISecondInterface
    {
        void Method2();
    }

    public class InterfaceImplementation : IFirstInterface, ISecondInterface
    {
        public void Method1() { }
        public void Method2() { }
    }

    public class SomeClass
    {
        public void SomeMethod()
        {
            IFirstInterface first = new InterfaceImplementation();
            first.Method1();

            // Shouldn't the next line return null?
            ISecondInterface second = first as ISecondInterface; 
            // second is not null and the call to Method2() works fine
            second.Method2();
        }
    }

我正试图了解为什么选角成功。是的,该类实现了这两个接口,但我认为由于第一个变量被声明为 IFirstInterface(它不是从 ISecondInterface 继承的),因此转换应该仍然失败。

我也尝试过以其他方式重构我的代码,例如不使用“as”,但转换仍然成功。

我错过了什么?

【问题讨论】:

    标签: c# inheritance interface casting


    【解决方案1】:

    如果你从具体对象的角度来看,你可以说“我是一个 IFirstInterface,但我也是一个 ISecondInterface”。你是这个意思吗?您描述的问题最终会在继承/实现链中进行转换。

    【讨论】:

      【解决方案2】:

      您唯一缺少的是,这正是它的本意,这是一个有用的功能,而不是问题。转换时,您可以将代码视为基本上是在说,“我不在乎我知道这个对象的类型是什么,我想看看它是否可以转换为类型 T”。在这种情况下,由于底层对象的类型是InterfaceImplementation,不管它目前被称为IFirstInterface,答案是肯定的,它可以转换为ISecondInterface

      【讨论】:

        【解决方案3】:

        欢迎来到多态。对象first 始终是InterfaceImplementation 的一个实例。您选择引用它的方式不会影响对象真正“是”什么。这就是抽象概念作为一个整体的运作方式。

        【讨论】:

          【解决方案4】:

          实例first指向的实际类型实现了这两个接口。所以显然Method1Method2 在对象上都可用。

          first 的静态类型只允许您访问Method1second 的静态类型只允许您访问Method2。如果您使用任一接口声明对对象的引用,您只需选择将实例视为满足所选合同(接口)的对象。

          由于InterfaceImplementation 实现了这两个接口,您可以选择使用任一接口引用实例。

          【讨论】:

            【解决方案5】:

            从您的示例中,您应该在调用任何功能之前测试类型类型。第一次创建将创建一个支持两个接口的完全限定的“InterfaceImplementation”。但是,您将其放入仅第一个接口的声明类型中。因此,从“第一个”对象的角度来看,它只关心与 IFirstInterface 实现相关的任何内容。

            现在,第二个...即使您已经创建了对象,您仍然可以问...顺便问一下...您也是第二个接口吗?如果是这样,请执行此操作...

            IFirstInterface first = new InterfaceImplementation();
            
            if( first is ISecondInterface )
              // typecast since the second interface is legit, then call it's method 2
              ((ISecondInterface)first).Method2();
            

            【讨论】:

            • 这证实了我的想法。谢谢
            【解决方案6】:

            这确实表明存在设计缺陷。客户端知道这两个接口是由同一个对象实现的。对于您的示例,这很好,但如果这些接口是单独实现的,您将无法从第一个跳转到第二个。理想情况下,最好有某种查询界面,您可以在其中从一种类型转到另一种类型。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-12-13
              • 2019-05-08
              • 2023-01-28
              • 2010-10-22
              • 2010-09-06
              • 2021-09-12
              • 2023-03-25
              • 1970-01-01
              相关资源
              最近更新 更多