C#中的阴影和覆盖之间的区别?


Difference between shadowing and overriding in C#?

在C中隐藏和重写方法有什么区别?


好吧,继承……

假设您有这些类:

1
2
3
4
5
6
7
8
class A {
   public int Foo(){ return 5;}
   public virtual int Bar(){return 5;}
}
class B : A{
   public new int Foo() { return 1;}     //shadow
   public override int Bar() {return 1;} //override
}

然后,当你称之为:

1
2
3
4
5
6
7
8
9
10
11
A clA = new A();
B clB = new B();

Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1

//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1

假设您有一个基类,并且您在所有代码中使用该基类而不是继承的类,并且您使用shadow,它将返回基类返回的值,而不是跟随对象的实际类型的继承树。

在这里运行代码

希望我说得有道理:)


阴影实际上是我们在C中所说的隐藏的VB语言。

通常隐藏(在vb中隐藏)和覆盖由stormenet响应。

一个虚拟方法会被一个子类覆盖,即使是在超级类类型上或从超级类的内部代码调用该方法,也会从子类调用替换实现。

然后,在子类上定义具有相同签名的方法时,使用new关键字显示隐藏的具体方法(未标记为虚拟或抽象)。在这种情况下,当对超级类类型调用方法时,将使用原始实现,新实现仅在子类上可用。

然而,经常忽略的是,也可以隐藏一个虚拟方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
    public virtual void DoStuff() { // original implementation }
}

class B : A
{
    public new void DoStuff() {  //new implementation }
}

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

b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.

注:在上述示例中,dostuff变为混凝土,不能覆盖。但是,也可以同时使用virtualnew关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
    public virtual void DoStuff() { // original implementation }
}

class B : A
{
    public new virtual void DoStuff() {  //new implementation }
}

class C : B
{
    public override void DoStuff() { //replacement implementation }
}

C c = new C();
B b = c;
A a = b;

c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.

注意,尽管所有涉及的方法都是虚拟的,但是C上的重写不会影响A上的虚拟方法,因为在B中使用new隐藏了A实现。

编辑:在对这个答案的评论中注意到,上面的内容可能很危险,或者至少不是特别有用。我会说是的,它可能很危险,如果有用的话,它就会出现在外面。

尤其是,如果您还更改了可访问性修饰符,可能会遇到各种各样的麻烦。例如:

1
2
3
4
5
6
7
8
9
10
public class Foo
{
    internal Foo() { }
    protected virtual string Thing() { return"foo"; }
}

public class Bar : Foo
{
 internal new string Thing() { return"bar"; }
}

对于Bar的外部继承者,Foo的thing()实现仍然是可访问和可重写的。根据.NET类型的规则,所有合法和可解释的内容永远都是毫无意义的。

我发布这个答案是为了加深对事物如何工作的理解,而不是作为可以自由使用的技术的建议。


我认为主要的区别是,使用阴影时,基本上是重用名称,而忽略了超类的使用。使用overriding,您将更改实现,但不会更改可访问性和签名(例如参数类型和返回)。请参阅http://www.geekinterview.com/questionu details/19331。


阴影是一个vb.net概念。在C中,阴影被称为隐藏。它隐藏派生类方法。它是使用"new"关键字完成的。

override关键字用于提供派生类中基类方法(标记为"virtual")的全新实现。


基本上,如果你有下面这样的东西,

1
2
3
4
5
6
7
8
9
Class A
{
}

Class B:A
{
}

A a = new B();

对对象"a"调用的任何方法都将在"a"类型(此处类型为"a")上进行。但是,如果在类B中实现的方法与类A中已经存在的方法相同,编译器将警告您使用"new"关键字。如果使用"新",警告将消失。除此之外,在继承类中使用"new"和不使用"new"没有区别。

在某些情况下,您可能需要调用引用类的方法,而不是调用对象类型上的方法。在上述情况下,它持有的引用是"b",但类型是"a"。因此,如果您希望方法调用应该发生在"b"上,那么您可以使用virtual和override来实现这一点。

希望这有帮助…

Daniel Sandeep。