看看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();
}
}
答案 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()
虚拟方法,并在运行时选择了适当的覆盖。