为什么在构造函数之前调用类的成员方法

时间:2014-10-12 12:05:24

标签: c# oop inheritance abstract-class

通常,构造函数是在实例化时在类中执行的第一件事。

但是在下面的情况下,首先执行该类的成员方法&然后是构造函数。

为什么会这样?

代码场景:

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");
        }
    }
}

3 个答案:

答案 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()被覆盖