Typowanie generyków

Typowanie generyków

Typowym zastosowaniem typu generycznego jest wydzielenie typowania na zewnątrz klasy. Działa to na zasadzie wstrzyknięcia pewnego typu do klasy i manipulacja nim. Do klasy generycznej możemy wstrzyknąć dowolny typ, który będzie można używać według  algorytmów zawartych w klasie.

Typ generyczny posiada swoją nazwę symboliczną, bardzo często wykorzystuje się  po prostu dużą literę T. Jednak nic nie stoi na przeszkodzie by nazwę określić w bardziej logiczny ciąg, np: TCompareType. Dobrą praktyką jest pozostawienie przedrostka T, która jak mniemam pochodzi z typów generycznych stosowanych w języku C++ określanych jako Template.

Nazewnictwo szczególnie przydatne gdy użyjemy więcej typów generycznych.

Ograniczenia na typach generycznych

Świat idzie do przodu, języki programowania także ewoluują, i tak doczekaliśmy się rozszerzenia możliwości typów generycznych o ograniczenia. Do tej pory można było przekazać prawie dowolny typ do klasy generycznej, obecnie można to bardzo ograniczyć tym samym gdy dev spróbuje przekazać nie odpowiedni typ, kompilator strzeli errorem prosto w …

Od wujka „Billa”, dostajemy słówko kluczowe where, i tym samym możemy określić konkretny typ jaki może zostać „wstrzyknięty” do klasy generycznej.

Generics

Składnia użycia ograniczenia to: where TGenericTypeName : TypeName.

Jak można  zauważyć implementacja metody IsEqual uległa zmianie, wykorzystuje właściwość Value, w tym przypadku jeżeli przekażemy niespójny typ do klasy generycznej, nie będzie on posiadał właściwości Value, to walnie błędem.

W przypadku gdy wykorzystamy więcej typów generycznych można wykorzystać więcej ograniczeń oddzielając je przecinkami:

public class SampleClassTTypeOne, TTypeTwo where TTypeOne : Credential1, where TTypeTwo : Credential2{ }

Istnieje także możliwość ustawienie wielu ograniczeń dla typu generycznego:

public class SampleClass<TType> where TType: Credential1Credential2 { }

 

Typy ograniczeń

Oczywiście nie jest to jedyny sposób ograniczenia jest ich nieco więcej:

  • where TStruct: struct – ten typ ograniczenia określa, iż można wstrzyknąć do klasy generycznej typy wartości z wyjątkiem nullable, np: int, byte, long, jednak nie będą się już klasyfikować typy int?, long?,
  • where TClass : class –  TClass może zostać zastąpiony przez typy referencyjne: class, interface, array,  delegate,
  • where TNew : new() – można wykorzystać typy posiadające publiczny konstruktor bezparametrowy, to ograniczenie w przypadku stosowania wielu do typu generycznego powinno znajdować się na końcu,
  • where TBaseClass : BaseClassName – typ musi bazować na klasie o nazwie BaseClassName,
  • where TInterface : InterfaceName – wstrzykiwany typ musi implementować interfejs o nazwie InterfaceName,
  • where TType: U – typ generyczny TType musi być typu generycznego U.

 

Mam cichą nadzieję, iż jest to przydatna wiedza, ja na pewno nauczyłem się wiele pisząc tego posta, zachęcam do pisania zawsze jest duża szansa, iż napisałem jakąś  bujdę.

 

Jest to post przygotowany na potrzeby konkursu „Daj Się Poznać 2017” organizowanym przez Macieja Aniserowicza.