Cast从ICollection <TestCastChild>失败到ICollection <ICastBase>

Jef*_*eff 0 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; }
}
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)

Luc*_*ski 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>并添加索引器.