为什么当我投一个类来它没有实现一个接口,没有编译器错误?(Why no compiler error

2019-06-28 01:34发布

如果我尝试从一个类的无效转换到一个接口,那么编译器不会抱怨(在运行时出现错误); 但是它确实抱怨,如果我尝试了类似的强制转换为抽象类。

class Program
{
    abstract class aBaz
    {
        public abstract int A { get; }
    }

    interface IBar
    {
        int B { get; }
    }

    class Foo
    {
        public int C { get; }
    }

    static void Main()
    {
        Foo foo = new Foo();

        // compiler error, as expected, since Foo doesn't inherit aBaz
        aBaz baz = (aBaz)foo;

        // no compiler error, even though Foo doesn't implement IBar
        IBar bar = (IBar)foo;
    }
}

为什么不编译器拒绝从伊巴尔投,当它的(貌似?)无效? 或者,翻转的问题,如果编译器允许这种“无效”剧组到接口伊巴尔 ,为何它没有允许转换为抽象类aBaz类似的“无效”?

Answer 1:

你需要了解的.Net的继承体系,看看为什么这是有道理的。 在.NET中,一类可以从仅一个基类继承但可以实现任何数量的接口。

class Program
{
    abstract class aBaz
    {
        public abstract int A { get; }
    }

    interface IBar
    {
        int B { get; }
    }

    class Foo
    {
        public int C { get; }
    }

    class BarableFoo : Foo, IBar
    {
        public int C { get; }
    }

    static void Main()
    {
        // This is why the compiler doesn't error on the later cast
        Foo foo = new BarableFoo();

        // compiler error: aBaz is a class and the compiler knows that
        // Foo is not a _subclass_ of aBaz.
        aBaz baz = (aBaz)foo;

        // no compiler error: the class Foo does not implement IBar, however at runtime
        // this instance, "foo", might be a subclass of Foo that _implements_ IBar.
        // This is perfectly valid, and succeeds at runtime.
        IBar bar = (IBar)foo;

        // On the other hand...
        foo = new Foo();

        // This fails at runtime as expected. 
        bar = (IBar)foo;
    }

}

在这个问题非常简单原始的例子,它看起来像编译器可以检测到FOO的这个实例是永远不会被强制转换为伊巴尔,但更多的是“锦上添花”,警告不是语言正确性的问题。



Answer 2:

铸造的整点是抑制编译器错误。
(例如,如果你知道foo实际上是没有实现接口的子类型的实例)

如果编译器可以证明它是不可能的投成功,它仍然会给出一个错误。 (例如,如果你投的一 ,是不是在它的层次)



Answer 3:

并表明编译器不傻有施放时会在编译时失败actulaly情况:如果编译器可以证明没有其他类可以从类它将无法铸造在编译时接口派生:

sealed class NoBar
{ 
} 

struct NoBarValue
{
}

IBar noBar = (IBar)(new NoBar()); // fails at compile time
IBar noBarValue = (IBar)(new NoBarValue()); // fails at compile time

在第一种情况下( NoBar )类明确密封(因此也没有派生类可以实现的IFoo)和编译器知道它没有实现IBar本身-因此可以在编译时失败。 第二种情况( NoBarValue )是唯一的差别值类型(结构)被隐式密封类似。



文章来源: Why no compiler error when I cast a class to an interface it doesn't implement?