Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting IEnumerable<Derived> to IEnumerable<BaseClass>

I have a class which I use to enumerate through lists from my database. All tables in the database have their own class with their own properties, and they all derive from DatabaseTableRow.

public class DatabaseLinkRowsEnumerator<T> : IEnumerator<T>, IEnumerable<T> where T : DatabaseTableRow

I have a User class, which derives from Page, which derives from DatabaseTableRow. I then have a property that returns a DatabaseLinkRowsEnumerator, a list of users.

I also have a UI function that displays lists of any Page in a horizontal list, with the image, name and a link.

protected string GetVerticalListModuleHtml(IEnumerable<Page> pages)

Now all I want to do is pass the value I have of DatabaseLinkRowsEnumerator to this function. User derives from Page, and DatabaseLinkRowsEnumerator is an IEnumerator. Even when I try to cast, I get the following error:

Unable to cast object of type 'Database.DatabaseLinkRowsEnumerator`1[Database.User]' to type 'System.Collections.Generic.IEnumerable`1[Database.Page]'.

I'm using ASP.NET 2.0. Does anyone have any ideas of how to cast/convert this without making an entire copy of each?

like image 375
Connell Avatar asked Apr 13 '11 19:04

Connell


People also ask

How to cast an IEnumerable to an IEnumerable<T>?

To cast an IEnumerable to an IEnumerable<T>, you can use this code: C#. Copy Code. IEnumerable ienumerable = new int [] { 1, 5, 6, 7, 8, 11, 10, 134, 90 }; IEnumerable casted = ienumerable.Cast<int> (); // change 'int' into the //type of the elements in your IEnumerable. Now, you can use a LINQ query for casted.

What is cast<TResult> (IEnumerable) in Java?

An IEnumerable<T> that contains each element of the source sequence cast to the specified type. source is null. An element in the sequence cannot be cast to type TResult. The following code example demonstrates how to use Cast<TResult> (IEnumerable) to enable the use of the standard query operators on an ArrayList.

Why can't I use LINQ with IEnumerable?

But for an IEnumerable, you can't use LINQ. If you write this LINQ query for an IEnumerable: Then, you get this error: Could not find an implementation of the query pattern for source type 'System.Collections.IEnumerable'. 'Where' not found. Consider explicitly specifying the type of the range variable 'i'.

Does ArrayList implement IEnumerable in Java?

For example, ArrayList does not implement IEnumerable<T>, but by calling Cast<TResult> (IEnumerable) on the ArrayList object, the standard query operators can then be used to query the sequence. If an element cannot be converted to type TResult, this method throws a InvalidCastException.


1 Answers

Using .NET 2.0, it's slightly awkward, but not too hard:

public static IEnumerable<TBase> Cast<TDerived, TBase>
    (IEnumerable<TDerived> source)
    where TDerived : TBase
{
    foreach (TDerived item in source)
    {
        yield return item;
    }
}

Call it like this:

IEnumerable<Page> pages = UtilityClass.Cast<User, Page>(users);

This will evaluate it lazily. In LINQ it's easier - you use the Cast extension method:

var baseSequence = derivedSequence.Cast<BaseClass>();

In .NET 4, IEnumerable<T> is covariant in T so there's a reference type conversion from IEnumerable<DerivedClass> to IEnumerable<BaseClass> already :)

like image 96
Jon Skeet Avatar answered Sep 21 '22 22:09

Jon Skeet