【发布时间】:2010-10-20 16:53:57
【问题描述】:
在 C# 中,可以在派生类中重写常量吗?我有一组相同的类,除了一些常量值,所以我想创建一个定义所有方法的基类,然后在派生类中设置相关常量。这可能吗?
我宁愿不只是将这些值传递给每个对象的构造函数,因为我希望增加多个类的类型安全性(因为两个具有不同常量的对象进行交互是没有意义的)。
【问题讨论】:
标签: c# inheritance constants
在 C# 中,可以在派生类中重写常量吗?我有一组相同的类,除了一些常量值,所以我想创建一个定义所有方法的基类,然后在派生类中设置相关常量。这可能吗?
我宁愿不只是将这些值传递给每个对象的构造函数,因为我希望增加多个类的类型安全性(因为两个具有不同常量的对象进行交互是没有意义的)。
【问题讨论】:
标签: c# inheritance constants
不幸的是,常量不能被覆盖,因为它们不是虚拟成员。编译器在编译时将代码中的常量标识符替换为其文字值。
我建议您尝试将抽象或虚拟属性用于您想做的事情。它们是虚拟的,因此可以(在抽象属性的情况下必须)在派生类型中被覆盖。
【讨论】:
如果你想覆盖它,它不是一个常数;)。尝试虚拟只读属性(或受保护的 setter)。
只读属性:
public class MyClass {
public virtual string MyConst { get { return "SOMETHING"; } }
}
...
public class MyDerived : MyClass {
public override string MyConst { get { return "SOMETHINGELSE"; } }
}
受保护的设置器:
public class MyClass {
public string MyConst { get; protected set; }
public MyClass() {
MyConst = "SOMETHING";
}
}
public class MyDerived : MyClass {
public MyDerived() {
MyConst = "SOMETHING ELSE";
}
}
【讨论】:
标有const 的常量不能被覆盖,因为它们在编译时被编译器替换。
但是分配给常量值的常规静态字段可以。我刚才也遇到过这样的情况:
class Columns
{
public static int MaxFactCell = 7;
}
class Columns2 : Columns
{
static Columns2()
{
MaxFactCell = 13;
}
}
如果我只是在派生类中重新定义 MaxFactCell 字段,则多态将不起作用:使用 Columns2 作为 Columns 的代码将看不到覆盖值。
如果您需要限制对该字段的写入(但不是读取)访问,使用readonly 将禁止在Columns2 中重新定义它。改为属性,代码稍微多一点:
class Columns
{
static Columns()
{
MaxFactCell = 7;
}
public static int MaxFactCell { get; protected set; }
}
class Columns2 : Columns
{
static Columns2()
{
MaxFactCell = 13;
}
}
【讨论】:
Columns2.MacFactCell之前调用Columns2的static constructor,结果可能是7。此外,一旦调用了Columns2 构造函数(例如在创建第一个Columns2 实例时),Columns.MacFactCell 将显示为 13。
csc,正如您所说(代码是为 VS2008 和 .NET 3.5 编写的),但它似乎与文档直接矛盾!
MaxFactCell 似乎被认为是Columns 的成员,即使通过Columns2.MaxFactCell 访问时也是如此,因此不会调用Columns2 静态构造函数,这与文档一致。这是有道理的,因为您不能使用静态类进行继承。当 Columns2 继承 Columns 时,仅关注 Columns2 的 instances。
编辑:这可能会有意想不到的行为,请参阅下面 Shai Petel 的评论。
您可以通过声明新常量new 来隐藏派生类中继承的常量。不过,我不确定这是一个好习惯。
class A
{
protected const int MyConst = 1;
}
class B : A
{
new private const int MyConst = 2;
}
【讨论】:
instanceA.MyConst),需要写A.MyConst,这样就清楚了。但是,如果类A 有一个使用MyConst 的方法,并且该方法是从B 调用的,则它使用来自A 的MyConst 值。
解决 dten + Tracker1 的答案,但已针对 c# 6 进行了更新
public class MyClass {
public virtual string MyConst =>"SOMETHING";
}
...
public class MyDerived : MyClass {
public override string MyConst =>"SOMETHING ELSE";
}
【讨论】:
您可以强制派生类具有一个常量值(嗯,一个只读属性)
例子:
public interface IHasConstant
{
string MyConst { get; }
}
【讨论】: