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

时间:2022-06-05 00:37:35

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?

在基类型“virtual”中声明方法然后使用“override”关键字在子类型中覆盖它而不是在声明子类型中的匹配方法时简单地使用“new”关键字之间有什么区别?

10 个解决方案

#1


173  

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

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

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

这打印为false,如果你使用了覆盖它会打印为true。

(Base code taken from Joseph Daigle)

(基本代码取自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.

所以,如果你正在做真正的多态性,你应该总是超越。您需要使用“new”的唯一地方是该方法与基类版本无关。

#2


216  

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)

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

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

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

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

#3


40  

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

#4


18  

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

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

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.

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

#5


9  

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.

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

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

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

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

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告诉编译器您要向派生类添加一个方法,该方法与基类中的方法同名,但它们彼此没有关系。

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

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

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

(new SubClass()).NewBar()

Will call the SubClass's NewBar() method.

将调用SubClass的NewBar()方法。

#6


8  

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.

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

#7


4  

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

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

Check out the folllowing links for more information...

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

MSDN and Other

MSDN和其他

#8


3  

  • 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.
  • 重写以覆盖。 - 表示您使用基类的引用调用派生类方法。输出将基于派生类方法。

#9


1  

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.

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

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

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

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

Bar bar只有1,因为它想要GetSomething的全新行为。

#10


0  

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

使用new in derived class标记基类虚方法意味着:这是一个新方法,与基类中具有相同名称的方法无关,应该使用对象的编译时类型(静态绑定)进行绑定。

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

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

#1


173  

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

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

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

这打印为false,如果你使用了覆盖它会打印为true。

(Base code taken from Joseph Daigle)

(基本代码取自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.

所以,如果你正在做真正的多态性,你应该总是超越。您需要使用“new”的唯一地方是该方法与基类版本无关。

#2


216  

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)

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

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

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

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

#3


40  

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

#4


18  

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

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

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.

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

#5


9  

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.

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

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

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

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

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告诉编译器您要向派生类添加一个方法,该方法与基类中的方法同名,但它们彼此没有关系。

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

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

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

(new SubClass()).NewBar()

Will call the SubClass's NewBar() method.

将调用SubClass的NewBar()方法。

#6


8  

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.

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

#7


4  

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

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

Check out the folllowing links for more information...

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

MSDN and Other

MSDN和其他

#8


3  

  • 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.
  • 重写以覆盖。 - 表示您使用基类的引用调用派生类方法。输出将基于派生类方法。

#9


1  

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.

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

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

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

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

Bar bar只有1,因为它想要GetSomething的全新行为。

#10


0  

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

使用new in derived class标记基类虚方法意味着:这是一个新方法,与基类中具有相同名称的方法无关,应该使用对象的编译时类型(静态绑定)进行绑定。

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

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