我使用反射获取一个属性,该属性是一个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>;
}
}
}发布于 2015-06-29 18:17:22
不能从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>,并添加索引器。
https://stackoverflow.com/questions/31122713
复制相似问题