Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 3267 razy

Wstęp

Szablony są niezwykle ważnym elementem programowania, umożliwiają one dynamiczne dostosowanie kodu klasy do naszych potrzeb, a to dynamiczne dostosowanie wykonywane jest w trakcie jego kompilacji. Umożliwiają one opisanie za pomocą jednego kodu klas, czy metod klas, które będą się różniły jedynie typem danych w nich zawartych.

Przykład implementacji szablonu klasy

Przykład implementacji klasy szablonowej:

// ######################### SZABLON KLASY ######################## class point<T> where T : struct/*, class, IComparable, IConvertible*/ { protected T x; public T X { get { return x; } set { x = value; } } protected T y; public T Y { get { return y; } set { y = value; } } public point(T x, T y) { this.x = x; this.y = y; } public override string ToString() { return "point: x = " + x + "; y = " + y; } }

Jak widać w C# nie jest konieczne użycie słowa kluczowego template tak jak to miało miejsce w przypadku C++, wystarczy bowiem podać po słowie kluczowym class listę typów używanych w klasie, po czym możliwe jest jeszcze zdefiniowanie dodatkowych warunków, jakie dane typy muszą spełniać. W powyższym przykładzie zaznaczono, że T musi być typu wartościowego (czyli strukturą). można też wyszczególnić interfejsy, po których dana klasa musi dziedziczyć. I tutaj warto wyróżnić dwa typy interfejsów: IComparable i IConvertible. Jeżeli chcesz zaznaczyć, że dany typ musi wykorzystywać operatory porównania, to musisz do listy warunków dodać właśnie interfejs IComparable, natomiast gdy chcesz, aby dany typ obsługiwał metody związane z konwersją na typy proste, musisz dodać dziedziczenie po interfejsie IConvertible.

Można też wymusić, aby podany typ obsługiwał konstruktor bezparametrowy w następujący sposób:

class point<T> where T: class, new(){ ... }

Można też wymusić dziedziczenie jednego typu po drugim:

class point<T, A> where T: A, new(){ ... }