将子类型列表转换为父类型列表

本文关键字:类型 列表 父类 转换 | 更新日期: 2023-09-27 18:14:46

为简洁起见,我将在这里使用通用名称。我有一个基类- Review -它有一个子类- ShelfAwarenessReview。

我还有一个方法,接口需要它的签名:

public List<Review> GetReviews(string filePath)
        {
            XElement xmlDoc = XElement.Load(filePath);
            var dtos = from item in xmlDoc.Descendants("message")
                       select new ShelfAwarenessReview()
                       {
                           PubDate = item.Element("meta").Attribute("permlinkdate").Value,
                           Summary = item.Element("meta").Element("summary").Value,
                           Isbn = item.Element("BookInfo").Element("ISBN").Value
                       };
            List<Review> reviews = new List<Review>();
            reviews = dtos.ToList();
            return reviews;
        }

现在,我得到的错误是List<ShelfAwarenessReview>不能隐式转换为List<Review>

我已经尝试了几种类型的转换——或者,至少我认为我做了——但它不起作用。我想,因为ShelfAwarenessReview是Review的一个子类,所以这应该行得通。毕竟,正如继承的格言所说,"所有的烤面包机都是电器,但并非所有的电器都是烤面包机"…

我需要做些什么来获得ShelfAwarenessReviews的列表,以退出其父类型(Review)的列表中的方法?

仅供参考,调用该方法的代码并不关心它所获得的类型审查。

我非常感谢。

将子类型列表转换为父类型列表

首先,您不需要创建一个空的List<Review>,然后忽略它:)

下面是最简单的解决方案:

public List<Review> GetReviews(string filePath)
{
    XElement xmlDoc = XElement.Load(filePath);
    var dtos = ...; // As before
    return dtos.Cast<Review>().ToList();
}

如果你正在使用。net 4和c# 4,由于通用协方差,有另一种选择,适用于IEnumerable<T>,但不适用List<T>:

public List<Review> GetReviews(string filePath)
{
    XElement xmlDoc = XElement.Load(filePath);
    IEnumerable<Review> dtos = ...; // As before
    return dtos.ToList();
}

注意dtos类型的显式规范。查询表达式的类型为IEnumerable<ShelfAwarenessReview>,但可以隐式转换(在c# 4中)为IEnumerable<Review>

变化:

reviews = dtos.ToList();

:

reviews = dtos.Cast<Review>().ToList();

问题是List和List不是协变的。如果你仔细想想,就很容易理解了:

List<ShelfAwarenessReview> initial = new List<ShelfAwarenessReview>();
List<Review> cast = (List<Review>)initial;
// The underlying type is still List<ShelfAwarenessReview>.
// SomeOtherReview inherits Review but not ShelfAwarenessReview
// What will happen when I make the following call?
cast.Add(new SomeOtherReview());

使用强制类型转换为基类型:

return dtos.Cast<Review>().ToList();

这是协方差的问题。对于您的特定问题,请尝试:

return dtos.ToList().Cast<Review>();

不能将List强制转换为List。假设你可以,可怕的事情会发生:

List<String> list = new list<String>();
list.Add("Hello");
List<Object> list2 = List<Object>(list);
list2.Add(12);

啊?我刚才是不是给字符串列表加了一个整数。这就是为什么你不能。你应该读一读协方差和逆变性

List<Review> reviews = dtos.Cast<Review>().ToList();

使用这个

  List<Review> reviews = dtos.Cast<Review>().ToList();