#c# #.net
#c# #.net
Вопрос:
У меня есть серия списков и классов, которые реализуют таблицу данных. Основными классами являются: столбцы, строки и ячейки. Строки содержат некоторую идентификационную информацию и список ячеек, который содержит значение строки для каждого столбца. В настоящее время я создаю строки в ячейке с помощью кода, подобного этому
void CreateRow()
{
Row newRow = new Row();
newRow.ID = idInfo;
foreach (var Column in Columns)
{
newRow.Cells.Add(new Cell(Column.ID));
}
Rows.Add(newRow);
}
Работает нормально, но в некоторых случаях я вызываю CreateRow () 20 000 раз и получаю более 200 столбцов. Итак, мне интересно, существует ли более эффективный способ заполнения ячеек, поскольку ячейки в определенном столбце в каждой строке идентичны.
Есть идеи?
Спасибо,
Джерри
Комментарии:
1. Что такое
Row
? Я никогда с этим не сталкивался. Если вы нажмете клавишу F12 в строке, в какое пространство имен это приведет вас?2. может ли вся таблица быть двумерным массивом некоторых
ValueType
? Это определенно будет эффективно, если это возможно в вашем случае.3. можете ли вы опубликовать каждый из ваших классов? Может помочь прояснить ситуацию.
Ответ №1:
В настоящее время вы создаете уникальный Cell
объект для каждой позиции в вашей матрице — это много ячеек, учитывая ваш вариант использования из более чем 20 000 строк.
Одним из более эффективных подходов могло бы быть то, чтобы вообще не добавлять ячейки при построении матрицы, а только при попытке получить или установить ее значение (т. е. используя Lazy<T>
).
Предполагая, что вы задаете значение ячейки перед ее извлечением, вы могли бы затем использовать заводской метод для создания ячейки со значением — сделайте Cell
объект неизменяемым, и когда вы «создаете» Cell
объект, для которого у вас уже есть другая ячейка с идентичным значением, верните вместо нее эту ячейку. Это может значительно сократить общее количество Cell
объектов, конечно, это приведет к увеличению накладных расходов, поскольку вам нужно проверить, есть ли у вас уже ячейка с тем же значением, и вам нужно снова вызвать заводской метод, если вам нужно обновить значение ячейки.
Опять же, все это может не стоить того, если вы не испытываете никаких проблем с памятью / производительностью при вашем текущем подходе — ключевым моментом здесь является измерение производительности.
Ответ №2:
Разве столбцы не являются коллекцией?
var Ids = Columns.Select(c => c.Id).ToArray();
var Names = Columns.Select(c => c.Name).ToArray();
и т.д. Кроме того, зачем это делать, если Columns уже является коллекцией? Для вас могли бы сделать Columns[index].Id
Или если вам необходим код, который вы описали:
Row newRow = new Row();
newRow.ID = idInfo;
// presuming Cells is a List<>
newRow.Cells.AddRange(Columns.Select(c => new Cell(c.Id)));
Rows.Add(newRow);
Комментарии:
1. @hunter извини, чувак, я этого не делал — мы просто думали в том же направлении.
2. Да, если вы заметили, я использую AddRange, а не прямое размещение в ячейках. Я использую копию его кода и свой AddRange вместо foreach, чего он и хотел — способа быстрого создания списков.
3. Конечно, работает любой способ — честно говоря, я не видел ваш код до окончания редактирования, и моя правка совсем не похожа на вашу, кроме
Columns.Select(c => new Cell(c.Id))
которая уже полностью соответствует тому коду, который у меня уже был.
Ответ №3:
Некоторые предложения (зависит от того, что вы ищете)
-
Рассмотрите возможность использования (строго типизированного) DataSet / DataTable
-
Если вы используете List и знаете размер, установите емкость, чтобы избежать перераспределения (новый список (2000))
-
Используйте struct вместо class, если это имеет смысл
-
Кэшируйте объекты, если это имеет смысл (вместо многократного дублирования одного и того же объекта)
Комментарии:
1. Я забыл упомянуть, что я использую Silverlight, без DataSet / DataTabe
Ответ №4:
Вы все равно создаете ячейки. Итак, я понимаю, что вопрос относится к тому, когда вы будете заполнять ячейки их значениями, которые всегда есть в каждом столбце для всех строк.
-
Я действительно думаю, что с точки зрения корректности имеет смысл дублировать данные, поскольку они фактически являются отдельными экземплярами одних и тех же данных.
-
Тем не менее, если это на самом деле не данные, но вы просто хотите показать столбец представления с одинаковым значением для каждой строки, и вы просто хотите, чтобы он был столбцом данных, чтобы упростить отображение его как столбца представления, то в вашем property-get
Row.Cells(Id)
вы можете проверить идентификатор, и если это один из тех столбцов, где значение всегда одно и то же, верните это значение, минуя просмотр вашей_Cells
коллекции. -
Если данные в основном одинаковые, а иногда и разные, вы можете захотеть использовать «значения по умолчанию», где, если объект Cell не существует, будет возвращено значение по умолчанию для этого столбца. Однако для этого требуется
GetValue()
метод в строке, если вы хотите вообще избежать использования объекта Cell для мест, где он используется по умолчанию. -
Если вас не волнует # 1, вы действительно можете создать единственный экземпляр любого значения и ссылаться на него в вашем
Cell
значении. Это сложнее сделать для типа значения, чем для ссылочного типа (определение здесь), но это можно сделать. -
Наконец, есть ли какая-либо причина, по которой вы не используете .Предоставленные NET
DataTable
иDataRow
типы? Я уверен, что гики из MS заложили в них столько эффективности, сколько могли.