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

时间:2011-11-16 19:57:08

标签: c# .net

为简洁起见,我将在这里通用。我有一个基类 - 评论 - 有一个孩子 - 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)?

仅仅是一个FYI,调用此方法的代码不打算关注它所获得的类型评论。后续代码将以任何方式运行。

我很欣赏它。

7 个答案:

答案 0 :(得分:6)

首先,您不需要创建一个空的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>

答案 1 :(得分:3)

变化:

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());

答案 2 :(得分:3)

使用Cast转换为基本类型:

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

答案 3 :(得分:3)

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

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

答案 4 :(得分:1)

使用这个

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

答案 5 :(得分:1)

您无法将列表转换为列表。假设你可能会发生可怕的事情:

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

咦?我是否只是将一个整数添加到字符串列表中。这就是为什么你不能。你应该阅读协方差和逆变。

答案 6 :(得分:1)

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