Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why LINQ casting with a Data.DataTableCollection

Tags:

c#

linq

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?

like image 311
newcarcrazy Avatar asked Dec 21 '22 05:12

newcarcrazy


1 Answers

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>()
like image 61
Steven Avatar answered Jan 06 '23 10:01

Steven