我有一些C#课程&接口看起来像这样:
abstract Component { ... }
interface IA { ... }
interface IB { ... }
class ComponentA : Component, IA { ... }
class ComponentB : Component, IB { ... }
class ComponentAB : Component, IA, IB { ... }
abstract class Collection<T> where T : Component
{
protected List<T> Items;
... // Use Items as Component
}
class CollectionA : Collection<IA>
{
// Contains ComponentA and ComponentAB
... // Use Items as IA
}
class CollectionB : Collection<IB>
{
// Contains ComponentB and ComponentAB
... // Use Items as IB
}
这里的问题是对Collection类的T的约束。 Collection中的代码需要在项目上使用Component的成员,而CollectionA / B中的代码需要使用IA / IB的成员。
目前无法编译,因为您无法将IA / IB作为类型参数传递,并且还将类型约束保留在基本集合类上。
我不能用基类替换接口,因为有些组件实现了这两个接口。我不想要类型转换,因为在这种情况下,拥有集合的重点是成为性能改进的索引,因此转换有太多的开销。
有没有办法定义类型约束以使其工作,而不使用强制转换?
答案 0 :(得分:0)
这是您修复此对象模型的方法:
interface IComponent { }
abstract class Component : IComponent { }
interface IA : IComponent { }
interface IB : IComponent { }
interface IAB : IA, IB { }
class ComponentA : Component, IA { }
class ComponentB : Component, IB { }
class ComponentAB : Component, IAB { }
abstract class Collection<T1> where T1 : IComponent
{
protected List<T1> Items;
}
class CollectionA : Collection<IA> { }
class CollectionB : Collection<IB> { }
class CollectionAB : Collection<IAB> { }
答案 1 :(得分:-1)
提供额外的通用参数:
public abstract class Collection<TSource, TView> where TSource : Component, TView
{
private List<TSource> _items;
// This is the property that child classes will see.
// It needs to be readonly because child classes can't insert TView elements
protected IEnumerable<TView> Items { get { return _items; } }
// ...
}
然后你将它扩展为:
public class CollectionA : Collection<ComponentA, IA>
{
// base.Items is IEnumerable<IA>
}
答案 2 :(得分:-1)
自从评论上述问题以来,我已经对此进行了更多的研究。
我没有将Component
作为一个接口的原始建议,而是将其保留为类,但声明了ICommon
和IA
的新IB
接口。 } 从获得。我还将其与Matias Cicero的两个通用论点的答案结合起来。我认为所有这些结合起来,它会给你你想要的东西。它确实编译至少......
abstract class Component { }
interface ICommon { }
interface IA : ICommon { }
interface IB : ICommon { }
class ComponentA : Component, IA { }
class ComponentB : Component, IB { }
class ComponentAB : Component, IA, IB { }
abstract class Collection<T1, T2> where T1 : Component where T2 : ICommon
{
protected List<T1> Items;
// ... // Use Items as Component
}
class CollectionA : Collection<Component, IA>
{
// Contains ComponentA and ComponentAB
// ... // Use Items as IA
}
class CollectionB : Collection<Component, IB>
{
// Contains ComponentB and ComponentAB
// ... // Use Items as IB
}