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

我有一个包含两个列表的struct

 struct MonthData { public List Frontline; public List Leadership; } 

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

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

然后我得到:

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

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

  1. 在创建MonthData实例时初始化这两个属性
  2. 使用类而不是结构
  3. 使用参数创建构造函数并使用它
  4. 为懒惰初始化它们的属性创建getter和setter。

推荐的方法是什么? 现在,我在想这个课程是最好的主意。

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

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

你无论如何都在你的struct中使用引用类型( List ),因此使用struct作为值类型对我没有任何意义。 我只是去上课。

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

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

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

例如:

 struct MonthData { private bool m_initialized; private List m_frontLine; private List m_leaderShip; public List FrontLine { get { EnsureInitialized(); return m_frontLine; } } public List LeaderShip { get { EnsureInitialized(); return m_leaderShip; } } void EnsureInitialized() { if (!m_initialized) { m_initialized = true; m_frontLine = new List(); m_leaderShip = new List(); } } } 

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

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

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