使用有效示例隐藏在c#中的方法.为什么在框架中实现?什么是真实世界的优势?

vij*_*ter 13 .net c# oop polymorphism inheritance

任何人都可以用一个有效的例子解释隐藏在C#中的方法的实际用法吗?

如果使用new派生类中的关键字定义方法,则无法覆盖该方法.然后它与创建一个具有不同名称的新方法(除了在基类中提到的方法之外)相同.

有没有具体的理由使用new关键字?

jer*_*enh 10

我有时对新关键字使用的一个用法是在并行继承树中使用'穷人的属性协方差'.考虑这个例子:

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;}}
}
Run Code Online (Sandbox Code Playgroud)

继承树Derived1:Base对ConcreteDependency1:IDependency'具有'parallell依赖'.在派生类中,我知道MyDependency的类型为ConcreteDependency1,因此我可以使用new关键字从基类中隐藏属性getter.

编辑:请参阅Eric Lippert撰写的这篇博文,以获得对新关键字的详细解释.

  • 有趣的 - > +1 (3认同)

Ars*_*yan 7

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()"
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 我不确定为什么这会被标记为答案.这只是一个例子,而OP问**为什么**不**如何** (2认同)

Jur*_*uri 7

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

A::Foo()
B::Foo()
A::Foo()
Run Code Online (Sandbox Code Playgroud)

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

A::Foo()
B::Foo()
B::Foo()
Run Code Online (Sandbox Code Playgroud)

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

A a;
B b;

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

a = new B(); //<< Here
a.Foo();  
Run Code Online (Sandbox Code Playgroud)

然而,在他的例子中,你仍然得到"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()"); }
}
Run Code Online (Sandbox Code Playgroud)

现在是"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()"); }
}
Run Code Online (Sandbox Code Playgroud)

然后你再次获得输出

A::Foo()
B::Foo()
A::Foo()
Run Code Online (Sandbox Code Playgroud)