de Salvatore es totalmente correcto, sólo quería para describir el concepto un poco mejor.
Lo que necesita es una "restricción de tipo genérico"; para especificar que el tipo utilizado como T debe ajustarse a ciertos comportamientos (tales como derivarse de un objeto o interfaz más derivado que el Objeto), aumentando así lo que está permitido hacer con ese objeto sin más conversión (lo que generalmente se debe evitar en genéricos).
Como muestra la respuesta de Salvatore, GTC se definen mediante el "donde" la palabra clave:
public abstract class BaseViewModel<T> :
NotificationObject,
INavigationAware
where T : Entity;
{
...
Este GTC, básicamente, establece que cualquier T debe derivar (sin embargo de forma remota) de la entidad. Esto le permite tratar a T como si fuera una entidad (a excepción de la creación de instancias de nuevas Ts, que requiere un GTC adicional), independientemente de cómo más o menos deriva el tipo de parámetro genérico real de la entidad. Puede llamar a cualquier método que aparezca en Entity, y obtener/configurar cualquier campo o propiedad.
También puede especificar que:
- El tipo debe ser una clase (
where T:class
), o, alternativamente, debe ser un ValueType (where T:struct
). Esto permite o impide que la comparación y asignación de una instancia T sea nula, lo que también permite o impide el uso del operador nulo-coalescente ??
.
- El tipo debe tener un constructor de una firma particular (
where T:new()
, where T:new(int,float)
). Esto permite crear instancias de Ts usando la palabra clave new
, asegurando en tiempo de compilación que todos los tipos utilizados como Ts tienen un constructor con la firma esperada.