Arikael
asked on
LINQ anonymous types and reference issues
Hi experts, I'm fairly new to the whole linq stuff. Today I came across a behaviour I don't really understand.
Frist, see code below, it's an extension method for a dataset.
This one works, no problem.
but, if I don't loop through TableNamesToDelete.ToList( ) and would instead use TableNamesToDelete directly, I get an exception in the foreach loop, saying the enumeration has been changed while looping.
the same happens when I create an anonymous type in the linq query, like
select new{t.TableName} and use TableNamesToDelete directly.
So, somehow it seems I still have a reference to the datatables in the datasets, which causes the foreach-loop to fail.
I don't really get it, why is there still a reference when I create an anonymous type?
Or am I getting something wrong here?
Frist, see code below, it's an extension method for a dataset.
This one works, no problem.
but, if I don't loop through TableNamesToDelete.ToList(
the same happens when I create an anonymous type in the linq query, like
select new{t.TableName} and use TableNamesToDelete directly.
So, somehow it seems I still have a reference to the datatables in the datasets, which causes the foreach-loop to fail.
I don't really get it, why is there still a reference when I create an anonymous type?
Or am I getting something wrong here?
public static class ExtensionMethods
{
public static void RemoveUnnecessaryTables(this DataSet ds)
{
var TableNamesToDelete = from t in ds.Tables.Cast<DataTable>()
where t is INoImport
select t.TableName;
foreach(string TName in TableNamesToDelete.ToList())
{
if(ds.Tables.Contains(TName))
ds.Tables.Remove(TName);
}
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Use a "for" loop instead and work backwards (see below). As sanket_1985 stated, you cannot modify a collection that you are iterating over--it would screw up the internal iterator for the collection. Use a "for" loop when you want to add/remove from a collection in a loop.
var TableNamesToDelete = (from t in ds.Tables.Cast<DataTable>()
where t is INoImport
select t.TableName).ToList();
for(int i = TableNamesToDelete.Count - 1; i >= 0; i--)
{
if(ds.Tables.Contains(TableNamesToDelete[i]))
ds.Tables.Remove(TableNamesToDelete[i]);
}
In hindsight, you don't have to "work backwards" in this particular scenario. You would be fine to start at the beginning of TableNamesToDelete and go forward.
ASKER
Hi,
I know that I can't modify a collection I'm iterating over :)
But I don't really understand why TableNamesToDelete seems to have a reference to to the dataset/datatable, even when I return a new anonymous type.
I know that I can't modify a collection I'm iterating over :)
But I don't really understand why TableNamesToDelete seems to have a reference to to the dataset/datatable, even when I return a new anonymous type.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thanks
I still find it strange, especially when I return an anonymous type. It's not the behaviour I would expect.
I still find it strange, especially when I return an anonymous type. It's not the behaviour I would expect.
ASKER