Подтвердить что ты не робот

Есть ли способ инициализировать элементы структуры без использования конструктора?

У меня есть 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
...

Поскольку structs не может иметь конструкторы без параметров, я не могу просто установить это в конструкторе. До сих пор я могу видеть только следующие варианты:

  • Инициализировать оба свойства при создании экземпляра MonthData​​li >
  • Используйте класс вместо struct
  • Создайте конструктор с параметром и используйте
  • Создайте геттеры и сеттеры для свойств, которые их инициализируют лениво.

Каков рекомендуемый подход для этого? Прямо сейчас, я думаю, что создание этого класса - лучшая идея.

4b9b3361

Ответ 1

Вместо этого вы должны использовать класс. Из MSDN:

В общем, классы используются для моделирования более сложного поведения или данных, которые должны быть изменены после создания объекта класса. Структуры лучше всего подходят для небольших структур данных, которые содержат в основном данные, которые не предназначены для модификации после создания структуры.

Ответ 2

Если вы просто спрашиваете о синтаксисе... попробуйте создать и использовать статический factory вместо этого... В общем, структуры должны использоваться для вещей, которые являются неизменяемыми, и factory (который вызывает частный конструктор) - лучший подход к неизменяемому типу, чем использование публичного конструктора.

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

Ответ 3

В любом случае вы используете ссылочные типы (List<T>) в своей структуре, поэтому использование структуры как типа значения не имеет для меня никакого смысла. Я бы просто пошел с классом.

Ответ 4

Нет никакого способа сделать это с помощью конструктора. 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>();
    }
  }
}

Ответ 5

Было бы неплохо, если бы CLR дала возможность гарантировать, что на вещи типа структуры может быть запущен некоторый код инициализации, прежде чем они станут видимыми для чего-либо вне такого кода. Это можно было бы сделать даже при создании массива типа структуры, поскольку CLR передавал по ссылке все отдельные элементы массива до того, как ссылка на сам массив была открыта где угодно. К сожалению, это привело бы к неловкой ситуации, если бы исключение было выброшено во время создания массива. Если у конструкторов не было никаких побочных эффектов, проблем не возникло бы - просто отбросьте массив и притворись, что даже успешно созданные объекты никогда не существовали. Однако конструкторы с побочными эффектами могут вызвать некоторые трудности.

Однако, как бы то ни было, нет возможности инициализировать структуры при построении и, следовательно, не имеет никакого хорошего способа получить семантику значения-типа с объектами, требующими инициализации. Сожалею. Даже если семантика значения-типа будет более подходящей для вашего типа (как это было бы гораздо чаще, чем некоторые полагают), вам потребуется использовать ссылочный тип, если требуется инициализация. Ленивая инициализация структур не работает. Например, если у вас есть словарь < String, MonthData > называемый MyDict, повторный доступ к MyDict ( "Джордж" ). FrontLine будет генерировать новый список. Противный.

Переменные структуры не являются злыми; Я, во всяком случае, один из их сильных адвокатов. Тем не менее, существуют некоторые ограничения в .net-обработке изменчивых структур, и, следовательно, существует множество условий, при которых семантика значения-типа будет подходящей, но ограничения .net делают невозможным правильное предоставление такой семантики.