tipuri generice in c#
Embed Size (px)
TRANSCRIPT
Tipuri generice in C#
Introducere Structuri de date type-safe; Reutilizarea algoritmilor de procesare fara cunoasterea tipului de date;
Problema//solutie object-based public class Stack { object[] m_Items; public void Push(object item) {...} public object Pop() {...} } //instante de tipuri diferite
Solutie 1public class Stack { readonly int m_Size; int m_StackPointer = 0; object[] m_Items; public Stack():this(100) { } public Stack(int size) { m_Size = size; m_Items = new object[m_Size]; } public void Push(object item) { if(m_StackPointer >= m_Size) throw new StackOverflowException(); m_Items[m_StackPointer] = item; m_StackPointer++; } public object Pop() { m_StackPointer--; if(m_StackPointer >= 0) { return m_Items[m_StackPointer]; } else { m_StackPointer = 0; throw new InvalidOperationException("Cannot pop an empty stack"); } } }
UtilizareStack stack = new Stack(); stack.Push(1); stack.Push(2); int number = (int)stack.Pop();
Probleme1. De performanta: -la tipuri valoare trebuie folosit procedeul boxing/unboxing; -la tipuri referinta trebuie conversie explicita:Stack stack = new Stack(); stack.Push("1"); string number = (string)stack.Pop();
2. Type-safety: Stack stack = new Stack(); stack.Push(1); //se compileaza, dar la executie apare exceptie string number = (string)stack.Pop();
Solutie alternativa Cate a structura pentru fiecare tip IntStack, StringStack, Problema: actiune error-prone (repetitiva). Copy+paste introduce totdeauna erori!!!! Cand se repara o eroare in codul pentru IntStack, acest lucru trebuie facut pentru toate celelalte,
Ce sunt tipurile generice Clase type-safe cu tipuri de date generice;//T este parametru tip-generic public class Stack { T[] m_Items; public void Push(T item) {...} public T Pop() {...} } Stack stack = new Stack(); stack.Push(1); stack.Push(2); int number = stack.Pop();AVANTAJ: algoritmii interni raman neschimbati pentru toate tipurile de date
Clase si structuri genericepublic struct Point { public T X; public T Y; } Point point1; point1.X = 1;
point1.Y = 2;Point point2; point2.X = 1.2; point2.Y = 3.4;
Operatorul default()public T Pop() { m_StackPointer--; if(m_StackPointer >= 0) { return m_Items[m_StackPointer]; } else { m_StackPointer = 0; return default(T); } } //default(T) intoarce valoare default a tipului T
Mai multi parametrii//lista cu legaturiclass Node { public K Key; public T Item; public Node NextNode; public Node() { Key = default(K); Item = defualt(T); NextNode = null; } public Node(K key,T item,Node nextNode) { Key = key; Item = item; NextNode = nextNode; } } public class LinkedList { Node m_Head; public LinkedList() { m_Head = new Node(); } public void AddHead(K key,T item) { Node newNode = new Node(key,item,m_Head.NextNode); m_Head.NextNode = newNode; } }
Mai multi parametriiFiecare nod contine o cheie (de tip generic K) si o valoare (de tip generic T); Utilizare: LinkedList list1= new LinkedList(); list1.AddHead(123,"AAA");
LinkedList list2 = new LinkedList(); list2.AddHead(DateTime.Now,"AAA");
Alias pentru combinatii particulare de tipuriusing List = LinkedList; class ListClient { static void Main(string[] args) { List list = new List(); list.AddHead(123,"AAA"); } }
//scope: la nivel de fisier in care apare
Constrangeri pentru tipurile generice1. Constr. la derivare: parametrul generic este derivat dintr-o superclasa sau interfata public class LinkedList { T Find(K key) {...} //cautarea unei valori dupa cheie public T this[K key] { //indexare dupa cheie get{return Find(key);} } } //nu se compileaza in acest moment
T Find(K key) { Node current = m_Head; while(current.NextNode != null) { if(current.Key == key) //nu se compileaza break; else current = current.NextNode; } return current.Item; }
public interface IComparable { int CompareTo(object obj);
}
public class LinkedList where K : IComparable { T Find(K key) { Node current = m_Head; while(current.NextNode != null) { if(current.Key.CompareTo(key) == 0) break; else current = current.NextNode; } return current.Item; } //Restul implementarii }
Alte combinatii1. public class MyBaseClass {...} public class LinkedList where K : MyBaseClass {...}
2. public class MyClass where T : U {...}
3. public interface IMyInterface {...} public class MyClass where T : IMyInterface {...}MyClass obj = new MyClass();
Constrangere Constructorclass Node where T : new() { public K Key; public T Item; public Node NextNode; public Node() { Key = default(K); Item = new T(); NextNode = null; } } //tipul T trebuie sa detina constructor default
Constrangere tip referinta/valoarepublic class MyClass where T : struct {...} public class MyClass where T : class {...}