Introduzione ai Nullable Types con .NET Framework 1.1 e 2.0

2 pagine in totale: <<Indietro 1 [2]

Emulare un Int32 parte I: conversioni

Dovendo creare un nuovo tipo, un ruolo importante è ricoperto dalle conversioni (cast) che si possono effettuare da uno all'altro. La semplice conversione di una variabile da Int32 a Int32NT e viceversa, comporta la scrittura di codice da parte nostra.

Per passare da una Int32 ad una Int32NT il meccanismo può essere gestito implicitamente, in quanto non potendo il tipo Int32 essere null ed essendo Int32 dello stesso tipo di cui Int32NT fa da wrapper, non abbiamo bisogno di far effettuare all'utente un cast specifico.ta già ariabile Da Int32 a Int32NT e viceversa, comporta già un nuovo ffettuare da un tipo ad un altroall'utente un Cast specifico Stessa cosa dicasi per i tipi numerici di dimensioni inferiori a Int32 (Int16 e Byte). Andremo quindi ad eseguire l'overload implicito dell'operatore.

Al contrario, per passare da un Int32NT ad un Int32 è opportuno forzare l'utente a fare un cast in quanto si sta passando da una forma Nullable ad una Non-Nullable. Se poi il valore della variabile Int32NT è Null allora si solleverà l'eccezione impostata nel getter della proprietà Value. In questo caso eseguiremo l'overload esplicito dell'operatore.

  public static implicit operator Int32NT(int value){
   return new Int32NT(value);
  }
  public static explicit operator int(Int32NT value){
   return x.Value;
  }

Questo discorso è valido per la conversione tra tipi Int16, Int32 e NullableTypes, ma può, anzi deve, essere esteso ad ogni altro tipo per valore. Prendiamo ad esempio un tipo Int64 e cerchiamo di convertirlo in un Int32NT. Questo, allo stato attuale delle cose, può essere ottenuto solamente convertendo la variabile da Int64 a Int32 per poi passarla alla variabile Int32NT.

Sebbene funzionante, l'eleganza del codice ne risente, in quanto l'operazione può essere necessaria in più punti e siamo quindi costretti a replicare il codice. La cosa migliore da fare è utilizzare l'overload dell'operatore che accetti in input un tipo INT64 e la converta in Int32 così da eliminare tutte le conversioni nel codice. Questo meccanismo può essere implementato per tutti i tipi (Double, Decimal, Single, ecc ecc.)

  public static explicit operator Int32NT(Int64 value) {
   checked { return new Int32NT(Convert.ToInt32(value)); }
  }

La nostra classe è così pronta per convertire qualunque, o quasi, tipo.

Creare un wrapper per un solo tipo non è molto utile, l'ideale è avere a disposizione una suite di wrapper per ogni tipo. Questo apre uno scenario in cui si ha l'esigenza di convertire da un tipo Nullable ad un altro tipo Nullable. Questo evita di fare casting da tipi Nullable a Non-Nullable e poi di nuovo a Nullable.

  public static explicit operator Int32NT (StringNT value){
   if (!value.HasValue) return Int32NT.Null;

   return new Int32NT(Convert.ToInt32(value));
  }

Proseguendo su questa riga, saremmo in grado di convertire qualunque tipo, sia esso Nullable che Non-Nullable, nel nostro tipo.

Emulare un Int32 parte II: operazioni matematiche

Il nostro wrapper manca ancora di una caratteristica fondamentale: non può effettuare le operazioni matematiche. Infatti non possiamo sommare una struttura ad una variabile int o ad un'altra struttura.

Anche in questo caso ci torna utile l'overload degli operatori. Al momento di fare una somma, moltiplicazione, o una qualsiasi altra operazione, possiamo intercettare il processo e dire al nostro tipo che i fattori dell'operazione non sono le strutture stesse, ma il valore che esse espongono. Per emulare il comportamento della versione 2.0, osserviamo che quando una delle due variabili di input è Null viene restituito Null e non viene sollevata nessuna eccezione.

  public static Int32NT operator + (Int32NT value1, Int32NT value2) {
   if (!value1.HasValue || !value2.HasValue) return Int32NT.Null;

   checked { return new Int32NT(value1.Value + value2.Value); }
  }
  public static Int32NT operator  - (Int32NT value1, Int32NT value2) {
   if (!value1.HasValue || !value2.HasValue) return Int32NT.Null;

   checked { return new Int32NT(value1.Value - value2.Value); }
  }

Conclusioni

In questo articolo abbiamo visto come sia possibile implementare una struttura Nullable Types per un tipo Int32. La stessa logica può essere applicata su tutti gli altri tipi del .NET Framework.

Così facendo si può creare una libreria che sfrutti in maniera totale i Nullable Types anche di altri tipi. Ad esempio, l'operatore ">" della classe Int32NT potrebbe tornare un BooleanNT invece che un bool, cosa, tra l'altro, corretta in caso si faccia il raffronto tra 2 Int32NT di cui uno e Null.

Una libreria del genere è stata già implementata da Luca Minudel che ringrazio per la collaborazione.

Approfondimenti

2 pagine in totale: <<Indietro 1 [2]

Contenuti dell'articolo

Commenti
Dai un voto a questo articolo, ci aiuterà a migliorare il nostro sito (1 è il voto minimo, 5 il massimo).

Per procedere al rating dell'articolo devi essere autenticato.

Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.


TUTORIALS
TOP TEN ARTICOLI
NOTIFICHE

Iscriviti alla nostra newsletter nuoviarticoli per ricevere e-mail le notifiche!

Indirizzo e-mail:
PROVIDER ASP.NET 2.0

Seleziona il database per avere il web.config pronto per Membership, Roles e Profile API.



IN EVIDENZA
MISC