Reputation: 14411
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?
Upvotes: 7
Views: 5768
Reputation: 1502066
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 :)
Upvotes: 13
Reputation: 292555
You can do that:
DatabaseLinkRowsEnumerator<User> users = ...
IEnumerable<Page> = users.Cast<Page>();
EDIT: the Cast
extension method is not available in .NET 2.0. You can use Jon Skeet's implementation as a normal static method instead. If you're using VS2008, you can also use LinqBridge, which allows you to use Linq to Objects when targeting .NET 2.0
Upvotes: 5