C# “使用”有什么意义;方法隐藏";?
可能重复:C# “使用”有什么意义;方法隐藏";?,c#,methods,method-hiding,C#,Methods,Method Hiding,可能重复: 我想知道方法隐藏在c#中如何有用?如果你深入研究这个概念,你会发现方法隐藏是一件让人困惑的事情,并驱使我们使用意大利面代码。原因如下: 1-如果在派生类中需要新方法,可以在派生类中使用新名称定义新方法。 2-以多态方式使用当您使用向上转换时,预期的行为将无法实现,这可能会令人困惑 (特别是,如果基类和派生类位于不同的库中,并且您希望在代码中的某个地方对它们进行多态性使用,那么这种奇怪的行为可能非常明显) 这样的行为可能会让人困惑,但如果我们在“Base”中使用“virtual”,
我想知道方法隐藏在c#中如何有用?如果你深入研究这个概念,你会发现方法隐藏是一件让人困惑的事情,并驱使我们使用意大利面代码。原因如下: 1-如果在派生类中需要新方法,可以在派生类中使用新名称定义新方法。 2-以多态方式使用当您使用向上转换时,预期的行为将无法实现,这可能会令人困惑 (特别是,如果基类和派生类位于不同的库中,并且您希望在代码中的某个地方对它们进行多态性使用,那么这种奇怪的行为可能非常明显) 这样的行为可能会让人困惑,但如果我们在“Base”中使用“virtual”,在“Derived”中使用“override”(我是指多态用法),则输出结果是:“我是派生类”。 我认为这是我们大多数人所期望的结果 换句话说,我相信在层次结构中,大多数开发人员希望在派生类中重写方法,而不是希望隐藏基类实现的新方法 我不明白为什么在c语言中会有这样一件没有优势的坏事?至少我想知道隐藏在c#中的方法的最佳用法是什么 谢谢你的帮助 如果在派生类中需要新方法,可以在派生类中使用新名称定义新方法 不总是这样。考虑这样一种情况,即派生一个在其他库中暴露的类,其中一个库是您无法控制的。您可以向类中添加一些方法 稍后,您所依赖的库的开发人员将添加一些增强功能,并使用与您添加到派生类中的方法之一相同的名称。在这种情况下,隐藏仅仅是保留现有功能。如果更改方法名称,则必须更新整个代码库,并且会破坏与使用库的任何人的兼容性。相反,您可以隐藏现有方法,同时保留与依赖项以及所依赖库的兼容性 就我个人而言,我使用方法隐藏最多的情况是在多个类上实现克隆操作时;如果没有此功能,我无法更改返回类型以匹配类的返回类型:
class A
{
public A Clone()
{
return CloneImpl();
}
protected virtual A CloneImpl()
{
return MemberwiseClone();
}
}
class B : A
{
new public B Clone()
{
return (B)CloneImpl();
}
}
受保护的虚拟方法意味着,无论调用哪个Clone()
,您仍然可以获得正确类型的对象。但是,您获得的引用类型将取决于用于调用Clone()
的引用类型。这允许:
B b = new B();
B b2 = b.Clone(); // Did not have to cast, thanks to the hiding method.
A a = b;
A a2 = a.Clone(); // Still returns a B, only typed as an A.
“预期的行为将无法实现”-这取决于开发人员的预期。如果他期望非虚拟方法虚拟地运行,这是一个有缺陷的期望。下面是一个例子:如果你有一个动物集合,并在集合中迭代调用Speak(),对每一个动物,你不希望奶牛说“Moo”,狗说“Woof”?@mbeckish这是一个需要虚拟方法的人为案例。一个反例并不能否定整个特性。我不确定您是否正确使用了术语“方法隐藏”。您的代码示例是方法隐藏的一个示例。如果该方法是虚拟的,则它将是方法重写。你说哪一个不是好东西?这是和的复制品。另请参见我的文章和脆性基类示例。这就是为什么在可能的情况下最好使用组合而不是继承的原因之一。@Servy我同意。我希望C#在这方面提供更多;实现两个接口然后将它们委托给成员对象是一件痛苦的事情。编写样板代码不是一个有趣的练习。(特别是指您希望将组合对象作为“一”公开的情况——我现在忘记了该模式的名称。)不幸的是,问题已经解决了,但只是出于好奇,即使在这种情况下,如果第一个开发人员在基类中使用了“virtual”,您也可以“重写”派生类中的方法。我的意思是,即使在这种情况下,“重写”也更好,如果在c#中,方法的定义默认为“virtual”,那么就不需要隐藏方法。我说得对吗?@siamak no.如果方法默认为virtual/override(想想Java)然后,在父类中添加新方法可能会导致派生类中的方法突然重写它,这可能是不必要的行为,并且可能会产生不良后果。
B b = new B();
B b2 = b.Clone(); // Did not have to cast, thanks to the hiding method.
A a = b;
A a2 = a.Clone(); // Still returns a B, only typed as an A.