dot*_*hen 18 c# mono inheritance
继承继承的类时,new/override行为不是我所期望的:
$ cat Program.cs
using System;
class A {
public virtual void SayHi() {
Console.WriteLine("From A");
}
}
class B : A {
public new virtual void SayHi() {
Console.WriteLine("From B");
}
}
class C : B {
public override void SayHi() {
Console.WriteLine("From C");
}
}
public class Program {
public static void Main() {
A p = new C();
p.SayHi();
}
}
$ ./Program.exe
From A
Run Code Online (Sandbox Code Playgroud)
由于C类覆盖了sayHi()方法,我希望输出为From C.为什么B类的new修饰符优先于此?那是什么用例?特别是因为它打破了C真正覆盖A的明显用例.
请注意,上面的代码是在Debian派生的发行版上运行的Mono 2.10上运行的.但我已经使用MS Visual Studio中的C#编译器确认了相同的行为.
Dou*_*las 21
该new修改使成员隐藏,它打破在你的类层次结构中的多态性关系.该SayHi方法B被视为与s的不同(不是覆盖)A(因此选择单词"new"作为关键字).C的方法然后覆盖了B,而不是A(它仍然是隐藏的).
因此,当你调用SayHi一个C通过一个实例A参考,运行时会解决它针对A类型,而不是C类型(在其中SayHi是继承了"新"的方法B).
另一方面,如果你要跑:
B p = new C();
p.SayHi();
Run Code Online (Sandbox Code Playgroud)
...你会得到预期的多态结果:
From C
Run Code Online (Sandbox Code Playgroud)
编辑:由于您请求了一个用例,这里是一个.在.NET Framework 2.0中引入泛型之前,成员隐藏有时用作更改派生类中的继承方法的返回类型(在覆盖时无法执行的操作)以返回更多特定类型的方法.例如:
class ObjectContainer
{
private object item;
public object Item
{
get { return item; }
set { item = value; }
}
}
class StringContainer : ObjectContainer
{
public new virtual string Item
{
get { return base.Item as string; }
set { base.Item = value as string; }
}
}
class QuotedStringContainer : StringContainer
{
public override string Item
{
get { return "\"" + base.Item + "\""; }
}
}
Run Code Online (Sandbox Code Playgroud)
该类的Item属性ObjectContainer返回一个普通的object.但是,在StringContainer此中,隐藏此继承属性以返回string.从而:
ObjectContainer oc = new StringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since StringContainer.Item is now resolved
Run Code Online (Sandbox Code Playgroud)
本QuotedStringContainer类覆盖了Item财产StringContainer,继承了它的string返回类型; 然而,它仍然隐藏在 - object令人遗憾的Item财产中ObjectContainer.如果不是这样,就没有办法调和他们不同的回报类型......
ObjectContainer oc = new QuotedStringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
// (polymorphism!)
string s3 = ((QuotedStringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
Run Code Online (Sandbox Code Playgroud)