Использование List в структуре
Делаю учебную задачу. По требованию задачи необходимо использовать структуры (классы еще не проходили). Создал следующую структуру:
public struct Workers
{
public const int MAX_WORKERS_IN_DEP = 1_000_000;
/// <summary>
/// Список сотрудников
/// </summary>
private List<Worker> _workers;
/// <summary>
/// Кол-во сотрудников
/// </summary>
public int Count => _workers.Count;
}
С удивлением обнаружил, что при использовании структур нельзя использовать конструктор по умолчанию. И это первый вопрос - почему так? Но поскольку нужно инициализировать List, накостылил следующим образом:
public void Initialization()
{
_workers = new List<Worker>();
}
Второй вопрос: а как Вы решаете подобные задачки?
Ответы (1 шт):
С удивлением обнаружил, что при использовании структур нельзя использовать конструктор по умолчанию.
Всё из-за того как структура существует в памяти. Она значимый тип, она не может быть null, она копируется при присваивании...
Когда вы делаете:
Workers workers1 = new Workers();
Workers workers2;
Фактически вы делаете одно и то же.
При при создании структуры без параметров по-сути не запускается никакой конструктор, структура может тупо копироваться из шаблона. А если в ней будут проинициализированы ссылочные поля - будет вакханалия, все свежесозданные структуры будут ссылаться на один и тот-же объект, как лист.
Обходной путь вы сами и представили. Но можно всё-таки использовать конструктор с параметрами или делать List публичным.
Второй вопрос: а как Вы решаете подобные задачки?
Да так и решаем, я бы предпочёл делать подобные поля публичными и инициализировать следующим образом:
Workers workers = new Workers() { _workers = new List<Worker>() };
Но можно и немножечко лайфхакнуть:
public struct Workers
{
public const int MAX_WORKERS_IN_DEP = 1_000_000;
private List<Worker> _workers_inside;
private List<Worker> _workers => _workers_inside != null ? _workers_inside : _workers_inside = new List<Worker>();
public int Count => _workers.Count;
}
В данном случае мы имеем реальный _workers_inside и get на него, который его и создаёт в случае если он null;