通常,构造函数是在实例化时在类中执行的第一件事。
但是在下面的情况下,首先执行该类的成员方法&然后是构造函数。
为什么会这样?
代码场景:
namespace AbsPractice
{
class Program
{
static void Main(string[] args)
{
SavingsCustomer sc = new SavingsCustomer();
CorporateCustomer cc = new CorporateCustomer();
}
}
public abstract class Customer
{
protected Customer()
{
Console.WriteLine("Constructor of Abstract Customer");
Print();
}
protected abstract void Print();
}
public class SavingsCustomer : Customer
{
public SavingsCustomer()
{
Console.WriteLine("Constructor of SavingsCustomer");
}
protected override void Print()
{
Console.WriteLine("Print() Method of SavingsCustomer");
}
}
public class CorporateCustomer : Customer
{
public CorporateCustomer()
{
Console.WriteLine("Constructor of CorporateCustomer");
}
protected override void Print()
{
Console.WriteLine("Print() Method of CorporateCustomer");
}
}
}
答案 0 :(得分:6)
那是因为当你打电话给SavingsCustomer
ctor时,首先要调用它的基类ctor;在Customer
ctor中,您致电Print
,这是一种被覆盖的方法
因此,在执行SavingsCustomer
ctor指令之前,必须完全调用Customer
ctor。
请注意,当您从Print
致电Customer
时,会执行SavingsCustomer.Print()
。
这是预期的行为;如果您希望类的行为不同,则必须更改其逻辑。也许你不应该从基础构造函数中调用抽象方法,只是为了避免你现在看到的......
答案 1 :(得分:1)
除非你有充分的理由,否则你永远不应该这样做。
从构造函数中调用虚方法是一种等待发生的灾难。
在C#对象构造中遵循类层次结构顺序;也就是说,当调用构造函数时,首先调用最基类的构造函数,然后调用直接派生的类构造函数,然后调用下一个等等(如果我没有记错的话,在C ++中它是另一种方式可以导致更加混乱)。
因此,当您从构造函数中调用虚方法时,实际发生的是虚方法(如果被覆盖(在您的情况下是保证))将在调用实现类构造函数之前执行。这意味着该方法可以在对象的状态被正确初始化之前执行(通常通过构造函数;如果方法不依赖于任何对象状态,那么这种模式不是问题,尽管我仍然不推荐它)。 / p>
如果绝对有必要使用此模式,那么良好实践建议实施Initialize()
方法并在那里进行任何虚拟调用。在使用对象之前强制消费者调用Initialize
是一项微不足道的任务,您可以保证在进行虚拟调用时对象的状态始终有效。
答案 2 :(得分:0)
棘手的问题。当你创建像这样的对象时
SavingsCustomer sc = new SavingsCustomer();
它调用 Customer [class SavingsCustomer ]的构造函数,意味着 Customer() - 由于 Customer 类中的抽象,它从类 SavingsCustomer 调用 Print()。 虽然它是 SavingsCustomer 的成员函数,但在调用 SavingsCustomer 的构造函数之前,可以从 Customer 类调用它,然后运行 Print()被声明为抽象方法,因此由这两个类共享。
以下声明中也是如此
CorporateCustomer cc = new CorporateCustomer();
来自 CorporateCustomer 类的打印(),因为 SavingsCustomer.Print()被覆盖