C# 中的方法隐藏和阴影有什么区别?它们是相同的还是不同的?我们可以将它们称为多态性(编译时或运行时)吗?
5 回答
C# 中的方法隐藏和阴影有什么区别?
阴影是另一个常用的隐藏术语。C# 规范仅使用“隐藏”,但两者都可以接受。
您只调用“方法隐藏”,但除了方法隐藏之外还有其他形式的隐藏。例如:
namespace N
{
class D {}
class C
{
class N
{
class D
{
N.D nd; // Which N.D does this refer to?
嵌套类 N 在 D 中时隐藏了命名空间 N。
我们可以将它们称为多态性(编译时或运行时)吗?
方法隐藏可用于多态性,是的。您甚至可以将方法隐藏与方法覆盖混合使用;通过隐藏旧的虚方法引入新的虚方法是合法的;在这种情况下,选择哪种虚拟方法取决于接收器的编译时和运行时类型。这样做非常令人困惑,如果可能的话,你应该避免它。
VB.NET 编译器将其称为遮蔽,在 C# 中称为隐藏。在 C# 中将其称为阴影是 VB 的溢出效应。
这是一个编译器警告,它本质上是基类和派生类之间的名称冲突。
我们可以将它们称为多态性(编译时或运行时)吗?
它当然不是运行时多态的一种形式。对隐藏或隐藏方法的调用在编译时解决。这使得它通常不会被称为或考虑多态性。
这两个术语在 C# 中的含义相同。
方法隐藏 == 阴影。
您可以将其用作多态性的一种形式 - 当您不希望基类方法通过继承类可见/可用时。
阴影方法与基类完全分离——它是一种新方法。使用术语隐藏是因为它具有与基类相同的签名并且正在“隐藏”它 - 它破坏了继承链。
它们只是同一事物的两个不同词,但在您最常使用它们的上下文中有所不同。通常,所谓的“隐藏”与多态性有关,而所谓的“阴影”则不是。
在 C# 用语中,当您说“隐藏”时,您通常是在谈论继承,其中更派生的方法从正常的继承方法调用链中“隐藏”基类方法。
当您说“影子”时,您通常是在谈论范围:内部范围内的标识符正在“遮蔽”更高范围内的标识符。在其他语言中,C# 中所谓的“隐藏”有时也称为“阴影”。
两者都是编译时概念;当编译器绑定它时,它们描述了给定标识符在给定上下文中引用的对象。
public class A
{
public int B;
public void C()
{
return this.B;
}
}
public class D : A
{
public int X;
public new void C()
{
var X = 1.0m;
return X;
}
}
方法D.C()
“隐藏”方法A.C()
;通常,调用D.C()
总是会调用基类A.C()
方法,因为它不是virtual
. 我们不希望这样;我们想要D.C()
。显然这是你应该尽量避免的事情,因为它会令人困惑,尤其是当你开始将你的 D 转换为 A 时,但如果你需要它就存在。另外,请注意方法隐藏是自动的:new
这里没有关键字,D.C()
仍然会隐藏,A.C()
但我们会收到警告,因为通常这不是您想要的。new
关键字只是清楚地表明这确实是我们想要的。
局部变量只X
在D.C()
shadows 类成员D.X
的范围内D.C()
。在这种情况下,范围内有两件事可以合法地调用X
,编译器需要规则来告诉它你的意思是哪一个。“更本地化”X
掩盖了“更少本地化” D.X
,这就是我们得到的。
C# 的名称隐藏(new
修饰符)在 VB.NET 中称为遮蔽(关键字Shadows
)。
仅在覆盖是“多态”的意义上,这可以被认为是多态,即静态或编译时。它不是调用虚函数的经典意义上的多态性。