Goran
Goran

Reputation: 6518

Generic type as generic type argument

// 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>

How can I achieve this?

Upvotes: 0

Views: 205

Answers (3)

Jo&#227;o Mendes
Jo&#227;o Mendes

Reputation: 1425

You can do covariance easily enough if you're willing to work with interfaces instead of classes. The following code compiles fine:

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> { }

Upvotes: 1

phoog
phoog

Reputation: 43046

You can achieve this thus:

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

class AllPersonsViewModel : CollectionViewModel<Person, PersonViewModel> 

As usr's answer implies, you would get more flexibility if you constrain the types to interfaces rather than abstract base classes; this is especially true if the interface is co- or contravariant.

Upvotes: 1

usr
usr

Reputation: 171178

You are deriving from CollectionViewModel<PersonViewModel> but you restricted T to be a EditableViewModel<EntityBase>. PersonViewModel is a EditableViewModel<Person>, but it is not a EditableViewModel<EntityBase>. The two types are unrelated.

Why are they unrelated? Example: If B is assignment-compatible to A, then List<B> is not assignment-compatible to List<A>.

If you want to know more about this research the topic of co- and contravariance in C#.

Upvotes: 1

Related Questions