C#中用于常量字段的继承修饰符"new"

3
今天我了解到我们可以将new继承修饰符应用于const字段。我已经在普通字段和方法中使用过,它们对我来说很有意义,因为它们参与继承层次结构。我尽我最大努力理解这个关键字适用于const字段的适用性,但没有成功。以下是我想到的一些事情:
继承和运行时多态在普通(非静态)类中有意义。const字段默认为静态。此外,在C#中,静态类不支持继承。
假设我有两个如下所示的类:
class MyClass1
{
    public const string PI = "3.14";
}

class MyClass2 : MyClass1
{
    public const string PI = "3.141";   
}

对于外部世界来说,他们总是使用ClassName.FieldName的语法访问这些类中的常量,例如MyClass1.PIMyClass2.PI。因此,对于外部世界来说,如果MyClass1和MyClass2通过继承层次结构相关,则并不重要。MyClass1.PI获得3.14,MyClass2.PI获得3.141。

如果我在MyClass2的实例方法中(如下所示),则类完全知道他是使用自己类的静态成员还是基类的静态成员。如果他正在引用基类的静态字段,则使用MyClass1.PI语法。没有任何内容会在运行时解决。

class MyClass2 : MyClass1
{
    public const string PI = "3.141";
    string GetValueOfPi()
    {
        return PI;
    }

    string GetValueOfPiFromBaseClass()
    {
        return MyClass2.PI; //It clearly uses the syntax for accessing a static field of its base type
    }
}

因此,我无法弄清楚new继承修饰符对于常量字段的用法/相关性/重要性。在代码段#1中,解析器明确地给出以下警告:
“‘MyClass2.PI’隐藏了继承的成员‘MyClass1.PI’。如果有意隐藏,请使用new关键字。”
但是,如果我不使用new继承访问修饰符(即如果我不修复警告),消费者代码将会感到困惑、破裂或陷入问题的情况是什么?有人能帮助我理解其中涉及的概念吗?

也许是因为 const 变量可以通过类名和实例名访问? - Ian H.
const 是静态字段的一种形式。因此,对于 const 字段,同样适用相同的规则。如果您想要消除警告,请使用 new 关键字。 - M.kazem Akhgary
1
可能是“static new”修饰符的作用是什么?的重复问题。 - M.kazem Akhgary
2个回答

1

如果您的派生类有一个常量,您希望有不同的实现。对于const,只有使用new关键字才能发生这种情况。对于方法/属性,您可以在基类中将其定义为虚拟,并在派生类中重写它或再次使用new。新和覆盖都有不同的工作方式,但这不是您问题的一部分:了解何时使用Override和New关键字,如果您想了解何时使用它。

关于您的警告:如果您不指定new,则生成的输出与指定new相同,但您还会收到编译器警告(因为您可能不知道您正在隐藏基类方法并仅忘记包含该关键字)。


1
“但是,如果我不使用新的继承访问修饰符(即如果我不修复警告),哪些消费者代码将会混淆、中断或遇到问题呢?” 警告告诉你,如果任何代码引用 MyClass1.PI,则可能错误地期望使用 MyClass2.PI。假设我们将 GetValueOfPi 移动到基类:
class MyClass1
{
    public const string PI = "3.14";
    public string GetValueOfPi() { return PI; }
}
class MyClass2 : MyClass1
{
    public const string PI = "3.141";
}

现在,new MyClass2().GetValueOfPi()将返回"3.14",而不是"3.141"。从代码中无法确定编写者是否有意这样做。通过添加new关键字,您只是告诉编译器“是的,这确实是我想要的”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接