C# ICollection的强制转换失败<;TestCastChild>;到ICollection<;ICastBase>;
我使用反射来获取一个属性,该属性是C# ICollection的强制转换失败<;TestCastChild>;到ICollection<;ICastBase>;,c#,C#,我使用反射来获取一个属性,该属性是ICollection,并将其转换为ICollection。TestCastChild实现的ICastBase。当我尝试转换集合时,转换失败。我肯定我错过了一些简单的东西。我不明白这为什么会失败 public interface ICastBase { int Id { get; set; } } public interface ICastChild : ICastBase { string Name { get; set; } } pub
ICollection
,并将其转换为ICollection
。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; }
}
公共接口ICastBase
{
int Id{get;set;}
}
公共接口ICastChild:ICastBase
{
字符串名称{get;set;}
}
公共抽象类TestCastBase:ICastBase
{
公共int Id{get;set;}
}
公共类TestCastChild:TestCastBase,ICastChild
{
公共字符串名称{get;set;}
}
公共类TestCastParent:TestCastBase
{
公共虚拟ICollection子项{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>;
}
}
}
[TestMethod]
公共void TestCast()
{
var parent=新的TestCastParent();
parent.Children=parent.Children??新列表();
Add(newtestcastchild{Name=“a”});
Add(newtestcastchild{Name=“b”});
Add(newtestcastchild{Name=“c”});
var propinfo=parent.GetType().GetProperties();
foreach(PropInfo中的var propertyInfo)
{
if(propertyInfo.PropertyType.GetMethod(“添加”)!=null)
{
var tmpVal=propertyInfo.GetValue(父级);
//其计算结果为null
var cast1=tmpVal作为ICollection;
//其计算结果为null
var cast2=tmpVal作为ICollection;
//这将计算为预期值
var cast3=tmpVal作为ICollection;
}
}
}
由于ICollection
不是协变的,因此您不能从ICollection
强制转换为ICollection
如果可能,您可以将i集合
投射到i集合
,然后将Cat
添加到集合中,因为它也是哺乳动物
您可以执行的操作是从IReadOnlyCollection
强制转换为IReadOnlyCollection
,因为IReadOnlyCollection
是协变的。如果您的具体集合类型实现了IReadOnlyCollection
(并且List
实现了),那么它可以正常工作,但您只能获得一个到基础集合的只读接口。这样,类型安全性仍然保持不变
请注意,您还可以使用
IReadOnlyList
,它继承自IReadOnlyCollection
,并添加索引器。您无法将ICollection
转换为ICollection
,因为ICollection
不是协变的
如果可能,您可以将i集合
投射到i集合
,然后将Cat
添加到集合中,因为它也是哺乳动物
您可以执行的操作是从IReadOnlyCollection
强制转换为IReadOnlyCollection
,因为IReadOnlyCollection
是协变的。如果您的具体集合类型实现了IReadOnlyCollection
(并且List
实现了),那么它可以正常工作,但您只能获得一个到基础集合的只读接口。这样,类型安全性仍然保持不变
请注意,您还可以使用
IReadOnlyList
,它继承自IReadOnlyCollection
,并添加索引器。是的,这是一个重复项。在这里看到答案后,我可以搜索“协变”并找到其他答案。是的,这是一个副本。在这里看到答案后,我能够搜索“协变”并找到其他答案。