Link to home
Start Free TrialLog in
Avatar of Arikael
ArikaelFlag for Switzerland

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?
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);
            }
        }

    }

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of sanket_1985
sanket_1985
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Arikael

ASKER

so, you say, even when I return an anonymous type in my linq-query, I have somehow a reference to the datatable/dataset?
Avatar of kaufmed
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]);
}

Open in new window

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.
Avatar of Arikael

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.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Arikael

ASKER

thanks

I still find it strange, especially when I return an anonymous type. It's not the behaviour I would expect.