Есть ли более эффективный способ создавать одинаковые списки?

#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:

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

  1. Я действительно думаю, что с точки зрения корректности имеет смысл дублировать данные, поскольку они фактически являются отдельными экземплярами одних и тех же данных.

  2. Тем не менее, если это на самом деле не данные, но вы просто хотите показать столбец представления с одинаковым значением для каждой строки, и вы просто хотите, чтобы он был столбцом данных, чтобы упростить отображение его как столбца представления, то в вашем property-get Row.Cells(Id) вы можете проверить идентификатор, и если это один из тех столбцов, где значение всегда одно и то же, верните это значение, минуя просмотр вашей _Cells коллекции.

  3. Если данные в основном одинаковые, а иногда и разные, вы можете захотеть использовать «значения по умолчанию», где, если объект Cell не существует, будет возвращено значение по умолчанию для этого столбца. Однако для этого требуется GetValue() метод в строке, если вы хотите вообще избежать использования объекта Cell для мест, где он используется по умолчанию.

  4. Если вас не волнует # 1, вы действительно можете создать единственный экземпляр любого значения и ссылаться на него в вашем Cell значении. Это сложнее сделать для типа значения, чем для ссылочного типа (определение здесь), но это можно сделать.

  5. Наконец, есть ли какая-либо причина, по которой вы не используете .Предоставленные NET DataTable и DataRow типы? Я уверен, что гики из MS заложили в них столько эффективности, сколько могли.