我正在使用反射获得一个属性,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; }
}
Run Code Online (Sandbox Code Playgroud)
然后测试:
[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>;
}
}
}
Run Code Online (Sandbox Code Playgroud)
你无法从投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>并添加索引器.
| 归档时间: |
|
| 查看次数: |
47 次 |
| 最近记录: |