【问题标题】:Stop derived class from being initialized停止初始化派生类
【发布时间】:2012-03-20 20:02:20
【问题描述】:

我有一个基类,我想在初始化派生类之前用它做一些检查..

class BaseClass
{
    public BaseClass(Object Param)
    {
        // Do checks
    }
}

我也(当然)有派生类

class NewClass : BaseClass
{
    public NewClass(Object Param) : base(Param)
    {
        // Code here
    }
}

现在,我想遇到如下情况

如果基类中的检查失败,那么我希望派生类中的代码(// 这里的代码)根本不被执行。

这可能吗?如果是,如何?

【问题讨论】:

    标签: c# class base


    【解决方案1】:

    不要写“vexing exception”。 派生类必须有办法知道基类ctor是否会抛出。否则,派生类的作者无法轻松防止错误。 p>

    正确的做法是 (1) 让派生类的调用者很容易知道异常是否将被抛出,并且 (2) 如果他们弄错了。让向您传递不良数据感到痛苦,并轻松避免这种痛苦,并且您最终将永远不会抛出该异常,因为您的派生类将避免这种痛苦。

    【讨论】:

      【解决方案2】:

      你能做的最好的就是让基类构造函数抛出一个异常。

      【讨论】:

        【解决方案3】:

        有没有可能,是的,只是抛出一个异常。然后你可以确定派生类的代码不会被调用。这是个好主意吗?也许,但可能不是。在构造函数中抛出异常被认为是不好的形式。

        一个不那么平均的选择是在基类构造函数中设置一个受保护的字段/属性isValid。然后派生类只能做if(isValid) 的事情。只要您知道自己会与自己相处融洽,就可以了。

        【讨论】:

        • 抛出构造函数是否被认为是不好的形式?我听说拥有一个僵尸对象(一个初始化失败的对象)被认为是不好的形式。投入构造函数对我来说更有意义,那样你就无法避免,只能处理它,如果你必须在任何地方检查isValid,它会变得很麻烦并且容易出错。如果isValid 是假的,你应该怎么做?
        • 嗯,这取决于具体情况。请注意,我并不是说你永远不应该抛出构造函数,它更多地表明了一些潜在的设计问题,你应该考虑重新设计类的可能方法。例如,也许你试图在构造函数中做太多事情。也许应该调用某种 Init 方法,或者您只是在做某种属于构造函数之外的方法的工作。如果没有,那么继续抛出异常。
        • 至于 isValid,这更像是针对所提出问题的技术解决方案,如果没有更多细节,我无法真正说出它的适当性/用途。
        • 问题是基类应该从多个(很多!)其他类中实现,所以我认为在每个类中都有'IsValid'有点难看......它在这一点上使用异常会更好,我想......
        【解决方案4】:

        如果检查失败,您可以让基本构造函数抛出异常。

        您可以实现所谓的空对象模式,其中您有一个内部isValid 成员。您可以根据您在基本构造函数中的检查将其设置为false,如果isValid 为假,您的所有方法都不会执行任何操作。

        最好的方法是使用工厂模式,这也消除了对异常的需要。只需将对象创建委托给工厂对象/方法,该工厂对象/方法执行检查并根据您的检查创建或不创建派生对象。

        【讨论】:

        • 你能解释一下这个工厂模式吗?谢谢
        • @user1264377:一种简单的方法:避免使用公共构造函数并拥有一个调用构造函数的公共方法。此方法将执行验证,如果验证失败,将返回 null。就个人而言,我宁愿让验证方法公开并抛出异常(不应该不被捕获 - 调用者将调用这些方法以保证不会发生异常),这可能符合Eric Lippert's Advice。但是,Andrei 的解决方案将验证与对象创建更紧密地联系在一起,这可能是您想要的。
        【解决方案5】:

        是的,这是可能的,只是抛出一个异常。对象的创建会立即失败,派生的构造函数也不会运行。

        【讨论】:

          【解决方案6】:

          在基类中检查代码后,在基类中设置一个属性值。您可以在子类中访问它并决定是否继续

          class BaseClass
          {
              public bool IsValid {set;get;}
              public BaseClass(Object Param)
              {
                  // Do checks and set the value of property
                   this.IsValid=false; // or true
              }
          }
          
          class NewClass : BaseClass
          {
              public NewClass(Object Param) : base(Param)
              {
                  if(this.IsValid)
                  {
                    // Code here
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2020-08-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-12-03
            • 2015-10-23
            • 1970-01-01
            • 2015-03-04
            • 1970-01-01
            相关资源
            最近更新 更多