C# - 关键字使用 virtual+override 与 new

发布于 2024-07-06 04:24:49 字数 120 浏览 11 评论 0原文

在基类型“virtual”中声明方法,然后使用“override”关键字在子类型中重写该方法与简单地使用“< code>new" 关键字在子类型中声明匹配方法时?

What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

妄断弥空 2024-07-13 04:24:50

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

Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.

孤独患者 2024-07-13 04:24:50

“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)

因此,如果您正在执行真正的多态性,那么您应该始终覆盖。 唯一需要使用“new”的地方是当该方法与基类版本没有任何关系时。

The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.

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 ());
    }
}

This prints false, if you used override it would have printed true.

(Base code taken from Joseph Daigle)

So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.

寒尘 2024-07-13 04:24:50

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

The new keyword actually creates a completely new member that only exists on that specific type.

For instance

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

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

The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.

独孤求败 2024-07-13 04:24:50

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

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;
    }
}

Here's some code to understand the difference in the behavior of virtual and non-virtual methods:

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;
    }
}
和影子一齐双人舞 2024-07-13 04:24:50

虚拟/重写告诉编译器这两个方法是相关的,并且在某些情况下,当您认为正在调用第一个(虚拟)方法时,实际上调用第二个(重写)方法是正确的。 这是多态性的基础。

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

将调用子类的重写 VirtualFoo() 方法。

new 告诉编译器您正在向派生类添加一个与基类中的方法同名的方法,但它们彼此没有关系。

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

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

(new SubClass()).NewBar()

将调用 SubClass 的 NewBar() 方法。

virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.

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

Will call the SubClass's overriden VirtualFoo() method.

new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.

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

Will call the BaseClass's NewBar() method, whereas:

(new SubClass()).NewBar()

Will call the SubClass's NewBar() method.

在你怀里撒娇 2024-07-13 04:24:50
  • new 关键字用于隐藏。 - 意味着您在运行时隐藏您的方法。 输出将基于基类方法。
  • override 用于覆盖。 - 意味着您正在使用基类的引用调用派生类方法。 输出将基于派生类方法。
  • new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
  • override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
如果没有 2024-07-13 04:24:50

override关键字和new关键字的区别在于前者进行方法重写,后者进行方法隐藏。

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

MSDN其他

The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.

Check out the folllowing links for more information...

MSDN and Other

独行侠 2024-07-13 04:24:50

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

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 foo2 GetSomething 属性,因为它实际上有 2 个版本属性,Foo's 和 Bar's,并且为了知道使用哪一个,c#“挑选”当前类型的属性。

如果您想使用 Bar 的版本,则可以使用 override 或使用 Foo foo 代替。

Bar bar 只有 1,因为它需要 GetSomething 具有完全行为。

My version of explanation comes from using properties to help understand the differences.

override is simple enough, right ? The underlying type overrides the parent's.

new is perhaps the misleading (for me it was). With properties it's easier to understand:

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);
}

Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.

If you wanted to use the Bar's version, you would have used override or use Foo foo instead.

Bar bar has only 1, as it wants completely new behavior for GetSomething.

泪意 2024-07-13 04:24:50

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

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

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

在派生类中用 new 标记基类virtual方法意味着:这是一个新方法,与基类中的同名方法没有关系。应使用对象的编译时类型进行绑定(静态绑定)。

在派生类中不标记基类虚拟方法意味着:该方法被标记为new(静态绑定)。

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

Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).

Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).

Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).

Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).

Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).

Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).

不知在何时 2024-07-13 04:24:50
using System;  
using System.Text;  
  
namespace OverrideAndNew  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            BaseClass bc = new BaseClass();  
            DerivedClass dc = new DerivedClass();  
            BaseClass bcdc = new DerivedClass();  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in BaseClass.  
            bc.Method1();  
            bc.Method2();  
            // Output:  
            // Base - Method1  
            // Base - Method2  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in DerivedClass.  
            dc.Method1();  
            dc.Method2();  
            // Output:  
            // Derived - Method1  
            // Derived - Method2  
  
            // The following two calls produce different results, depending
            // on whether override (Method1) or new (Method2) is used.  
            bcdc.Method1();  
            bcdc.Method2();  
            // Output:  
            // Derived - Method1  
            // Base - Method2  
        }  
    }  
  
    class BaseClass  
    {  
        public virtual void Method1()  
        {  
            Console.WriteLine("Base - Method1");  
        }  
  
        public virtual void Method2()  
        {  
            Console.WriteLine("Base - Method2");  
        }  
    }  
  
    class DerivedClass : BaseClass  
    {  
        public override void Method1()  
        {  
            Console.WriteLine("Derived - Method1");  
        }  
  
        public new void Method2()  
        {  
            Console.WriteLine("Derived - Method2");  
        }  
    }  
}  
using System;  
using System.Text;  
  
namespace OverrideAndNew  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            BaseClass bc = new BaseClass();  
            DerivedClass dc = new DerivedClass();  
            BaseClass bcdc = new DerivedClass();  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in BaseClass.  
            bc.Method1();  
            bc.Method2();  
            // Output:  
            // Base - Method1  
            // Base - Method2  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in DerivedClass.  
            dc.Method1();  
            dc.Method2();  
            // Output:  
            // Derived - Method1  
            // Derived - Method2  
  
            // The following two calls produce different results, depending
            // on whether override (Method1) or new (Method2) is used.  
            bcdc.Method1();  
            bcdc.Method2();  
            // Output:  
            // Derived - Method1  
            // Base - Method2  
        }  
    }  
  
    class BaseClass  
    {  
        public virtual void Method1()  
        {  
            Console.WriteLine("Base - Method1");  
        }  
  
        public virtual void Method2()  
        {  
            Console.WriteLine("Base - Method2");  
        }  
    }  
  
    class DerivedClass : BaseClass  
    {  
        public override void Method1()  
        {  
            Console.WriteLine("Derived - Method1");  
        }  
  
        public new void Method2()  
        {  
            Console.WriteLine("Derived - Method2");  
        }  
    }  
}  
给妤﹃绝世温柔 2024-07-13 04:24:49

我总是发现这样的事情用图片更容易理解:

再次,采用 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 类型的变量中(这类似于强制转换它)

那么结果将如下所示,具体取决于是否您在声明类时使用了virtual/overridenew

虚拟/覆盖解释图片

I always find things like this more easily understood with pictures:

Again, taking joseph daigle's code,

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

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

If you then call the code like this:

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

NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)

Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.

Virtual/Override explanation image

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文