gpt4 book ai didi

c# - 这种继承特性的用例是什么?

转载 作者:IT王子 更新时间:2023-10-29 04:47:06 26 4
gpt4 key购买 nike

当继承一个被继承的类时,新的/覆盖的行为不是我所期望的:

$ 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

由于 C 类重写了 sayHi() 方法,我希望输出是 From C。为什么 B 类的 new 修饰符在这里优先?它的用例是什么?特别是因为它打破了让 C 真正覆盖 A 的明显用例。

请注意,上面的代码是在 Mono 2.10 上运行的,Mono 2.10 是在 Debian 派生的发行版上运行的。但我已经在 MS Visual Studio 中使用 C# 编译器确认了相同的行为。

最佳答案

new modifier导致成员隐藏,这会破坏类层次结构中的多态关系。 BSayHi 方法被视为与 A不同(而不是覆盖)(因此选择"new"一词作为关键字)。 C 的方法然后覆盖 B 的方法,而不是 A 的方法(它仍然隐藏)。

因此,当您通过 A 引用在 C 实例上调用 SayHi 时,运行时将根据 A 解析它 类型,而不是 C 类型(其中 SayHi 是从 B 继承的"new"方法)。

另一方面,如果您要运行:

B p = new C();
p.SayHi();

……你会得到预期的多态结果:

From C

编辑:由于您请求了一个用例,这里有一个。在 .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 + "\""; }
}
}

ObjectContainer 类的Item 属性返回一个普通的对象。但是,在 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

QuotedStringContainer类覆盖了StringContainerItem属性,继承了它的string返回类型;但是,它仍然object 隐藏 - 返回 ObjectContainerItem 属性。如果不是这样,就没有办法协调它们不同的返回类型……

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

关于c# - 这种继承特性的用例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11039414/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com