【问题标题】:Instance initialization strategy in c#c#中的实例初始化策略
【发布时间】:2010-03-10 13:06:07
【问题描述】:

为了一个类实例正常工作,一些字段应该被正确初始化,你初始化这些字段的策略是什么,应该通过构造函数给出什么,应该通过属性给出什么?

我的困惑是,如果构造函数需要很长的参数列表,很难使用,如果通过属性,我往往会忘记设置一些属性。

最佳做法是什么?

【问题讨论】:

  • 有时,当你发现构造函数列表很长时,类(类型)做得太多了。当然,有时这是不可避免的......

标签: c# initialization properties


【解决方案1】:

你必须问自己,如果你的类需要创建那么多东西,也许它做的太多了。这表明您应该重新考虑您的设计,或者构造函数正在做多少“工作”。

确实,您不应该能够创建具有无效状态的实例;因此构造函数应该获取所有你需要的属性 in 一个有效的状态。

在某种程度上,这取决于您的模型。例如,我使用的 ORM 的构造函数带有一个参数;一个 ID,它可以通过它加载所有其他属性。如果我必须将它们全部传递进去,那会很烦人(这确实是 ORM 的工作;设置这个对象)。所以从这个意义上说,你可以说你有一个“无效”的对象(没有设置属性)。但你错了;您实际拥有的是“空白”或“空”对象。这不等于无效。

因此,请仔细考虑您的对象“无效”意味着什么。如果其他方法采用此对象,我会认为它无效,并且由于未设置某些内容而引发异常。使用此逻辑来确定构造函数中需要包含哪些内容,以及稍后可以设置哪些内容(通过其他进程)。

【讨论】:

    【解决方案2】:

    这始终是一种平衡行为 - 您不希望构造函数需要许多参数,但也不希望用户在对象处于有效状态之前设置许多属性。不幸的是,这里没有真正的指导,因为您必须根据手头的情况做出最佳判断。

    很多时候您可能需要创建一个具有许多属性和许多可能配置的复合类型(例如System.Web.Page)。复合类型往往具有简单的构造函数,它们接受很少或不接受参数,并且所有值都必须通过属性设置。复合类型是由低级分解(或原始)类型组成的高级类型。

    因子类型往往更简单,包含更少的状态,并且可以通过它们的构造函数完全初始化。分解类型的示例是 System.StringSystem.Int32。这些类型非常简单,往往是复合类型的构建块。

    如果你的类型是分解类型,那么尽量让消费者通过构造函数完全初始化类型。如果您的类型是复合类型,那么最好提供带有很少或没有参数的简单构造函数,并要求使用者通过属性设置器配置实例。

    【讨论】:

    • +1。我会指出,在composite types 的情况下,您需要定义一个定义明确的合同,该合同确定必须设置哪些属性才能为实例提供其状态。把它记录下来。这样,一年后,该对象就不会被严重错误配置:)
    【解决方案3】:

    既然 .NET 3.5 允许您在创建时设置任何属性,我通常将任何带参数的构造函数限制为实例在创建时绝对必须具有值的情况。确实没有任何其他理由添加带有参数 IMO 的构造函数重载。

    【讨论】:

      【解决方案4】:

      我认为最好的办法是执行验证,并且通常尝试保持没有参数的构造函数,因为这通常是不同 .NET 库的要求。 p>

      通过验证,您必须检查对象的有效性,但这是很常见的事情。言外之意:

      public interface IValidateable {
        IEnumerable<string> Validate();
      }
      
      public class Person : IValidateable {
          public string Title { get; set; }
          public string First { get; set; }
          public string Last { get; set; }
          public Address HomeAddress { get; set; }
      
          public Person() {
            HomeAddress = new Address();
          }
      
      
          public IEnumerable<string> Validate() {
            var errors = new List<string>();
            if (string.IsNullOrEmpty(First))
              errors.Add("First name is required.");
            // And so on...
            return errors;
          }    
      }
      
      // Usage
      var p1 = new Person();
      var p2 = new Person {
          First = "Dmitriy"
        };
      
      if (p1.Validate().Any()) {
        // Do something with invalid object
      }
      

      【讨论】:

      • 如果该类不是商务类怎么办,也许我应该去检查和引发异常。
      猜你喜欢
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 2013-05-08
      • 2013-09-21
      • 2012-05-27
      • 2013-10-18
      • 1970-01-01
      • 2013-04-25
      相关资源
      最近更新 更多