5

This question is a continuous question of "LINQ casting with a Data.DataTableCollection", here is the link [question]LINQ casting with a Data.DataTableCollection @Lasse Espeholt

I case the same situation. I want to do LINQ query on collection DataTableCollection. But if I write down the following code:

from dataTable in dataSet.Tables

The visual studio will report a error "Could not find an implementation of the query pattern for source type 'System.Data.DataTableCollection'". So the solution is change the code to following:

from dataTable in dataSet.Tables.Cast<DataTable> ()

So I dig the the root cause from internet. And I found some clue as "A typical LINQ to Objects query expression not only takes a class that implements IEnumerable as its data source, but it also returns an instance of this same type." in this page. So I wonder DataTableCollection don't inherit the interface IEnumerable. But according I checking in MSDN, I found the inheritence relationship of DataTableCollection is as following:

DataTableCollection
    InternalDataCollectionBase
        ICollection
            IEnumerable

So this inheritence relationship means that DataTableCollection only inherit the interface IEnumerable, don't inherit the interface IEnumerable. So it can't support the LINQ query. And the solution is using the cast method the transform to IEnumerable and then can do LINQ query.

So my summary as the class which want to enable the functionality of LINQ to object, it has to inherit the both interface IEnumerable and IEnumerable.

Is my summary right? And what's the difference between IEnumerable and IEnumerable?

Community
  • 1
  • 1
newcarcrazy
  • 105
  • 1
  • 7

1 Answers1

12

The problem here is that DataTableCollection doesn't implement the generic IEnumerable<T> interface. This interface is added with .NET 2.0 and it inherits from the non-generic IEnumerable interface that has been there from the early days. LINQ queries need this generic interface and don't work with the non-generic version.

DataTableCollection is a class that has been available before 2.0 while the generic IEnumerable<T> was added in .NET 2.0.

Although Microsoft could have added this generic interface on existig framework types, my guess is that they didn't because of time constraints, risks and limited usefulness.

There are a lot of old classes that could benefit from having this generic interface (and it is sometimes quite annoying that they lack that interface), but adding this takes a lot of time to implement and test for backwards compatibility. Changing existing stuff includes the risk of breaking existing applications. The .NET designers are really conservative about introducing breaking changes.

So I think they calculated that the costs where higher than the benefits, because those old types would not be used that much in the future of the availability of new tools. Besides, there is an easy workaround in the form of the Enumerable.Cast<T>(Enumerable) extension method, which you already found.

The C# LINQ language implementation even has built-in support for this Cast<T> method; it can be written as follows:

from DataTable dataTable in dataSet.Tables

Which under the covers translates to:

from dataTable in dataSet.Tables.Cast<DataTable>()
Steven
  • 166,672
  • 24
  • 332
  • 435
  • Thanks! @Steven, you last update is the question which I want to ask you. Base on your explanation, the grammar "from DataTable dataTable in dataSet.Tables", so here it seems that the type "DataTable" is not the declaration of variable dataTable, it's the declaration of the generic type. My I understanding right? – newcarcrazy May 30 '13 at 00:48
  • I'm not sure what you mean. – Steven May 30 '13 at 05:01
  • Hello, @Steven, excuse to make you confuse. At my first glance, I ignore the "The C# LINQ language implementation even has built-in support for this Cast method;", so I want to know the grammar definition of the first type of code. Now, I know that maybe after compiling, the first type of code can be transformed to the second type of code. Thanks again for your explanation. – newcarcrazy Jun 01 '13 at 08:17