我使用反射来获取ICollection<TestCastChild>
的属性并将其强制转换为ICollection<ICastBase>
。 TestCastChild实现了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 :(得分:6)
无法从ICollection<Derived>
投放到ICollection<Base>
,因为ICollection<T>
不是协变。
如果可能,您可以将ICollection<Dog>
投射到ICollection<Mammal>
,然后将Cat
添加到集合中,因为它也是Mammal
。< / p>
您可以做什么,从IReadOnlyCollection<Derived>
投射到IReadOnlyCollection<Base>
,因为IReadOnlyCollection<out T>
是协变。如果您的具体集合类型实现IReadOnlyCollection<out T>
(并且List<T>
确实)它将正常工作,但您只能获得底层集合的只读接口。这样,类型安全性仍然保留。
请注意,您还可以使用继承自IReadOnlyList<out T>
的{{1}}并添加索引器。