什么之间的差异,宣布一个方法中的一个基本类型"virtual"然后压倒一切的其中一个孩子的类型使用的"override"关键词,而不是简单地使用"new"关键字时声称匹配的方法在儿童的类型?

有帮助吗?

解决方案

“新”字样关键字不会覆盖,它表示与基类方法无关的新方法。

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

打印为false,如果您使用了覆盖,则打印为true。

(基本代码取自Joseph Daigle)

所以,如果你正在做真正的多态,你应该总是超越。您需要使用“新”的唯一地方当方法与基类版本没有任何关系时。

其他提示

我总是通过图片更容易理解这样的事情:

再次,采取joseph daigle的代码,

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

如果你然后调用这样的代码:

Foo a = new Bar();
a.DoSomething();

注意:重要的是我们的对象实际上是一个 Bar ,但我们将它存储在 Foo 的变量中strong>(这类似于施法)

然后结果将如下,具体取决于您在声明类时是否使用 virtual / override new

以下是一些用于理解虚拟和非虚拟方法行为差异的代码:

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

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

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}

new 关键字实际上创建了一个仅存在于该特定类型的全新成员。

例如

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

这两种类型都存在这种方法。当您使用反射并获取 Bar 类型的成员时,您实际上会找到两个看起来完全相同的 DoSomething()方法。通过使用 new ,您可以有效地隐藏基类中的实现,这样当类派生自 Bar (在我的示例中)时,方法调用 base.DoSomething( )转到 Bar 而不是 Foo

虚拟/覆盖告诉编译器这两个方法是相关的,在某些情况下,如果你认为你正在调用第一个(虚拟)方法,那么调用第二个(被覆盖的)实际上是正确的方法而不是。这是多态性的基础。

(new SubClass() as BaseClass).VirtualFoo()

将调用SubClass的覆盖VirtualFoo()方法。

new 告诉编译器您要向派生类添加一个方法,该方法的名称与基类中的方法相同,但它们之间没有任何关系。

(new SubClass() as BaseClass).NewBar()

将调用BaseClass的NewBar()方法,而不是:

(new SubClass()).NewBar()

将调用SubClass的NewBar()方法。

除了技术细节之外,我认为使用虚拟/覆盖可以在设计上传达大量的语义信息。声明方法虚拟时,表明您希望实现类可能希望提供自己的非默认实现。同样地,在基类中省略这一点,声明期望默认方法应该足以满足所有实现类。类似地,可以使用抽象声明来强制实现类来提供自己的实现。同样,我认为这传达了很多关于程序员如何期望使用代码的信息。如果我正在编写基础和实现类,并发现自己使用新的,我会认真地重新考虑不要在父级中使方法虚拟并明确声明我的意图。

override关键字和new关键字之间的区别在于前者执行方法覆盖,后者执行方法隐藏。

查看以下链接以获取更多信息......

MSDN 其他

  • new 关键词是为躲藏。-意味着你隐藏自己的方法在运行时间。产出将是基于基类方法。
  • override 为压倒一切的.-意味着你是用你的派生类方法的参考的基类。产出将是基于源类方法。

我的解释版本来自于使用属性来帮助理解差异。

override 很简单,对吗?底层类型会覆盖父级。

new 可能是误导性的(对我而言)。有了属性,它更容易理解:

public class Foo
{
    public bool GetSomething => false;
}

public class Bar : Foo
{
    public new bool GetSomething => true;
}

public static void Main(string[] args)
{
    Foo foo = new Bar();
    Console.WriteLine(foo.GetSomething);

    Bar bar = new Bar();
    Console.WriteLine(bar.GetSomething);
}

使用调试器你可以注意到 Foo foo 2 GetSomething 属性,因为它实际上有2个版本的属性, Foo Bar ,并知道要使用哪一个,c#" picks"当前类型的属性。

如果您想使用Bar的版本,您可能会使用覆盖或使用 Foo foo

条形码只有 1 ,因为它需要 GetSomething 的完全行为。

不用任何方法标记方法:使用对象的编译类型绑定此方法,而不是运行时类型(静态绑定)。

使用 virtual 标记方法意味着:使用对象的运行时类型绑定此方法,而不是编译时间类型(动态绑定)。

在派生类中使用 override 标记基类 virtual 方法意味着:这是使用对象的运行时类型(动态绑定)绑定的方法。

在派生类中使用 new 标记基类 virtual 方法意味着:这是一个新方法,与基础中具有相同名称的方法无关class,它应该使用object的编译时类型(静态绑定)绑定。

在派生类中未标记基类 virtual 方法意味着:此方法标记为 new (静态绑定)。

标记方法 abstract 意味着:此方法是虚拟的,但我不会为它声明一个主体,它的类也是抽象的(动态绑定)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top