2015-06-29 76 views
0

我使用反射來得到一個屬性,它是一個ICollection<TestCastChild>,並投它作爲一個ICollection<ICastBase>。 TestCastChild實現的ICastBase。當我嘗試投射收藏品時,投射失敗。我確定我錯過了一些簡單的東西。我看不出爲什麼會失敗。演員自ICollection <TestCastChild>未能ICollection的<ICastBase>

public interface ICastBase 
{ 
    int Id { get; set; } 
} 

public interface ICastChild : ICastBase 
{ 
    string Name { get; set; } 
} 

public abstract class TestCastBase : ICastBase 
{ 
    public int Id { get; set; } 
} 

public class TestCastChild : TestCastBase, ICastChild 
{ 
    public string Name { get; set; } 
} 

public class TestCastParent : TestCastBase 
{ 
    public virtual ICollection<TestCastChild> Children { get; set; } 
} 

然後進行測試:

[TestMethod] 
public void TestCast() 
{ 
    var parent = new TestCastParent(); 
    parent.Children = parent.Children ?? new List<TestCastChild>(); 
    parent.Children.Add(new TestCastChild{Name = "a"}); 
    parent.Children.Add(new TestCastChild { Name = "b"}); 
    parent.Children.Add(new TestCastChild { Name = "c"}); 

    var propInfos = parent.GetType().GetProperties(); 
    foreach (var propertyInfo in propInfos) 
    { 
     if (propertyInfo.PropertyType.GetMethod("Add") != null) 
     { 
      var tmpVal = propertyInfo.GetValue(parent); 
      //This evaluates to null 
      var cast1 = tmpVal as ICollection<ICastBase>; 
      //This evaluates to null 
      var cast2 = tmpVal as ICollection<ICastChild>; 
      //This evaluates to the expected value 
      var cast3 = tmpVal as ICollection<TestCastChild>; 
     }    
    } 
} 
+0

是的,這是重複的。在看到這裏的答案後,我能夠搜索'協變'並找到其他答案。 – Jeff

回答

6

不能從ICollection<Derived>投地ICollection<Base>,爲ICollection<T>

如果可能,您可以將ICollection<Dog>投射到ICollection<Mammal>,然後在集合中添加Cat,因爲它也是Mammal

可以做的,是從IReadOnlyCollection<Derived>投什麼IReadOnlyCollection<Base>IReadOnlyCollection<out T>協變。如果你的具體集合類型實現了IReadOnlyCollection<out T>(和List<T>),它將工作得很好,但你只會得到底層集合的只讀接口。這樣,類型安全性仍然保留。

請注意,您也可以使用IReadOnlyList<out T>,它從IReadOnlyCollection<out T>繼承,它添加了一個索引器。

相關問題