【问题标题】:Why the constructor get called in the reverse order?为什么构造函数以相反的顺序被调用?
【发布时间】:2010-10-04 09:03:15
【问题描述】:

在继承中,为什么基类构造函数首先得到调用,为什么派生的没有??

【问题讨论】:

标签: c# .net c#-4.0


【解决方案1】:

确保基类的公共或受保护成员在派生类中使用之前已正确初始化。
准确地说,派生类构造函数首先运行,隐式调用基类构造函数,编译器作为派生类构造函数主体中的第一条语句插入(假设默认无参数构造函数)。

【讨论】:

    【解决方案2】:

    派生类是通过扩展基类创建的。应确保基类成员已正确初始化,然后才能在派生类中扩展。此外,在派生类中初始化的成员不应被基类覆盖。

    【讨论】:

      【解决方案3】:

      想想如果反过来会发生什么。让我们想象一个具有_id 值的用户类。 0 的_id 是一个特殊值,代表“来宾”帐户(忽略围绕“特殊值”的问题,首先它们并不总是一个坏主意,其次这只是一个示例)。 _id 在构造后也不能更改(这是有道理的,如果它可以更改,它不再是一个真正的标识符)。

      public class User
      {
        private readonly int _id;
        public User(int id)
        {
          _id = id;
        }
        public int ID
        {
          get { return _id; }
        }
        public bool IsGuest
        {
          get { return _id == 0; }
        }
      }
      

      现在考虑一个继承自这个的 Admin 类。 Admin 类的规则之一是访客永远不能成为管理员。这个不变量应该在客人状态可以改变的所有点上强制执行,在这种情况下只在构造函数中:

      public class Admin : User
      {
        public Admin(int id)
          :base(id)
        {
          if(IsGuest)
            throw new SecurityException("Guest users cannot be admins.");
        }
      }
      

      如果 Admin 是在 User 之前构造的,那么它总是会抛出这个异常,因为测试总是将 0 与 0 进行比较。如果我们为客人设置不同的特殊值,那就更糟了,永远不会抛出即使应该出现异常,也允许出现安全问题。

      还要记住,编写Admin 类的人不需要了解User 的工作原理,而不仅仅是关于其公共和受保护接口的文档。他们可以通过添加自己的id 是否为零的测试来解决上述问题,但除了这是不必要的代码重复之外,他们没有理由知道IsGuest 检查是如何工作的,而且它可以比上面的要复杂得多,也许是专有的、混淆的和无证的。

      更一般地说,如果没有“构造用户”的概念作为先发生的事情,“构造管理员”的整个概念是没有意义的,如果不将 X 设置为一个先决条件。

      【讨论】:

        【解决方案4】:

        什么先出生,父母还是孩子?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-13
          • 2014-01-28
          • 1970-01-01
          相关资源
          最近更新 更多