у меня есть код
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);
}
}
Я хочу удалить некоторые "вещи" из коллекции, если они не найдены в другой коллекции.
Когда я запускаю указанную выше программу, я получаю
Итерация может не выполняться по мере изменения коллекции
"Коллекция была изменена" - Coz удалили, должно быть, ударили
Каков способ достичь такого?
То, что я могу придумать, - это отметить все "вещи" для удаления, а затем
foreach( aThing in all_things_to_remove)
remove_from_collection(aThing)
Но выше не кажется хорошим способом для меня, поскольку я должен сделать еще один цикл и использовать дополнительную память
В этом конкретном случае, когда вы перебираете небольшую коллекцию, содержащую несколько столбцов, вы можете просто создать новую коллекцию (через 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();
}
другой способ понижает индекс после удаления столбца.
for (int i = 0; i < datatable.Columns.Count; i++)
{
if (datatable.Columns[i].ColumnName.Contains("Column"))
{
datatable.Columns.RemoveAt(i);
i--;
}
}
Вы не можете удалять элементы из коллекции, перечисляя ее с помощью цикла foreach. Создайте копию коллекции, используя Collection.ToArray()
и запустите вас для копирования на копию и удалите свой предмет из фактической коллекции.
Поскольку DataTable.Columns не имеет ToArray
или ToList
, вы можете использовать метод CopyTo()
и скопировать все столбцы в ColumnsArray.
Если вы не хотите создавать копию, вы можете использовать для цикла вместо цикла 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
как это, вы удалите только 3 из них.
for(inedx = this.dataTable.Columns.Count - 1 ; index >= 0 ; index++)
или есть лучший способ?