Is there a way to initialize members of a struct without using a constructor?

女生的网名这么多〃 提交于 2020-01-14 07:16:10

问题


I have a struct that contains two lists:

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

However, I want to initialize both when the struct is created. If I try:

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

Then I get:

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

Since structs cannot have parameterless constructors, I can't just set this in a constructor either. So far, I can only see the following options:

  1. Initialize both properties when I create an instance of MonthData
  2. Use a class instead of a struct
  3. Create a constructor with a parameter and use that
  4. Make getters and setters for the properties that initialize them lazily.

What is the recommended approach for this? Right now, I'm thinking making this a class is the best idea.


回答1:


You ought to use a class instead. From MSDN:

In general, classes are used to model more complex behavior, or data that is intended to be modified after a class object is created. Structs are best suited for small data structures that contain primarily data that is not intended to be modified after the struct is created.




回答2:


You're using reference types (List<T>) in your struct anyway, thus the usage of a struct as value type wouldn't make any sense to me. I'd just go with a class.




回答3:


If you're just asking about syntax... try building and using a static factory instead... In general, structs should be used for things that are immutable, and a factory, (which calls a private constructor) is a better approach for an immutable type than using a public constructor.

  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); }
  } 



回答4:


There is no way to do this with a constructor. The CLR can and will create instances of structs simply be zero initializing the memory and avoid any ctor overhead. However you can take advantage of this knowledge and create delay initialized properties which have the same observable effect.

For example:

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>();
    }
  }
}



回答5:


It would have been nice if the CLR had allowed a means of guaranteeing that things of structure type could have some initialization code run on them before they became visible to anything outside such code. It would have been possible to do that, even when creating an array of a structure type, by having the CLR pass by reference all the individual elements of the array before a reference to the array itself was exposed anywhere. Unfortunately, it would have led to an awkward situation if an exception were thrown during the creation of the array. If the constructors didn't have any side effects, there would be no problem--simply discard the array and pretend that even the successfully-created objects never existed. Constructors with side-effects, however, could cause some difficulties.

As it is, however, there's no way to initialize structures at construction, and consequently no nice way to achieve value-type semantics with objects requiring initialization. Sorry. Even if value-type semantics would be more appropriate for your type (as would be the case far more often than some would believe) you'll have to use a reference type if initialization is necessary. Lazy initialization of structs doesn't really work. For example, if one has a Dictionary<String, MonthData> called MyDict, repeated accesses to MyDict("George").FrontLine would each generate a new List. Nasty.

Mutable structs are not evil; I am, if anything, one of their stronger advocates. Nonetheless, there are some limitations in .net's handling of mutable structs, and there are thus many circumstances where value-type semantics would be appropriate, but .net limitations make it impossible to provide such semantics properly.



来源:https://stackoverflow.com/questions/8158038/is-there-a-way-to-initialize-members-of-a-struct-without-using-a-constructor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!