2009-11-10 45 views
0

可能重複:
IList<Type> to IList<BaseType>你爲什麼不能自IList <IParent>轉換爲IList的<IChild>其中ICHILD實現IParent

我在C#中使用.NET 2.0開發,我不明白爲什麼下面的投射結果爲空引用。

如果你有一個IList <ICHILD>,爲什麼你不能把它轉換爲IList <IParent>其中ICHILD實現IParent。

using System.Collections.Generic; 

namespace InterfaceTest 
{ 
    public interface IParent 
    { 
    } 

    public interface IChild : IParent 
    { 
    } 

    public abstract class Parent : IParent 
    { 
    } 

    public sealed class Child : Parent, IChild 
    { 
    } 

    public sealed class Container 
    { 
     public IList<IChild> ChildInterfaceList 
     { 
      get; 
      set; 
     } 

     public Container() 
     { 
      ChildInterfaceList = new List<IChild>(); 
     } 
    } 

    class Program 
    { 
    static void Main(string[] args) 
    { 
      Container container = new Container(); 

      var childInterfaceList = container.ChildInterfaceList; 

      System.Diagnostics.Debug.Assert(childInterfaceList != null); 

      var parentInterfaceList = container.ChildInterfaceList as IList<IParent>; 

      //I don't expect parentInterfaceList to be null, but it is 
      System.Diagnostics.Debug.Assert(parentInterfaceList != null); 
     } 
    } 
} 
+0

確切的重複:http://stackoverflow.com/questions/1457265。也可能有用:http://blogs.msdn.com/rmbyers/archive/2005/02/16/375079.aspx – 2009-11-10 20:27:40

回答

3

C#可變集合不支持集合元素類型的差異。試想,如果你做了,會發生什麼這樣的:

IList<IChild> kids = new List<IChild> { 
    new Egg("Shelly"), new Egg("Egbert"), new Egg("Yoko") 
}; 

var parents = kids as IList<IParent>; 

parents.Add(new Sloth("Sid")); // what would happen here? 

如果中投得手,的parents運行時類型仍然是List<IChild>這將不接受的東西,沒有實現IChild,並且將不得不拋出一個異常。

一種可接受的轉化率將是:

using System.Linq; 
var parents = kids.Cast<IParent>().ToList(); 

這將創建原始列表的副本,但與作爲List<IParent>其運行時類型。

C#4.0支持通用差異,但可變集合不能安全地變爲變體。只有純粹的只讀接口(如IEnumerable)可以安全地進行協變,而純粹的只寫接口(有沒有?)可以安全地進行逆變。

+3

是的。例如IComparer 實際上是用於差異目的的只寫接口。 T的進來,結果出來了,但T從來沒有出來。比較任何兩隻動物的比較器也可以比較任何兩隻長頸鹿,所以IComparer 可以逆轉換爲IComparer 。 – 2009-11-10 21:22:22

+0

IEnumerable類型的對象不保證是隻讀的。 IEnumerable someList = new List (); // someList非常可寫:) – 2009-11-10 21:43:01

+0

正確,但無關緊要。沒有辦法通過IEnumerable獲取變異方法,這是相關的。這個事實使我們能夠安全地在T中製作IE 協變。 – 2009-11-10 23:13:53

0

這是一個常見的陷阱。

考慮一下這個簡單的解釋逐例如:在.NET

一切從Object繼承,對不對?所以,讓我們假設你想是可能的......

List<int> ints = new List<int>(); 
List<object> objects = ints as List<object>; 
objects.Add("Hello there!"); 

你只是想一個string添加到什麼是真正的整數列表。

相關問題