Manage data in a .NET Framework application using .NET Framework 2.0 system types (System namespace)
Generics: fanno riferimento a classi e metodi che lavorano allo stesso modo su differenti tipi di oggetti. Quando vengono istanziati, necessitano sempre di un tipo di dati, cosi’ da dargli un “preciso significato” e rappresentano l’implementazione in C# dei template del C++.
Uno dei vantaggi dei generics è quello di far risparmiare sul boxing/unboxing: la collezione generica “List” è l’equivalente di “ArrayList”, se ci mettiamo degli interi o dei double o un altro valueTypes non c’e’ boxing per inserire i dati e unboxing per leggere, cosa decisamente apprezzabile in termini di performance.
Gli esempi in rete implementano tutti gli stack.
Allora faccio una lista :
public class myList1< T > {
….
public void Add(T newValue) {…….}
}
E la cosa bella è che in una lista di interi dichiarata con non ci posso mettere dei double e fare confusione. :-)
Voglio pero’ fare in modo che la lista sia sempre ordinata, indipendentemente dal tipo di contenuto. Faccio una lista 2 e gli dico che il tipo T, implemente l’interfaccia IComparable, cosi’ che poi posso fare una funzione di Add sfrutti il metodo CompareTo. (I tipi di base sono tutti derivati da IComparable!).
public class myList2<T> where T : System.IComparable<T>
{
const int minSize = 10;
private T[] myData = new T[minSize];
private int size=0;
public void Add(T newValue)
{ //tralascio tutti gli oggetti piu' piccoli
int destPos = 0;
for (; destPos < size && myData[destPos].CompareTo( newValue)< 0; destPos++) ;
//sposto tutti quelli piu' grandi
for (int moveThis = size-1; moveThis >= destPos; moveThis--)
myData[moveThis + 1] = myData[moveThis];
//inserisco nel posto libero il mio
myData[destPos] = newValue;
//aggiorno la dimensione ed eventualmente allargo l'array
size++;
if (size == myData.Length) enlargeArray();
}
public void Display(string msg)
{
Console.WriteLine(msg);
for (int i = 0; i < size; i++)
Console.WriteLine(myData[i].ToString() + " ");
}
public void enlargeArray() {...}
}
Deve andare con i tipi di base, con i double, con qualsiasi cosa che implementi l’IComparer, anche un ValueType. Modifico la classe PuntoStruct di alcuni giorni fa:
public struct PuntoStruct: IComparable < PuntoStruct >
{
private double _x, _y, _z;
public PuntoStruct(double x1, double y1, double z1) {…}
public int CompareTo( PuntoStruct other)
{
//faccio un ordinamento solo per X, tanto per provare
return (_x.CompareTo(other._x));
}
public override string ToString() {
return (string.Format("x = {0}, y ={1}, z = {2}", _x, _y, _z)); }
};
Se la uso posso istanziare tranquillamente sia una lista di interi:
myList2<int> lista2 = new myList2<int>();
che una lista dei miei punti
myList2<PuntoStruct > listaPunti = new myList2<PuntoStruct>();