基本上我得到了那些样本类:
public interface IHasParts<TCollectionType> : where TCollectionType : ICollection
{
TCollectionType Parts { get; set; }
}
public class CarPart
{
//...
}
public class Car : IHasParts<List<CarPart>>
{
public List<CarPart> Parts { get; set; }
//...
}
是的,我需要在这里使用ICollection
的通用接口,因为实现IHasParts的类需要基于一些硬编程条件的Parts
的不同列表类型。
现在我得到了Car
的未知对象,我需要将其转换为仍具有Parts
属性的最高父级:
Car c = new Car() {
Parts = new List<CarPart>() {
// ...
}
};
object o = (object)c;
int partsCount = ((IHasParts<ICollection>)o).Parts.Count; // InvalidCastException
我该怎么做? DotNetFiddle
答案 0 :(得分:4)
这是一个差异问题。
您假设,因为List<T>
是ICollection
的子类型,因此IHasParts<List<T>>
也必须是IHasParts<ICollection>
的子类型。它没有。
如果您希望IHasParts<A>
成为IHasParts<B>
的子类型,其中A
是B
的子类型,那么您需要IHasParts
类型参数T
中的协变(使用out
关键字)。
public interface IHasParts<out TCollectionType> : where TCollectionType : ICollection
{
TCollectionType Parts { get; }
}
对于要协变的类型,T
只能用于协变位置:方法返回类型,只用属性类型和只用索引器。
它不能再用于逆变位置:方法参数,属性/索引器设置器。
答案 1 :(得分:2)
如果您使用ICollection
而不是List<CarPart>
定义Car类,则可以使用:
public class Car : IHasParts<ICollection>
{
public ICollection Parts { get; set; }
}
您仍然可以使用List<CarPart>
答案 2 :(得分:1)
添加一个抽象类来处理指定ICollection类型。声明你的代码是这样的:
public interface IHasParts
{
ICollection Parts { get; }
}
public abstract class HasParts<TCollectionType, TPartType> : IHasParts where TCollectionType : ICollection
{
public TCollectionType Parts;
ICollection IHasParts.Parts { get { return this.Parts; } }
}
public class CarPart
{
//...
}
public class Car : HasParts<List<CarPart>, CarPart>
{
protected void AddParts()
{
this.Parts.Add(new CarPart());
}
}
更新:
以下是您的DotNetFiddle的更新版本:https://dotnetfiddle.net/O3JZgc