有没有办法在不使用构造函数的情况下初始化结构的成员?

时间:2011-11-16 20:13:05

标签: c# struct

我有struct,其中包含两个列表:

struct MonthData
{
   public List<DataRow> Frontline;
   public List<DataRow> Leadership;
}

但是,我想在创建结构时初始化它们。如果我尝试:

struct MonthData
{
   public List<DataRow> Frontline = new List<DataRow>();
   public List<DataRow> Leadership = new List<DataRow>();
}

然后我得到:

Error   23  'MonthData.Frontline': cannot have instance field initializers in structs
...

由于结构不能有无参数构造函数,我不能只在构造函数中设置它。到目前为止,我只能看到以下选项:

  1. 在创建MonthData实例
  2. 时初始化这两个属性
  3. 使用类而不是结构
  4. 使用参数创建构造函数并使用
  5. 为初始化它们的属性创建getter和setter 懒惰地。
  6. 建议的方法是什么?现在,我在想这个课程是最好的主意。

5 个答案:

答案 0 :(得分:7)

你应该使用一个班级。来自MSDN

  

通常,类用于建模更复杂的行为,或者在创建类对象后要修改的数据。结构最适合于小数据结构,主要包含在创建结构后不打算修改的数据。

答案 1 :(得分:7)

如果您只是询问语法...尝试构建和使用静态工厂...通常,结构应该用于不可变的东西,而工厂(调用私有构造函数)是对于不可变类型而言,比使用公共构造函数更好。

  struct MonthData 
  {    
      public List<DataRow> Frontline;
      public List<DataRow> Leadership; 
      private MonthData(List<DataRow> frontLine = null, 
                        List<DataRow> leadership = null)
      { 
         Frontline = frontLine?? new List<DataRow>();
         Leadership = leadership?? new List<DataRow>();  
      }
      public static MonthData Factory(
          List<DataRow> frontLine= null, 
          List<DataRow> leadership= null)
      { return new MonthData(frontLine, leadership); }
  } 

答案 2 :(得分:7)

你在结构中使用引用类型(List<T>),因此使用结构作为值类型对我没有任何意义。我只是去上课。

答案 3 :(得分:1)

使用构造函数无法执行此操作。 CLR可以并且将创建结构的实例,只需将零初始化内存并避免任何ctor开销。但是,您可以利用此知识并创建具有相同可观察效果的延迟初始化属性。

例如:

struct MonthData {  
  private bool m_initialized;
  private List<DataRow> m_frontLine;
  private List<DataRow> m_leaderShip;

  public List<DataRow> FrontLine {
    get {
      EnsureInitialized(); 
      return m_frontLine;
    }
  }

  public List<DataRow> LeaderShip {
    get {
      EnsureInitialized(); 
      return m_leaderShip;
    }
  }

  void EnsureInitialized() {
    if (!m_initialized) {
      m_initialized = true;
      m_frontLine = new List<DataRow>();
      m_leaderShip = new List<DataRow>();
    }
  }
}

答案 4 :(得分:1)

如果CLR允许保证结构类型的东西在它们对这些代码之外的任何东西可见之前可以运行一些初始化代码,那将是很好的。即使在创建结构类型的数组时,也可以这样做,方法是在对数组本身的引用暴露在任何地方之前让CLR通过引用传递数组的所有单个元素。不幸的是,如果在创建数组期间抛出异常,它将导致一种尴尬的情况。如果构造函数没有任何副作用,那就没有问题 - 只需丢弃数组并假装即使成功创建的对象也不存在。然而,具有副作用的构造者可能会造成一些困难。

但是,实际上,没有办法在构造时初始化结构,因此没有很好的方法来实现需要初始化的对象的值类型语义。抱歉。即使值类型语义更适合您的类型(例如,比某些人认为的更常见),如果需要初始化,则必须使用引用类型。结构的延迟初始化并不真正起作用。例如,如果有一个Dictionary&lt; String,MonthData&gt;调用MyDict,重复访问MyDict(“George”).FrontLine将生成一个新的List。讨厌。

可变结构不是邪恶的;如果有的话,我是他们更强大的倡导者之一。尽管如此,.net处理可变结构存在一些限制,因此有许多情况下值类型语义是合适的,但.net限制使得无法正确提供这样的语义。