Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c类铸件#_C#_Asp.net_Oop_Casting - Fatal编程技术网

C# c类铸件#

C# c类铸件#,c#,asp.net,oop,casting,C#,Asp.net,Oop,Casting,这是c代码 产量 Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- Console.WriteLine(((A)clB).Bar()); // output 1 Console.WriteLine(((A)clB.Foo());//输出5我假设 var clB = new B(); Foo和Bar方法之间的区别在于Bar使用继承和多态性来决定调用什么实现,而Foo方法隐藏了它的原始实现 总之,一个词,a.Foo()和B

这是c代码

产量

Console.WriteLine(((A)clB).Foo()); // output 5 <<<--
Console.WriteLine(((A)clB).Bar()); // output 1
Console.WriteLine(((A)clB.Foo());//输出5我假设

var clB = new B();
Foo
Bar
方法之间的区别在于
Bar
使用继承和多态性来决定调用什么实现,而
Foo
方法隐藏了它的原始实现

总之,一个词,
a.Foo()
B.Foo()
是完全不相关的,它们只是碰巧有相同的名字。当编译器看到
a
类型的变量调用
Foo
时,它进入并执行
a.Foo()
,因为该方法不是虚拟的,所以无法重写。类似地,当它看到类型为
B
的变量调用
Foo
时,它执行
B.Foo()
,而不管变量中包含的实例的实际类型如何


另一方面,
Bar
方法被定义为virtual,继承类可以(并且应该)覆盖它的实现。因此,每当调用
Bar
,无论它来自声明为
a
B
的变量,实际调用的方法必须作为调用对象本身层次结构中的“最新”实现找到,不受用于引用对象的变量类型的影响。

在类
B
中,您引入了一个
新的
方法
Foo
,其名称和签名与已有的方法相同(继承自
a
)。所以
B
有两个同名的方法。如果你能避免的话,你是不会这么做的

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

相比之下,
Bar
方法是
virtual
。在
B
中只有一种方法
Bar
。无论表达式的编译时类型是什么,调用的总是“正确”的重写。

((A)clB).Foo()
((A)clB).Bar()
就像说“把
clB
当作
A
(如果可以的话)来对待,然后告诉我
Foo()的结果
”。因为
A
有一个非虚拟的
Foo
方法,所以它执行
A.Foo
。由于
B
Foo
方法是一种“
新的
”方法,因此在本例中不使用它

书写

((A)clB).Foo()
((A)clB).Bar()

类似-“将
clB
视为
A
(如果可以)并将
Bar()的结果告诉我。”。现在
A
有一个虚拟的
Bar
方法,这意味着它可以在基类中被重写。由于对象实际上是一个
B
,它对
Foo()
有一个
重写
,因此调用
B.Foo()

你用new重写
B
class
Foo
方法,因此它隐藏了class
a
@Romoku的
Foo方法:它根本不重写Foo。这就是重点。顺便说一句,在不使用new关键字的情况下,您将观察到相同的行为。@JonSkeet重载了,我很抱歉。@Romoku:甚至没有重载。你:这个方法不是虚拟的,所以它不能被继承,我想你的意思是“不能被重写”。所有方法都是由派生类型继承的(尽管其中一些方法可能无法访问(比如它们是
私有的
)。更详细地说,如果不指定
virtual
,则将其视为静态绑定,这意味着调用的方法实现是在编译时确定的。如果它是
虚拟的
,则它使用动态绑定,并在运行时根据实际对象实例确定调用的方法实现。@JeppeStigNielsen是的,这就是我的意思。实现是继承的,但更改它(覆盖)的权利不是继承的。您可以找到第二个问题的答案
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