我发现了一些奇怪的东西,我没想到它会起作用,实际上是有效的。我可以访问一个子类'来自基类的(常数)财产'构造:
public abstract class Parent {
public Parent() {
var constName = ConstName; // <-- surprisingly, this works
var randomName = RandomName; // <-- surprisingly, this works
}
public abstract string ConstName { get; }
public abstract string RandomName { get; }
}
public class Child : Parent {
public override string ConstName { get { return "Mike"; } }
public override string RandomName { get { return new Random().Next().ToString(); } }
}
Name
是非静态属性而不是字段。我一直认为类型的初始值设定项(用于static
和const
字段)被执行,然后是基类的那些,然后是基本的ctor,然后是子类&#39;构造函数。 这意味着孩子在父母的陪伴下还没有完全构建。
这是&#34;合法&#34;在所有情况下都可以使用的C#?为什么这样做?
编辑:
不,这不是一个愚蠢的问题。那个人在我的问题中没有类模式。
答案 0 :(得分:4)
Parent有一个抽象属性Parent.Name。由于单词abstract,您保证(子类)Parent的实例将实现属性Name。如果他们不这样做,你就无法创造它的对象。
请注意,我说:无法创建实例。如果子类没有实现属性Name,则该类可以存在,但是您无法实例化它。
Class Parent没有实现属性Name,因此您无法实例化Parent。
然而,Class Child实现了Name,因此你可以实例化它,并且因为你承诺类Parent的每个对象(=实例化)都有一个属性Name,你可以肯定,尽管你所知道的只是它是一个Parent,你也知道它有一个名字。
这是子类型中多态的基本原理 Wikipedia about polymorphism
这可能是您想要进行子类化的主要原因。
答案 1 :(得分:3)
您可以访问子类型的抽象/虚拟成员。属性getter最终是方法。
但是
正如您所说,子类构造函数尚未执行。因此,它可能有副作用。这就是你从FxCop收到警告的原因。
public abstract class Parent
{
public Parent()
{
// NullReferenceException here:
var nameLength = Name.Length;
}
public abstract string Name { get; }
}
public class Child : Parent
{
private string name;
public Child()
{
name = "My Name";
}
public override string Name { get { return name; } }
}
更糟糕的是:
public class Child : Parent
{
private string name;
public Child()
{
name = "My Name";
}
public override string Name
{
get
{
// NullReferenceException here.
// You didn't expect that this code is executed before
// the constructor was, did you?
return name.Substring(0, name.Length - 1);
}
}
}
因此不建议这样做。