Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “使用”有什么意义;方法隐藏";?_C#_Methods_Method Hiding - Fatal编程技术网

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.