Укажите класс generics, где T должен быть подклассом другого типа

Вот что я пытаюсь сделать, даже не уверен, если возможно..

Я создаю BaseViewModel<T>, и я хочу, чтобы он принимал типы, унаследованные от Entity

Рассмотрим этот код:

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

public T MyEntity;

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

}

Итак, я хочу сказать, что мой T унаследован от Entity, и поэтому я ЗНАЮ, что у него будет SomeEntityProperty.

Возможно ли это?

Ответ 1

Ответ Сальваторе абсолютно прав, я просто хотел немного описать концепцию.

Что вам нужно, это "ограничение общего типа"; чтобы указать, что тип, используемый как T, должен соответствовать определенному поведению (например, быть полученным из объекта или интерфейса, более производного, чем Object), тем самым увеличивая то, что вам разрешено делать с этим объектом без дальнейшего литья (чего, как правило, следует избегать в дженериках).

Как показывает ответ Сальваторе, GTC определяются с использованием ключевого слова "where":

public abstract class BaseViewModel<T> :
    NotificationObject,
    INavigationAware

    where T : Entity;
{
   ...

Этот GTC в основном утверждает, что любой T должен выводиться (хотя и удаленно) из Entity. Это позволяет обрабатывать T, как если бы это был Entity (за исключением создания нового Ts, который требует дополнительного GTC), независимо от того, как более или менее выведен фактический тип общих параметров из Entity. Вы можете вызвать любой метод, который появляется в Entity, и получить/установить любое поле или свойство.

Вы также можете указать, что:

  • Тип должен быть классом (where T:class) или попеременно должен быть ValueType (where T:struct). Это позволяет или препятствует сопоставлению и присваиванию экземпляра T null, что также позволяет или запрещает использование оператора с нулевым коалесцированием ??.
  • Тип должен иметь конструктор определенной сигнатуры (where T:new(), where T:new(int,float)). Это позволяет создавать экземпляры Ts с использованием ключевого слова new, обеспечивая во время компиляции, что все типы, используемые в качестве Ts, имеют конструктор с ожидаемой сигнатурой.

Ответ 2

public abstract class BaseViewModel<T> :
    NotificationObject,
    INavigationAware

    where T : Entity
{

    public T MyEntity;

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

}

Ответ 3

Просто используйте ключевое слово where:

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

Ответ 4

Попробуйте использовать где ограничение:

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

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