将接口转换为不继承的另一个接口

时间:2012-05-02 17:42:58

标签: c# inheritance interface casting

我希望有人可以解释我正在做出的错误假设。在C#4.0中,我有两个接口和一个实现它们的类。在一个方法中,我声明一个具有第一个接口类型的变量,使用实现两个接口的类来实例化它,并且可以某种方式将它成功地转换到第二个接口,如下面的代码所示:

    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',但演员表仍然是成功的。

我错过了什么?

6 个答案:

答案 0 :(得分:8)

从您的示例中,您应该在调用任何功能之前测试类型类型。第一个创建将创建一个支持两个接口的完全限定的“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();

答案 1 :(得分:3)

实例first的实际类型指向实现两个接口。显然,对象上可以使用Method1Method2

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

InterfaceImplementation实现两个接口时,您可以选择使用任一接口引用该实例。

答案 2 :(得分:1)

你唯一缺少的就是它的确如此,这是一个有用的功能,而不是一个问题。在转换时,你可以认为代码基本上是这样说的,“我不在乎我知道这个对象的类型是什么,我想知道它是否可以转换为类型T”。在这种情况下,由于底层对象的类型为InterfaceImplementation,无论它当前被称为IFirstInterface,答案是肯定的,它可以转换为ISecondInterface

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

相关问题