Как создать лист сразу с предзаполненными классами?
Мы можем создать лист:
List<MyClass> LC = new List<MyClass>();
MyClass представляет собой:
private class MyClass
{
public string A { get; set; };
public string B { get; set; };
public string C { get; set; };
}
Обычно мы делаем заполнение класса как-то так
for (int i = 0; i < 300; i++)
{
var tmp = new MyClass()
{
A = "ABC",
C = "DIG",
}
LC.Add(tmp);
}
А можно ли, зная кол-во классов в листе и зная константные элементы класса "ABC" и "DIG" сразу создать нужное кол-во заполненных классов?
Т.е. убрать множественный вызов Add()?
Ответы (3 шт):
Вот пример отсюда
var students = new List<Student>() {
new Student(){ Id = 1, Name="Bill"},
new Student(){ Id = 2, Name="Steve"},
new Student(){ Id = 3, Name="Ram"},
new Student(){ Id = 4, Name="Abdul"}
};
Или применительно к вашему топику.
var LC = new List<MyClass>() {
new MyClass(){ A = "ABC", C="DIG"},
new MyClass(){ A = "ABC1", C="DIG1"}
};
private class MyClass
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public MyClass() { }
public static MyClass Get_Template_A_ABC_C_DIG()
=> new MyClass() { A = "ABC", C = "DIG" };
public static List<MyClass> RepeatCreate(int Count, Func<MyClass> action)
=> Enumerable.Range(0, Count).Select(void_ => action()).ToList();
}
List<MyClass> LC = MyClass.RepeatCreate(300, MyClass.Get_Template_A_ABC_C_DIG);
Вы хотите убрать множественный вызов Add. В этом есть резон, потому что память для списка будет перевыделяться и данные копироваться в новую область памяти, когда ёмкости (Capacity) списка окажется недостаточно. Чтобы избежать этого, нужно создать список с нужной ёмкостью:
new List<MyClass>(300)
Теперь вызовы метода Add всегда имеют сложность O(1).
Свойству можно назначить инициализатор:
class MyClass
{
public string A { get; set; } = "ABC";
public string B { get; set; }
public string C { get; set; } = "DIG";
}
Теперь код будет выглядеть так:
var tmp = new MyClass();
list.Add(tmp);
// или так
list.Add(new MyClass());
Но следует помнить, что теперь эти свойства всегда будут иметь значение по умолчанию при создании, если их не изменить явно.
Возможно, вам подойдёт структура вместо класса (вообще, для хранения данных структуры почти всегда предпочтительней):
struct MyStruct
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
Тогда код с её применением будет выглядеть так:
var list = new List<MyStruct>(300);
var tmp = new MyStruct { A = "ABC", C = "DIG" };
for (int i = 0; i < 300; i++)
{
list.Add(tmp);
}
Создаём один экземпляр структуры с заполненными свойствами. Далее добавляем этот экземпляр - т. к. это значимый тип, создаются копии.
Если даже создание списка с заданной ёмкостью вас почему-то не устраивает и хочется непременно избавиться от метода Add, то предлагаю использовать массив.
var array = new MyClass[300];
for (int i = 0; i < array.Length; i++)
{
var tmp = new MyClass { A = "ABC", C = "DIG" };
array[i] = tmp;
}
Вуаля! Вместо добавления в список используем назначение элемента по индексу.
Вместе с массивом можно использовать как классы, так и структуры.
Напоследок отмечу, что применение LINQ: Enumerable.Range. ... .ToList() не избавляет от добавления элементов в список. Просто оно явно не видно, но внутри происходит. Причём производительность этого способа хуже.