将IEnumerable <derived>转换为IEnumerable <baseclass> </baseclass> </derived>

时间:2011-04-13 19:58:36

标签: c# generics inheritance casting .net-2.0

我有一个类用于枚举数据库中的列表。数据库中的所有表都有自己的类,它们都有自己的属性,它们都来自DatabaseTableRow。

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

我有一个User类,它派生自Page,它派生自DatabaseTableRow。然后我有一个属性,它返回一个DatabaseLinkRowsEnumerator,一个用户列表。

我还有一个UI功能,可以显示水平列表中任何页面的列表,包括图像,名称和链接。

protected string GetVerticalListModuleHtml(IEnumerable<Page> pages)

现在我要做的就是将我对DatabaseLinkRowsEnumerator的值传递给这个函数。用户派生自Page,DatabaseLinkRowsEnumerator是IEnumerator。即使我尝试施放,我也会收到以下错误:

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

我正在使用ASP.NET 2.0。有没有人有任何关于如何转换/转换它的想法而不制作每个的完整副本?

2 个答案:

答案 0 :(得分:12)

使用.NET 2.0,它略微尴尬,但不是太难:

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

这样称呼:

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

这将懒洋洋地评估它。在LINQ中,它更容易 - 您使用Cast扩展方法:

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

在.NET 4中,IEnumerable<T>中的T是协变的,因此已经有IEnumerable<DerivedClass>IEnumerable<BaseClass>的引用类型转换:)

答案 1 :(得分:4)

你可以这样做:

DatabaseLinkRowsEnumerator<User> users = ...
IEnumerable<Page> = users.Cast<Page>();

编辑:{2.0}中没有Cast扩展方法。您可以将Jon Skeet的实现用作常规静态方法。如果你正在使用VS2008,你也可以使用LinqBridge,它允许你在定位.NET 2.0时使用Linq到对象