Как удалить DataColumn из DataTable программно

У меня есть код

foreach (DataColumn dataTableCol in this.dataTable.Columns)
            {
                bool columnFound = false;
                foreach (GRTColumnView uiColumn in descriptor.UIColumns)
                {
                    if (dataTableCol.ColumnName.Equals(uiColumn.Name))
                    {
                        columnFound = true;
                        break;
                    }
                }

                if (!columnFound)
                {
                    if (this.dataTable.Columns.Contains(dataTableCol.ColumnName))
                        this.dataTable.Columns.Remove(dataTableCol.ColumnName);
                }

            }

Я хочу удалить некоторые "вещи" из коллекции, если они не найдены в другой коллекции.

Когда я запускаю вышеуказанную программу, я получаю

Итерация может не выполняться, так как коллекция была изменена

"Коллекция была изменена" - потому что удаление должно быть ударил

Как можно достичь такой цели?

Что я могу придумать, так это записать все "вещи", которые нужно удалить, а затем

foreach( aThing in all_things_to_remove)
     remove_from_collection(aThing)

Но вышеупомянутое не кажется мне хорошим способом, так как я должен сделать еще один цикл и использую дополнительную память

3 ответа

Решение

В этом конкретном случае, когда вы просматриваете небольшую коллекцию, содержащую несколько столбцов, вы можете просто создать новую коллекцию (через ToList()), так что вы не перебираете ту же коллекцию, которую модифицируете:

foreach (var dataTableCol in dataTable.Columns.Cast<DataColumn>().ToList())
{
    ...

    dataTable.Columns.Remove(dataTableCol.ColumnName);
}

Рекомендуемый способ, особенно если коллекция большая, состоит в перечислении в обратном порядке:

for (var i = dataTable.Columns.Count - 1; i >= 0; i--)
{
    ...

    dataTable.Columns.Remove(dataTable.Columns[i].ColumnName);
}
if (dt.Columns.Contains("RecordID")){
                    dt.Columns.Remove("RecordID");
                    dt.AcceptChanges();
                }

Вы не можете удалять элементы из коллекции, перечисляя ее с помощью цикла foreach. Сделайте копию коллекции, используя Collection.ToArray() и запустить вас foreach на копию и удалить свой элемент из фактической коллекции.

Поскольку DataTable.Columns не имеет ToArray или же ToList методы, вы могли бы использовать CopyTo() метод и скопировать все столбцы в ColumnsArray.

Если вы не хотите создавать копию, вы можете использовать цикл for вместо цикла foreach. Вы можете редактировать свой код следующим образом:

for (int i = 0; i < dataTable.Columns.Count; i++)
{
    bool columnFound = false;
    foreach (GRTColumnView uiColumn in descriptor.UIColumns)
    {
        if (dataTable.Columns[i].Name.Equals(uiColumn.Name))
        {
            columnFound = true;
            break;
        }
    }

    if (!columnFound)
    {
        if (this.dataTable.Columns.Contains(dataTableCol.ColumnName))
            this.dataTable.Columns.Remove(dataTableCol.ColumnName);
    }

}

Другой способ - понижение индекса после удаления столбца.

for (int i = 0; i < datatable.Columns.Count; i++)
            {
                if (datatable.Columns[i].ColumnName.Contains("Column"))
                {
                    datatable.Columns.RemoveAt(i);
                    i--;
                }
            }
Другие вопросы по тегам