Приведение IEnumerable <Derived>к IEnumerable <BaseClass> - PullRequest
4 голосов
/ 13 апреля 2011

У меня есть класс, который я использую для перечисления через списки из моей базы данных.Все таблицы в базе данных имеют свой собственный класс со своими собственными свойствами, и все они наследуются от DatabaseTableRow.

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

У меня есть класс User, который наследуется от Page, которая наследуется от DatabaseTableRow.Затем у меня есть свойство, которое возвращает DatabaseLinkRowsEnumerator, список пользователей.

У меня также есть функция пользовательского интерфейса, которая отображает списки любой страницы в горизонтальном списке с изображением, именем и ссылкой.

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 ]

12 голосов
/ 14 апреля 2011

Используя .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> уже :)

4 голосов
/ 14 апреля 2011

Вы можете сделать это:

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

РЕДАКТИРОВАТЬ: метод расширения Cast недоступен в .NET 2.0.Вместо этого вы можете использовать реализацию Джона Скита как обычный статический метод.Если вы используете VS2008, вы также можете использовать LinqBridge , что позволяет использовать Linq to Objects при нацеливании на .NET 2.0

...