隐藏在 c# 中的方法有一个有效的例子。为什么它在框架中实现?现实世界的优势是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1193848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:30:55  来源:igfitidea点击:

method hiding in c# with a valid example. why is it implemented in the framework? what is the Real world advantage?

c#.netoopinheritancepolymorphism

提问by vijaysylvester

Can anyone explain the actual use of method hidingin C# with a valid example ?

谁能用一个有效的例子解释隐藏在 C# 中的方法的实际使用?

If the method is defined using the newkeyword in the derived class, then it cannot be overridden. Then it is the same as creating a fresh method (other than the one mentioned in the base class) with a different name.

如果该方法是new在派生类中使用关键字定义的,则它不能被覆盖。那么它就等同于创建一个具有不同名称的新方法(基类中提到的方法除外)。

Is there any specific reason to use the newkeyword?

使用new关键字有什么具体原因吗?

采纳答案by Arsen Mkrtchyan

C# not only supports method overriding, but also method hiding. Simply put, if a method is not overriding the derived method, it is hiding it. A hiding method has to be declared using the new keyword. The correct class definition in the second listing is thus:

C# 不仅支持方法覆盖,还支持方法隐藏。简单地说,如果一个方法没有覆盖派生的方法,它就是隐藏它。必须使用 new 关键字声明隐藏方法。因此,第二个清单中正确的类定义是:

    using System;
    namespace Polymorphism
    {
        class A
        {
            public void Foo() { Console.WriteLine("A::Foo()"); }
        }

        class B : A
        {
            public new void Foo() { Console.WriteLine("B::Foo()"); }
        }

        class Test
        {
            static void Main(string[] args)
            {
                A a;
                B b;

                a = new A();
                b = new B();
                a.Foo();  // output --> "A::Foo()"
                b.Foo();  // output --> "B::Foo()"

                a = new B();
                a.Foo();  // output --> "A::Foo()"
            }
        }
    }

回答by jeroenh

One use I sometimes have for the new keyword is for 'poor mans property covariance' in a parallell inheritance tree. Consider this example:

我有时对 new 关键字的一种用途是用于并行继承树中的“穷人财产协方差”。考虑这个例子:

public interface IDependency
{
}

public interface ConcreteDependency1 : IDependency
{
}

public class Base
{
  protected Base(IDependency dependency)
  {
    MyDependency = dependency;
  }

  protected IDependency MyDependency {get; private set;}
}

public class Derived1 : Base // Derived1 depends on ConcreteDependency1
{
  public Derived1(ConcreteDependency1 dependency)  : base(dependency) {}

  // the new keyword allows to define a property in the derived class
  // that casts the base type to the correct concrete type
  private new ConcreteDependency1 MyDependency {get {return (ConcreteDependency1)base.MyDependency;}}
}

The inheritance tree Derived1 : Base has a 'parallell dependency' on ConcreteDependency1 : IDependency'. In the derived class, I know that MyDependency is of type ConcreteDependency1, therefore I can hide the property getter from the base class using the new keyword.

继承树 Derived1 : Base 对 ConcreteDependency1 : IDependency 具有“并行依赖关系”。在派生类中,我知道 MyDependency 是 ConcreteDependency1 类型,因此我可以使用 new 关键字从基类中隐藏属性 getter。

EDIT: see also this blog post by Eric Lippertfor a good explanation of the new keyword.

编辑:另请参阅Eric Lippert 的这篇博客文章,以获得对 new 关键字的良好解释。

回答by Juri

I think ArsenMkrt's example is not fully correct, at least it does not fully explain the hiding feature. By dropping the new keyword from the Foo method in class B, you will still get the output

我认为 ArsenMkrt 的例子并不完全正确,至少它没有完全解释隐藏功能。通过从 B 类的 Foo 方法中删除 new 关键字,您仍将获得输出

A::Foo()
B::Foo()
A::Foo()

In a programming language like Java, where all methods are "virtual", you'd expect to get the output

在像 Java 这样的编程语言中,所有方法都是“虚拟的”,您希望获得输出

A::Foo()
B::Foo()
B::Foo()

by taking ArsenMkrt's code above, due to the instantiation

由于实例化,通过采用上面的 ArsenMkrt 代码

A a;
B b;

a = new A();
b = new B();
a.Foo(); 
b.Foo(); 

a = new B(); //<< Here
a.Foo();  

In his example however, you still get "A::Foo()" because in C# methods aren't virtual by default and so the method B::Foo() automatically hides A's Foo(). To achieve the polymorphic behavior one has to write it as follows instead:

但是,在他的示例中,您仍然会得到“A::Foo()”,因为在 C# 中方法默认情况下不是虚拟的,因此方法 B::Foo() 会自动隐藏 A 的 Foo()。要实现多态行为,必须将其编写如下:

class A
{
    public virtual void Foo() { Console.WriteLine("A::Foo()"); }
}

class B : A
{
    public override void Foo() { Console.WriteLine("B::Foo()"); }
}

Now is where the "new" keyword comes in. Actually when you leave the "override" from B::Foo(), then you again would hide A::Foo() meaning that you don't override it's default behavior and you don't achieve polymorphism, i.e. you get "A::Foo()" again as output. The same can be achieved - and here's where I don't 100% understand why you HAVE to put it - by placing the "new" keyword like..

现在是“new”关键字出现的地方。实际上,当您离开 B::Foo() 的“覆盖”时,您将再次隐藏 A::Foo(),这意味着您不会覆盖它的默认行为,并且您不要实现多态性,即您再次获得“A::Foo()”作为输出。也可以实现同样的效果——这就是我不能 100% 理解你为什么必须放置它的地方——通过放置“new”关键字,如..

class A
{
    public virtual void Foo() { Console.WriteLine("A::Foo()"); }
}

class B : A
{
    public new void Foo() { Console.WriteLine("B::Foo()"); }
}

and you again get the output

你再次得到输出

A::Foo()
B::Foo()
A::Foo()

回答by supercat

One slightly obscure scenario where method hiding would be appropriate, but for a lack of any clean idiomatic way of expressing it, is in circumstances where a base class exposes a protected member to an inheritable descendant, but that descendant knows that there is no way any further derived classes could use that member without breaking things. A prime example of a method which many classes should hide (but very few do) is MemberwiseClone(). In many cases, if a class has a privatemember which expects to be the only extant reference to a mutable object, there is no possible means by which a derived class could ever use MemberwiseClone()correctly.

一种稍微模糊的场景,方法隐藏是合适的,但由于缺乏任何干净的惯用方式来表达它,是在基类将受保护的成员暴露给可继承的后代的情况下,但后代知道没有任何办法进一步的派生类可以在不破坏事物的情况下使用该成员。许多类应该隐藏(但很少有人这样做)的方法的一个主要示例是MemberwiseClone(). 在许多情况下,如果一个类有一个private成员,该成员期望是对可变对象的唯一现存引用,那么派生类就不可能MemberwiseClone()正确使用。

Note that hiding of protected members does notconstitute a violation of the LSP. Conformance with the LSP requires that in places where code might be expecting reference to a base-class object but receives a reference to a derived-class object, the latter object should work as would the base-class one. Protected members, however, are outside the scope of the LSP, since every type knows its base type absolutely. If Barand Bozboth derive from Foo, and Bozhides a protected member that Barrequires, the fact that Bozhides the member won't affect Bar, because Bar's base-type instance can't possibly be a Bozor anything other than Foo. No substitution is possible, and hence substitutability is irrelevant.

注意保护构件,其隐藏并没有违反了LSP。与 LSP 的一致性要求在代码可能期望对基类对象的引用但收到对派生类对象的引用的地方,后一种对象应该像基类对象一样工作。但是,受保护的成员不在 LSP 的范围内,因为每种类型都绝对知道其基类型。如果BarBoz两者都派生自Foo,并且Boz隐藏了一个Bar需要的受保护成员,则Boz隐藏该成员的事实不会影响Bar,因为Bar的基类型实例不可能是 aBoz或除Foo. 没有替代是可能的,因此可替代性是无关紧要的。

回答by Uneverno

This might help.

这可能会有所帮助。

class Base
{
   public void F() {}
}
class Derived: Base
{
   public void F() {}      // Warning, hiding an inherited name
}

In the above example, the declaration of F in Derived causes a warning to be reported. Hiding an inherited name is specifically not an error, since that would preclude separate evolution of base classes. For example, the above situation might have come about because a later version of Base introduced an F method that wasn't present in an earlier version of the class. Had the above situation been an error, then any change made to a base class in a separately versioned class library could potentially cause derived classes to become invalid. Source: https://msdn.microsoft.com/en-us/library/aa691135%28v=vs.71%29.aspx

在上面的示例中,在 Derived 中声明 F 会导致报告警告。隐藏继承的名称特别不是错误,因为这会阻止基类的单独演化。例如,上述情况可能是因为 Base 的更高版本引入了一个 F 方法,而该方法在该类的早期版本中不存在。如果上述情况是一个错误,那么对单独版本化的类库中的基类所做的任何更改都可能导致派生类无效。来源:https: //msdn.microsoft.com/en-us/library/aa691135%28v=vs.71%29.aspx

回答by Newell Clark

One time when you would use them is when you need to add/modify an attribute that is on a base-class method. For example:

当您需要添加/修改基类方法上的属性时,有时会使用它们。例如:

[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
public new event EventHandler TextChanged
{
    add { base.TextChanged += value; }
    remove { base.TextChanged -= value; }
}

The base Controlclass has a TextChangedevent, but the base event has all kinds of attributes slapped on it to prevent it from showing up in intellisense or the designer. Because the class I used that in makes extensive use of both the Textproperty and the TextChangedevent, I wanted the TextChangedevent to show up in intellisense and be visible in the properties window.

Control类有一个TextChanged事件,但基事件具有各种属性,以防止它出现在智能感知或设计器中。因为我在其中使用的类广泛使用了Text属性和TextChanged事件,所以我希望TextChanged事件显示在智能感知中并在属性窗口中可见。