Purtroppo i miei post riguardanti la preparazione per l’esame 70-536 si sono molto diradati, complice il crescente interesse sulla parte Unit Testing e Mocking che consuma la maggior parte del mio tempo, per non parlare del lavoro
. Ma non desisto, ho intenzione di prendere una certificazione Microsoft, anzi la butto lì….. voglio diventare MCT (di questo passo verso i 45 anni dovrei farcela
)
Parliamo di conversione tra i tipi.
Una conversione tra tipi può essere necessaria quando ad esempio si vogliono comparare due oggetti di tipo diverso. La conversione può essere:
Conversione implicita: il sistema effettua la conversione “senza bisogno di aiuto”; questo tipo di conversione è possibile quando il tipo di destinazione può accomodare tutti i possibili valori del tipo sorgente (Widening conversion). Il C# proibisce la conversione implicita da un tipo ad un altro quando essa causa perdita di precisione (narrowing conversion). In questo caso è necessaria la conversione esplicita.
Conversione esplicita: il sistema non è capace di effettuare la conversione e richiede che sia il programmatore a specificare la regola di conversione usando uno dei meccanismi seguenti:
- (type): il buon vecchio e caro cast è utilizzabile tra tipi che definiscono gli operatori di conversione specifici,
- System.Convert: consente la conversione tra tipi che implementano IConvertible,
- type.ToString: converte da tipo base a stringa (solleva eccezione se la conversione non è possibile),
- type.Parse: converte da stringa a tipo base (solleva eccezione se la conversione non è possibile),
- type.TryParse: come type.Parse converte da stringa a tipo base ma in questo caso se la conversione non è definita ritorna false,
Boxing e Unboxing:
Abbiamo già parlato di tipi Value e di tipi Reference. Il boxing non è altro che la conversione di un tipo Value in un tipo Reference (ad esempio la conversione di un int in un object). Tale conversione avviene anche quando si chiamano metodi virtuali di struct che derivano da System.Object.
L’unboxing è chiaramente l’operazione contraria.
Queste due operazioni se usate all’interno di cicli (loop) possono causare rallentamenti nelle performance. Ecco allora alcuni consigli per evitare il boxing/unboxing:
1) Usare i generics dove possibile invece di Object,
2) Fare l’override di ToString, Equals, GetHash per le strutture,
3) Per metodi che possono accettare diversi tipi value, fare sempre una versione del metodo specifica per il tipo (si legaal punto 1: evitare l’object).
Da ultimo vediamo quali tecniche si possono usare per implementare la conversioni tra tipi custom e tipi base:
A) Definire gli operatori di conversione, permette di specificare come convertire da tipo base a tipo custom e viceversa.
implicit operator da usare per le conversioni Widening.
explicit operator da usare per le conversioni Narrowing.
namespace ConsoleApplication1
{
public struct MyType
{
public double value;
public static implicit operator MyType (double a)
{
MyType b = new MyType();
b.value = a;
return b;
}
public static explicit operator int (MyType a)
{
return (int) a.value;
}
}
class Program
{
static void Main(string[] args)
{
MyType a;
double b = 10;
int c;
a = b; // Invece di a.value;
c = (int)a; // Invece di c = a.value;
}
}
}
Da notare che gli operatori vanno definit static e pubblici.
B) Fare l’override di ToString per consentire le conversioni verso string e l’override di Parse per le conversioni da string,
C) Implementare l’interfaccia System.IConvertible. Si tratta del overloading di una serie di metodi. Meglio far generare i metodi da Visual Studio ed implementare solo quelli che servono, lasciando gli altri generare l’eccezione NotImplementedException.
D) Implementare una classe TypeConverter che è utile per fare conversioni in design-time all’interno dell’ambiente di sviluppo Visual Studio per le Properties Window. Quest’ultimo metodo non è materia di esame.
Prossimo post: nuovo capitolo che parla dell’ I/O (Aiò!! Galapagos!)