katit
katit

Reputation: 17905

Specify generics class where T should be subclass of other type

Here is what I'm trying to do, not even sure if possible..

I'm creating BaseViewModel<T> and I want it to accept types inherited from Entity

Consider this code:

public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
{

public T MyEntity;

public SomeMethod()
{
MyEntity.SomeEntityProperty = SomeValue;
}

}

So, I want to say that my T inherited from Entity and therefore I KNOW that it will have SomeEntityProperty.

Is this possible?

Upvotes: 27

Views: 25199

Answers (4)

KeithS
KeithS

Reputation: 71565

Salvatore's answer is totally correct, I just wanted to describe the concept a little better.

What you need is a "generic type constraint"; to specify that the type used as T must conform to certain behaviors (such as being derived from an object or interface more derived than Object), thus increasing what you are allowed to do with that object without further casting (which is generally to be avoided in generics).

As Salvatore's answer shows, GTCs are defined using the "where" keyword:

public abstract class BaseViewModel<T> :
    NotificationObject,
    INavigationAware

    where T : Entity;
{
   ...

This GTC basically states that any T must derive (however remotely) from Entity. This allows you to treat T as if it were an Entity (except for instantiation of new Ts; that requires an additional GTC), regardless of how more or less derived the actual generic parameter type is from Entity. You can call any method that appears on Entity, and get/set any field or property.

You can also specify that:

  • The type must be a class (where T:class), or alternately must be a ValueType (where T:struct). This either permits or prevents comparison and assignment of a T instance to null, which also allows or prevents use of the null-coalescing operator ??.
  • The type must have a parameterless constructor (where T:new()). This allows instantiations of Ts using the new keyword, by ensuring at compile-time that all types used as Ts have a constructor that takes no parameters.

Upvotes: 34

Kieron
Kieron

Reputation: 27107

Try using the where constraint:

public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
    where T : Entity
{
    public T MyEntity;

    public SomeMethod()
    {
        MyEntity.SomeEntityProperty = SomeValue;
    }
}

Upvotes: 9

satnhak
satnhak

Reputation: 9861

Just use the where keyword:

public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
    where T:Entity
{
...

Upvotes: 8

Salvatore Previti
Salvatore Previti

Reputation: 9050

public abstract class BaseViewModel<T> :
    NotificationObject,
    INavigationAware

    where T : Entity
{

    public T MyEntity;

    public SomeMethod()
    {
        MyEntity.SomeEntityProperty = SomeValue;
    }

}

Upvotes: 17

Related Questions