繁体   English   中英

C#中的类转换

[英]class casting in c#

这是C#代码

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
}

输出

Console.WriteLine(((A)clB).Foo()); // output 5 <<<--
Console.WriteLine(((A)clB).Bar()); // output 1

我们如何获得这个输出。任何人都可以在这里解释类转换过程。

更新:

以及这如何显示阴影和替代之间的区别

我假设

var clB = new B();

FooBar方法之间的区别在于,尽管Bar使用继承和多态性来决定要调用的实现,但是Foo方法隐藏了其原始实现。

A.Foo()A.Foo()B.Foo()完全无关,它们恰好具有相同的名称。 当编译器看到类型A的变量调用Foo它将进入并执行A.Foo() ,因为该方法不是虚拟的,因此无法覆盖它。 类似地,当看到调用Foo B类型的变量时,它将执行B.Foo() ,而不管该变量中包含的实例的实际类型如何。

另一方面, Bar方法被定义为虚拟方法,并且继承的类可以(并且应该)重写其实现。 因此,无论何时调用Bar ,无论它来自声明为AB的变量,都必须在调用对象本身的层次结构中将实际调用的方法作为“最新”实现来查找。来自用于引用对象的变量类型的影响。

在类B ,您将引入一个new方法Foo ,其名称和签名与已有方法相同(从A继承)。 因此, B有两个同名方法。 如果可以避免,那不是您要做的事情。

Foo被调用的两种方法中的哪一种取决于所使用的变量或表达式(类型AB )的编译时类型。

相反,方法Barvirtual B只有一种方法Bar 无论表达式的编译时类型是什么,总是会调用“正确”的覆盖。

写作

((A)clB).Foo()

就像说“对待clB好像它是一个A (如果可以)并给我Foo()的结果”一样。 由于A具有非虚拟Foo方法,因此它将执行A.Foo 由于BFoo方法是“ new ”方法,因此在这种情况下不使用它。

写作

((A)clB).Bar()

相似-“将clB当作A对待(如果可以的话),然后给我Bar()的结果”。 现在A具有虚拟的 Bar方法,这意味着可以在基类中覆盖它。 由于该对象实际上B ,它具有Foo()overrideB.Foo()将改为调用B.Foo()

var clB = new B();
//Uses B's Foo method
Console.WriteLine(clB.Foo());    // output 1
//Uses A's Foo method since new was use to overload method
Console.WriteLine(((A)clB).Foo()); // output 5
//Uses B's Bar Method
Console.WriteLine(clB.Bar());    // output 1
//Uses B's Bar Method since A's Bar method was virtual
Console.WriteLine(((A)clB).Bar()); // output 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM