Casting

.::Home::.

.::Introduzione::.

1.Panoramica

4.DataBase

.::Presentazioni PPT::.

.::Link::.

.::DownLoad::.

 

Così come il boxing e l'unboxing permettono la conversione da value type a reference type e viceversa, la conversione tra reference type (oggetti) di tipi diversi è attuata attraverso il casting.

In conformità con l'architettura del .NET Framework l'operazione in C# è completamente type safe, e questo implica un vantaggio non indifferente, dal momento che in un ambiente unmanaged come C++ può avere, in caso di errori, effetti devastanti.

Dal momento che la sicurezza sui tipi è una delle principali caratteristiche del CLR, esso è sempre a conoscenza di che tipo è un qualunque oggetto. Anche il programmatore può sempre scoprire l'esatto tipo di un oggetto chiamando il metodo GetType. Dal momento che questo metodo non è virtuale, un tipo non può mai "imbrogliare", ad esempio scavalcando il metodo GetType per dichiararsi di tipo diverso da quello di appartenenza.

Per un programmatore è spesso necessario eseguire il cast (conversione) di un oggetto da un tipo all'altro e C# non richiede nessuna sintassi speciale per farlo con i propri tipi base. Comunque C# richiede che lo sviluppatore converta esplicitamente un tipo in uno dei suoi tipi derivati.

Supponiamo di creare due classi, mela (apple) e arancia (orange) e tentare di convertire mele in arance, operazione che C# (e la natura, per ora.) non ci permetterà di fare.

using System;

public class App {
class apple
{
  public string Fruit() { return "Apple"; }
}

class orange
{
  public string Fruit() { return "Orange"; }
}

static void Main() {
 apple myApple = new apple();
 orange myOrange = new orange();
 Console.WriteLine(myApple.Fruit());
 Console.WriteLine(myOrange.Fruit());
}
}

Casting

Anche se si andrà in contro ad una sconfitta, tentiamo comunque la conversione:

static void Main() {
apple myApple = new apple();
orange anotherOrange = (orange)myApple;
Console.WriteLine(myApple.Fruit());
Console.WriteLine(anotherOrange.Fruit());
}

Con questo codice l'unica cosa che si ottiene è il blocco della compilazione. C# sa che la conversione non è valida e l'eseguibile non sarà generato.

La ragione è ovviamente legata al fatto che la classe apple non ha nulla in comune con la classe orange.

In questo caso si utilizza un approccio diverso: per prima cosa si inserisce uno dei tipi in un oggetto generico objGeneral ed in seguito lo si converte nel tipo appropriato:

static void Main() {
apple myApple = new apple();
object objGeneral = myApple;
orange anotherOrange = (orange)objGeneral;
Console.WriteLine(myApple.Fruit());
Console.WriteLine(anotherOrange.Fruit());
}

Quando si sceglie un tipo sbagliato come è stato appositamente fatto qui, il CLR solleva una eccezione del tipo InvalidCastException durante il runtime.

Per catturare l'errore [vedi pagina sulle exception]:

static void Main() {
apple myApple = new apple();
object objGeneral = myApple;
 try
 {
   orange anotherOrange = (orange)objGeneral;
   // fai quel che vuoi con l'arancia!
 }
 catch(InvalidCastException e)
 {
   Console.WriteLine("L'arancia è marcia: "+e);
 }

}

In questo modo però si è venuti a conoscenza dell'insuccesso del cast solo attraverso un'eccezione. Sarebbe meglio poter sapere prima se un cast andrà a buon fine oppure no.

E' qui che entra in gioco l'operatore is.

L'operatore is

Come annunciato questo operatore permette di chiedere se il cast avrà successo o farà sorgere un'eccezione. Il codice seguente mostra come utilizzarlo in una applicazione.

static void Main() {
 apple myApple = new apple();
 object objGeneral = myApple;
 
 if (objGeneral is orange)
 {
   orange anotherOrange = (orange)objGeneral;
   // fai quel che vuoi con l'arancia!
 }
 else
 {
   Console.WriteLine("Non è un'Arancia!");
 }
}

L'operatore as

L'operatore as potrebbe essere considerato un cast senza eccezioni. La conversione è portata avanti in silenzio e se questa dovesse fallire, la variabile destinazione sarebbe impostata al valore null. Tutto ciò che rimane da fare è controllarla con uno statement if:

static void Main() {
 apple myApple = new apple();
 object objGeneral = myApple;
 
 orange anotherOrange;
 anotherOrange = objGeneral as orange;
 if (null != anotherOrange)
 {
   // fai quel che vuoi con l'arancia!
 }
 else
 {
   Console.WriteLine("Una bella spremuta di mela no?");
 }
}

Fonti:

http://www.aspheute.com/english/20001019.asp

Documentazione .NET Framework SDK

.::^top^::.

(2002) A cura di Carlo Becchi