基类和接口

时间:2017-05-11 02:41:29

标签: c# generics

我有一些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作为类型参数传递,并且还将类型约束保留在基本集合类上。

我不能用基类替换接口,因为有些组件实现了这两个接口。我不想要类型转换,因为在这种情况下,拥有集合的重点是成为性能改进的索引,因此转换有太多的开销。

有没有办法定义类型约束以使其工作,而不使用强制转换?

3 个答案:

答案 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作为一个接口的原始建议,而是将其保留为类,但声明了ICommonIA的新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
}