Cast从ICollection <testcastchild>失败到ICollection <icastbase>

时间:2015-06-29 18:14:29

标签: c#

我使用反射来获取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>;
        }               
    }
}

1 个答案:

答案 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}}并添加索引器。