泛型类型作为泛型类型参数

时间:2012-09-29 22:02:30

标签: c# c#-4.0 generics

// EF (Model) project
class EntityBase { } // base class for all types
class Person : EntityBase // specific implementation for type Person

// ViewModel project
class EditableViewModel<T> where T : EntityBase // base class for all viewmodel types
class PersonViewModel : EditableViewModel<Person>
class CollectionViewModel<T> where T : EditableViewModel<EntityBase> // base class that handles CRUD operation on EditableViewModel<T> collections

// everything up to this point work. I am unable to create specific instance of CollectionViewModel<>
class AllPersonsViewModel : CollectionViewModel<PersonViewModel>

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:1)

您来自CollectionViewModel<PersonViewModel>,但您限制TEditableViewModel<EntityBase>PersonViewModelEditableViewModel<Person>,但它不是EditableViewModel<EntityBase>。这两种类型是无关的。

他们为什么不相关?示例:如果B与A分配兼容,则List<B>List<A>的分配不兼容。

如果您想了解更多有关此研究的信息,请参阅C#中的共同和逆变主题。

答案 1 :(得分:1)

你可以这样做:

class CollectionViewModel<TEntity, TViewModel>
    where TViewModel : EditableViewModel<TEntity>
    where TEntity : EntityBase

class AllPersonsViewModel : CollectionViewModel<Person, PersonViewModel> 

正如我们的回答所暗示的那样,如果将类型约束为接口而不是抽象基类,则可以获得更大的灵活性;如果界面是共变或逆变,则尤其如此。

答案 2 :(得分:1)

如果您愿意使用接口而不是类,那么您可以轻松地进行协方差。以下代码编译良好:

class EntityBase { }
class Person : EntityBase {}

interface EditableViewModel<out T> where T : EntityBase {} // Must be an interface. "out" marks T as a covariant parameter
class PersonViewModel : EditableViewModel<Person> {}
class CollectionViewModel<T> where T : EditableViewModel<EntityBase> { }

class AllPersonsViewModel : CollectionViewModel<PersonViewModel> { }