Salvatore jest całkowicie poprawna, chciałem po prostu opisać koncepcję trochę lepiej.
Potrzebne jest "ogólne ograniczenie typu"; aby określić, że typ używany jako T musi być zgodny z określonymi zachowaniami (np. pochodzącymi z obiektu lub interfejsu bardziej pochodnego niż Object), zwiększając w ten sposób to, co możesz zrobić z tym obiektem bez dalszego rzucania (którego zasadniczo należy unikać w rodzajach ogólnych).
Jak pokazuje odpowiedziami Salvatore, OWS są definiowane za pomocą słowa kluczowego „gdzie”:
public abstract class BaseViewModel<T> :
NotificationObject,
INavigationAware
where T : Entity;
{
...
GTC to w zasadzie stanowi, że każde T musi pochodzić (jednak zdalnie) od podmiotu. Pozwala to traktować T tak, jakby był Entity (z wyjątkiem tworzenia nowego Ts, który wymaga dodatkowego GTC), niezależnie od tego, w jaki sposób bardziej lub mniej wyprowadzono faktyczny rodzaj parametru generycznego z Entity. Możesz wywołać dowolną metodę, która pojawia się w Entity i pobrać/ustawić dowolne pole lub właściwość.
Można również określić, że:
- typ musi być klasą (
where T:class
) lub przemiennie muszą być ValueType (where T:struct
). Umożliwia to lub uniemożliwia porównywanie i przypisywanie wystąpienia T do wartości zerowej, co również pozwala lub uniemożliwia użycie operatora koalescencyjnego zerowania.
- Typ musi mieć konstruktora określonego podpisu (
where T:new()
, where T:new(int,float)
). Pozwala to na tworzenie wystąpień Ts za pomocą słowa kluczowego new
, zapewniając w czasie kompilacji, że wszystkie typy używane jako Ts mają konstruktor o oczekiwanej sygnaturze.