2011-11-16 35 views
2

为简洁起见,我将在此处进行通用化。我有一个基类 - 评论 - 有一个孩子 - 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列表以退出方法列表其父类型(评论)?

只是一个FYI,调用此方法的代码并不关心它正在获取的类型评论。随后的代码将在任何情况下运行。

我很欣赏它大好时光。

回答

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.0和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>

+0

祝福你,亲切的先生。该死的。我需要更好地理解协方差和上演。你是第一个,所以你得到我的批准检查。谢谢十亿。 –

3

变化:

reviews = dtos.ToList(); 

要:

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

的问题是,列表和列表不是协变。这很容易理解,如果你仔细想想:

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

@JustinNiesnner很多人已经发布了答案,但感谢您的意见。 +1的努力,虽然:)。 –

3

使用CAST转换为基本类型:

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

很多人已经发布了答案,但是感谢您的意见。 +1的努力,但: –

3

它的Covariance问题。为了您的具体问题,请尝试:

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

很多人已经发布了答案,但感谢您的意见。 +1的努力,虽然: –

1

使用这一个

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

你不能投了名单列出。假设你可能会发生可怕的事情:

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

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

+0

我明白你的观点。感谢这个例子。我知道有些东西是用.NET 4来解决的,我确实需要更多地了解这一点。我仍然在寻找它的来源。再次感谢这个例子。 –

+1

没问题,请阅读:http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/default.aspx – zmbq

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