C#中阴影和覆盖的区别?
隐藏和重写C#中的一个方法有什么区别?我认为主要的区别在于,使用隐藏时,基本上是重用名称,而忽略了超类的使用。通过重写,您可以更改实现,但不能更改可访问性和签名(例如参数类型和返回)。请参阅。井继承 假设您有以下类:C#中阴影和覆盖的区别?,c#,C#,隐藏和重写C#中的一个方法有什么区别?我认为主要的区别在于,使用隐藏时,基本上是重用名称,而忽略了超类的使用。通过重写,您可以更改实现,但不能更改可访问性和签名(例如参数类型和返回)。请参阅。井继承 假设您有以下类: class A { public int Foo(){ return 5;} public virtual int Bar(){return 5;} } class B : A{ public new int Foo() { return 1;} //sh
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
}
那么当你称之为:
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
A clA=newa();
B clB=新的B();
Console.WriteLine(clA.Foo());//产出5
Console.WriteLine(clA.Bar());//产出5
Console.WriteLine(clB.Foo());//产出1
Console.WriteLine(clB.Bar());//产出1
//现在让我们把B投给A班
Console.WriteLine(((A)clB.Foo());//输出5阴影实际上是VB术语,我们称之为隐藏在C#中
通常,隐藏(VB中的阴影)和覆盖如答案所示
虚拟方法显示为被子类重写,即使在超类类型上或从超类的内部代码调用该方法,也会从子类调用替换实现
然后,在定义子类上具有相同签名的方法时,通过使用new
关键字隐藏具体方法(未标记为虚拟或抽象的方法)。在这种情况下,当在使用原始实现的超类类型上调用该方法时,新实现仅在子类上可用
然而,经常被忽略的是,还可以隐藏虚拟方法
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变为混凝土,无法覆盖。但是,也可以同时使用virtual
和new
关键字
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实现
编辑:在对该答案的评论中指出,上述内容可能很危险,或者至少不是特别有用。我会说,是的,这可能是危险的,如果有用的话,它也会存在
特别是,如果同时更改可访问性修饰符,可能会遇到各种各样的麻烦。例如:-
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类型规则,所有合法且可解释的内容都不会完全不符合实际
我发布这个答案是为了加深对事物如何工作的理解,而不是作为一个可以自由使用的技术建议。基本上,如果你有如下内容
Class A
{
}
Class B:A
{
}
A a = new B();
您对对象“a”调用的任何方法都将对“a”类型(此处类型为“a”)进行生成
但是,如果您在类B中实现了类A中已经存在的相同方法,编译器将警告您使用“New”关键字。如果使用“新建”,警告将消失。除此之外,在继承的类中使用“New”与不使用它没有区别
在某些情况下,您可能需要调用特定实例当时持有的引用类的方法,而不是调用对象类型的方法。在上述情况下,它持有的引用是“B”,但类型是“A”。因此,如果您希望方法调用应该发生在“B”上,那么您可以使用Virtual和override来实现这一点
希望这有助于
Daniel Sandeep.阴影是一个VB.NET概念。在C#中,阴影被称为隐藏。它隐藏了派生类方法。它是使用“new”关键字完成的
Override关键字用于在派生类中提供基类方法(标记为“Virtual”)的全新实现。如果出现无法更改类内容的情况,比如说a
,但您希望使用它的一些方法以及一个通用名称的方法,您可以通过new
关键字使用自己的方法实现
关键是使用它,引用和对象必须是同一类型
class A
{
public void Test()
{
Console.WriteLine("base");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("sub");
}
public static void Main(string[] args)
{
A a = new A();
B aa = new B();
a.Test();
aa.Test();
}
}
覆盖提供多态性,阴影在该层次结构级别提供不同的实现,但不是多态性。@dribeas,您将使用什么多态性定义来得出这一结论?@AnthonyWJones,多态性是一个(派生)类型用作不同(基)的能力类型,其中实际实现(行为)是实际特定(派生)类型的实现(行为)。若重写,派生方法将通过对base的引用来调用,但若在我看来不是true,那个么示例代码中就有一个错误。强制转换应该是((A)clB.Foo(),不是吗?不,因为bar是虚拟的,所以它仍然会调用B BarNice来知道这一点。虽然它的使用可能是危险的:)所有工具如果使用不当都可能是危险的。但是,它的可用性似乎真的有问题!是否有任何“严肃”的开源应用程序使用此?可用性?你是说有用吗?有些边缘的东西在你需要之前可能看起来毫无用处。似乎只有在虚拟和新的游戏中才会出现阴影@Stormenet只是解释了重写的事情,因为类调用自己的方法是正常的行为,除非它是虚拟的。它隐藏派生类方法,而使用基类方法?