C#:为什么安全转换(as)返回重写方法而不是基本方法?

时间:2017-02-14 11:30:32

标签: c# casting

看看as关键字在C#中是如何工作的,我可以看到它允许在显式转换(即使用括号)阻止编译的情况下进行转换。

但是在下面的代码中,我发现如果我覆盖派生类中的方法,然后安全地转换为基类,那么派生类中的重写方法仍然会执行。为什么是这样?我期待在基类上定义的方法来执行。

class Base
{
    public override string ToString()
    {
        return base.ToString();
    }

    public string OtherMethod()
    {
        return "Other method";
    }
}

class Derived : Base
{
    public override string ToString()
    {
        return "Derived class";
    }
}

class Program
{
    static void Main()
    {
        Derived d = new Derived();
        Base b = new Base();

        System.Console.WriteLine(b.ToString()); // Base
        System.Console.WriteLine(d.ToString()); // Derived class
        System.Console.WriteLine((d as Base).ToString()); // Derived class => WHY IS THIS?
        System.Console.WriteLine((d as Base).OtherMethod()); // Other method
        // System.Console.WriteLine((Base)d.OtherMethod()); // --- prevents compilation

        // As noted in the comments, this works
        System.Console.WriteLine(((Base)d).OtherMethod()); // Other method

        System.Console.ReadLine();
    }
}

3 个答案:

答案 0 :(得分:4)

只有在阴影的情况下,只有当阴影时才会向需要并且导致执行不同方法的唯一时间。< / p>

当派生类实现与基类 1 中的方法同名的方法时会发生阴影,并且显然,这不是override。通常,这些标记使用关键字new进行标记。如果您有派生类的实例但希望调用基类成员,则需要将其强制转换为该基类(或者继承链中的任何中间类,它们本身并不影响所讨论的方法)

在没有阴影的情况下,任何方法调用总是使用最多派生的方法,基于对象的运行时类型,而不是变量的声明类型。

但是,通常最好避免使用阴影。

1 不一定是直接基类 - 在继承链中的任何地方都回到object

答案 1 :(得分:0)

这就是继承和多态在C#中的工作原理。 INSERT INTO B SELECT A.* FROM A LEFT JOIN B ON A.articlenumber = B.articlenumber WHERE B.articlenumber IS NULL 运算符仅执行安全转换,但在内部仍为as。它只是更改它,以便编译器知道它具有正确的类型。根据您的类型,不需要铸造。这只是有效:

Derived

这仍然会调用 Base d = new Derived(); 覆盖的虚拟方法。

对于显式强制转换,它失败了,因为它的优先级低于该表达式上的其他运算符。首先评估整个右侧,然后评估演员。从本质上讲,这就是你告诉编译器的内容。

Derived

答案 2 :(得分:0)

这可以帮助:https://msdn.microsoft.com/en-us/library/ms173152.aspx

  

基类可以定义和实现virtualmethods,派生类可以覆盖它们,这意味着它们提供自己的定义和实现。 在运行时,当客户端代码调用该方法时,CLR会查找该对象的运行时类型,并调用该虚拟方法的覆盖。因此,在源代码中,您可以在基类上调用方法,并导致派生类的方法版本被执行。

在您的情况下,您正在调用Object.ToString()虚拟方法,并在运行时选择了适当的覆盖。