Casting e conversioni di tipi (Guida per programmatori C#)
Aggiornamento: Luglio 2008
Poiché il codice C# viene tipizzato in modo statico in fase di compilazione, una variabile dichiarata non può essere nuovamente dichiarata o utilizzata per archiviare valori di un altro tipo a meno che il tipo non sia convertibile nel tipo della variabile. Ad esempio, non esiste alcuna conversione da un valore integer a una stringa arbitraria. Pertanto, dopo avere dichiarato i come valore integer, non è possibile assegnare a esso la stringa "Hello", come mostrato nel codice seguente.
int i;
i = "Hello"; // Error: "Cannot implicitly convert type 'string' to 'int'"
Tuttavia, copiare un valore in una variabile o in un parametro di metodo di un altro tipo potrebbe essere talvolta necessario. Ad esempio, è possibile che si disponga di una variabile integer che è necessario passare a un metodo il cui parametro è tipizzato come double oppure che sia necessario assegnare una variabile di classe a una variabile di un tipo di interfaccia. Questi tipi di operazioni sono detti conversioni di tipi. In C#, è possibile eseguire i tipi di conversioni seguenti:
Conversioni implicite: non è richiesta alcuna sintassi speciale perché la conversione è indipendente dai tipi e nessun dato viene perso. Gli esempi includono le conversioni da tipi integrali più piccoli a più grandi e le conversioni da classi derivate a classi di base.
Conversioni esplicite (cast): le conversioni esplicite richiedono un operatore di cast. Le variabili di origine e di destinazione sono compatibili, ma c'è un rischio di perdita di dati perché il tipo della variabile di destinazione è di dimensione inferiore (o è una classe di base) della variabile di origine.
Conversioni definite dall'utente: le conversioni definite dall'utente vengono eseguite da metodi speciali che è possibile definire per attivare le conversioni esplicite e implicite fra tipi personalizzati privi di relazione classe di base-classe derivata. Per ulteriori informazioni, vedere la classe Operatori di conversione (Guida per programmatori C#).
Conversioni con le classi di supporto: per eseguire la conversione tra tipi non compatibili, ad esempio numeri interi e oggetti System.DateTime o stringhe esadecimali e matrici di byte, è possibile utilizzare la classe System.BitConverter, la classe System.Convert e i metodi Parse dei tipi numerici incorporati, ad esempio Int32.Parse. Per ulteriori informazioni, vedere Procedura: convertire una matrice di byte in un valore integer (Guida per programmatori C#), Procedura: convertire una stringa in un valore integer (Guida per programmatori C#) e Procedura: eseguire la conversione tra stringhe esadecimali e tipi numerici (Guida per programmatori C#).
Conversioni implicite
Per i tipi numerici incorporati, una conversione implicita può essere eseguita quando il valore da archiviare può essere adattato alla variabile senza essere troncato o arrotondato. Ad esempio, una variabile di tipo longlong (Riferimenti per C#) (valore integer a 8 byte) può archiviare qualsiasi valore archiviabile in intint (Riferimenti per C#) (4 byte su un computer a 32 bit). Nell'esempio seguente, il compilatore converte implicitamente il valore a destra in un tipo long prima di assegnarlo a bigNum.
// Implicit conversion. num long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
Per un elenco completo delle conversioni numeriche implicite, vedere Tabella delle conversioni numeriche implicite (Riferimenti per C#).
Per i tipi riferimento, esiste sempre una conversione implicita da una classe a una delle relative classi di base o interfacce dirette o indirette. Non è necessaria alcuna sintassi speciale perché una classe derivata contiene sempre tutti i membri di una classe di base.
Derived d = new Derived();
Base b = d; // Always OK.
Conversioni esplicite
Tuttavia, se una conversione non può essere eseguita senza un rischio di perdita di informazioni, il compilatore richiede che si esegua una conversione esplicita, chiamata cast. Il cast è un modo di informare in modo esplicito il compilatore che si intende eseguire la conversione e che si è consapevoli che potrebbe verificarsi una perdita di dati. Per eseguire un cast, specificare il tipo di destinazione del cast in parentesi davanti al valore o alla variabile da convertire. Il programma descritto di seguito esegue il cast di doubledouble (Riferimenti per C#) su intint (Riferimenti per C#). Se il cast non è presente, il programma non verrà compilato.
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
Per un elenco delle conversioni numeriche esplicite consentite, vedere Tabella delle conversioni numeriche esplicite (Riferimenti per C#).
Per i tipi riferimento, un cast esplicito è richiesto se è necessario eseguire la conversione da un tipo di base a un tipo derivato:
// Create a new derived type.
Giraffe g = new Giraffe();
// Implicit conversion to base type is safe.
Animal a = g;
// Explicit conversion is required to cast
// back to derived type. Note: This will compile but
// throw an exception at run time if the right-side
// object is not in fact a Giraffe.
Giraffe g2 = (Giraffe) a;
Un'operazione cast tra tipi riferimento non modifica il tipo in fase di esecuzione dell'oggetto sottostante, ma modifica solo il tipo del valore utilizzato come riferimento a tale oggetto. Per ulteriori informazioni, vedere Polimorfismo (Guida per programmatori C#).
Eccezioni di conversione di tipi in fase di esecuzione
In alcune conversioni di tipi riferimento, il compilatore non è in grado di determinare se un cast sarà valido. È possibile che un'operazione di cast compilata correttamente non riesca in fase di esecuzione. Come mostrato nell'esempio seguente, un cast di tipo che non riesce in fase di esecuzione provoca la generazione di InvalidCastException.
class Animal
{
public void Eat() { Console.WriteLine("Eating."); }
public override string ToString()
{
return "I am an animal.";
}
}
class Reptile : Animal { }
class Mammal : Animal { }
class UnSafeCast
{
static void Main()
{
Test(new Mammal());
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
static void Test(Animal a)
{
// Cause InvalidCastException at run time
// because Mammal is not convertible to Reptile.
Reptile r = (Reptile)a;
}
}
Il linguaggio C# fornisce gli operatori is e as per consentire di verificare la compatibilità prima di eseguire un cast. Per ulteriori informazioni, vedere Procedura: eseguire il cast sicuro tramite gli operatori as e is (Guida per programmatori C#).
Specifiche del linguaggio C#
Per ulteriori informazioni su cast e conversioni di tipi, vedere le seguenti sezioni incluse in Specifiche del linguaggio C#:
7.6.6 Espressioni cast
6.1 Conversioni implicite
6.2 Conversioni esplicite
Vedere anche
Attività
Procedura: convertire una stringa in un valore integer (Guida per programmatori C#)
Concetti
Conversione di tipi generalizzata
Conversione dei tipi esportati
Riferimenti
Tipi (Guida per programmatori C#)
Operatore () (Riferimenti per C#)
Operatori di conversione (Guida per programmatori C#)
Cronologia delle modifiche
Data |
Cronologia |
Motivo |
---|---|---|
Luglio 2008 |
Contenuto aggiunto all'introduzione e altrove. |
Correzione di errori nel contenuto. |