Esercizio - Esplorare il cast e la conversione del tipo di dati
- 30 minuti
Esistono diverse tecniche per eseguire la conversione di un tipo di dati. La scelta della tecnica dipende dalla risposta a due importanti domande:
- è possibile, a seconda del valore, che il tentativo di modificare il tipo di dati del valore generi un'eccezione in fase di esecuzione?
- è possibile, a seconda del valore, che il tentativo di modificare il tipo di dati del valore comporti una perdita di informazioni?
In questo esercizio si analizzeranno a fondo queste domande, le implicazioni delle risposte e la tecnica da usare quando è necessario modificare il tipo di dati.
Preparare l'ambiente di scrittura del codice
Questo modulo include attività pratiche che illustrano il processo di compilazione ed esecuzione del codice dimostrativo. È consigliabile completare queste attività usando Visual Studio Code come ambiente di sviluppo. L'uso di Visual Studio Code per queste attività consente di acquisire familiarità nella scrittura e nell'esecuzione del codice in un ambiente di sviluppo usato da professionisti di tutto il mondo.
Nota
Se si sono completati altri moduli di Microsoft Learn in questa serie C#, potrebbe essere già stata creata una cartella di progetto per gli esempi di codice. In tal caso, è possibile ignorare la sezione seguente della procedura ed eliminare il codice nel file Program.cs usato per un esercizio precedente.
Nota
Gli esempi di codice di questo esercizio sono progettati in base all'impostazione culturale "en-US", ovvero inglese statunitense, in cui viene usato il punto (.) come separatore decimale. Compilare e eseguire codice con un'impostazione culturale diversa che usa un separatore decimale diverso, ad esempio una virgola ,, potrebbe restituire errori o risultati imprevisti. Per risolvere questo problema, sostituire, negli esempi di codice, i separatori decimali sotto forma di punto, con il separatore decimale locale, ad esempio ,.
In alternativa, se si vuole eseguire un programma usando l'impostazione culturale "en-US", aggiungere il codice seguente all'inizio del programma: using System.Globalization;, e dopo ogni istruzione using, aggiungere CultureInfo.CurrentCulture = new CultureInfo("en-US");.
Aprire Visual Studio Code.
Per aprire Visual Studio Code è possibile usare il menu Start di Windows (o una risorsa equivalente per un altro sistema operativo).
Scegliere Apri cartella dal menu File di Visual Studio Code.
Nella finestra di dialogo Apri cartella passare alla cartella Desktop di Windows.
Se si dispone di un percorso di cartella diverso in cui si conservano i progetti di codice, è possibile usare tale percorso. Per questo training, l'aspetto importante è avere una posizione facile da individuare e ricordare.
Nella finestra di dialogo Apri cartellaselezionare Seleziona cartella.
Se viene visualizzata una finestra di dialogo di sicurezza che chiede se si considera attendibile gli autori, selezionare Sì.
Nel menu Terminale di Visual Studio Code selezionare Nuovo terminale.
Si noti che in un prompt dei comandi nel pannello Terminale viene visualizzato il percorso della cartella corrente. Ad esempio:
C:\Users\someuser\Desktop>Nel prompt dei comandi del Terminale, per creare una nuova applicazione console in una cartella specificata digitare
dotnet new console -o ./CsharpProjects/TestProjecte premere INVIO.Questo comando dell'interfaccia della riga di comando .NET usa un modello di programma .NET per creare un nuovo progetto di applicazione console C# nel percorso di cartella specificato. Il comando crea le cartelle CsharpProjects e TestProject e usa TestProject come nome del file
.csproj.Nel pannello EXPLORER espandere la cartella CsharpProjects .
Verrà visualizzata la cartella TestProject con due file, un file di programma C# denominato Program.cs e un file di progetto C# denominato TestProject.csproj.
Nel pannello EXPLORER selezionare Program.cs per visualizzare il file di codice nel pannello Editor.
Eliminare le righe di codice esistenti.
Questo progetto console C# verrà usato per creare, compilare ed eseguire esempi di codice durante questo modulo.
Chiudere il pannello Terminale.
Domanda: È possibile che il tentativo di modificare il tipo di dati del valore generi un'eccezione in fase di esecuzione?
Il compilatore C# prova ad adattare il codice, ma non completa un'operazione che potrebbe generare un'eccezione. Conoscendo la priorità del compilatore C#, sarà più facile capire perché funzioni in un determinato modo.
Scrivere codice che prova ad aggiungere un valore int e un valore string e a salvare il risultato in un valore int
Assicurarsi che Visual Studio Code sia aperto e che Program.cs sia visualizzato nel pannello dell'editor.
Nota
Program.cs deve essere vuoto. In caso contrario, selezionare ed eliminare tutte le righe di codice.
Digitare il codice seguente nell'editor di Visual Studio Code:
int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);In questo caso si prova ad aggiungere i valori
2e4. Il valore4è di tipostring. Funzionerà?Scegliere Salva dal menu File di Visual Studio Code.
Il file Program.cs deve essere salvato prima di compilare o eseguire il codice.
Nel pannello EXPLORER, per aprire un terminale nel percorso della cartella TestProject, fare clic con il pulsante destro del mouse su TestProject e quindi scegliere Apri nel terminale integrato.
Verrà aperto un pannello del terminale con un prompt dei comandi che indica che il terminale è aperto al percorso della cartella TestProject.
Nel prompt dei comandi del terminale, digitare
dotnet runper eseguire il codice, quindi premere INVIO.Verrà visualizzato l'output approssimato seguente
C:\Users\someuser\Desktop\csharpprojects\TestProject\Program.cs(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int'Nota
Se viene visualizzato un messaggio che indica "Impossibile trovare un progetto da eseguire", assicurarsi che il prompt dei comandi del terminale visualizzi il percorso previsto della cartella TestProject. Ad esempio:
C:\Users\someuser\Desktop\csharpprojects\TestProject>Prendere in considerazione il motivo per cui il compilatore non è riuscito a eseguire il primo esempio di codice.
La parte importante del messaggio di errore,
(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int', indica che il problema è legato all'uso del tipo di datistring.Tuttavia, perché il compilatore C# non riesce a gestirlo? Dopo tutto, è possibile eseguire l'opposto per concatenare un numero a un
stringe salvarlo in una variabile stringa. In questo caso, si cambierà il tipo di dati della variabileresultdaintastring.Aggiornare il codice nell'editor di Visual Studio Code come indicato di seguito:
int first = 2; string second = "4"; string result = first + second; Console.WriteLine(result);Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice.
e si dovrà osservare l'output seguente:
24L'output è matematicamente errato, ma viene completato combinando i valori come caratteri "2" e "4".
Esaminare ancora una volta il primo esempio di codice in cui la variabile
resultè di tipoint. Il codice con il messaggio di errore.int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);Perché il compilatore C# non riesce a capire che la variabile
secondcontenente4deve essere trattata come numero e non comestring?
I compilatori rendono sicure le conversioni
Il compilatore C# rileva un potenziale problema nell'esecuzione. La variabile second è di tipo string, quindi potrebbe essere impostata su un valore diverso, ad esempio "hello". Se il compilatore C# provasse a convertire "hello" in un numero, verrebbe generata un'eccezione in fase di esecuzione. Per evitare questa possibilità, il compilatore C# non eseguirà automaticamente la conversione implicita da string a int.
Dal punto di vista del compilatore C#, l'operazione più sicura consiste nel convertire int in string e nell'eseguire invece la concatenazione.
Se si intende eseguire l'addizione usando una stringa, il compilatore C# richiede di assumere un controllo più esplicito del processo di conversione dei dati. In altre parole, richiede un maggior coinvolgimento da parte dell'utente, che in questo modo potrà adottare le precauzioni appropriate nell'eventualità che la conversione generi un'eccezione.
Se è necessario modificare un valore dal tipo di dati originale a un nuovo tipo di dati e la modifica potrebbe generare un'eccezione in fase di esecuzione, è necessario eseguire una conversione dei dati.
Per eseguire la conversione dei dati, è possibile scegliere una delle tecniche seguenti:
- Usare un metodo helper per il tipo di dati
- Usare un metodo helper per la variabile
- Usare i metodi della classe
Convert
Più avanti in questa unità verranno esaminati alcuni esempi di queste tecniche per la conversione dei dati.
Domanda: È possibile che il tentativo di modificare il tipo di dati del valore comporti una perdita di informazioni?
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:int myInt = 3; Console.WriteLine($"int: {myInt}"); decimal myDecimal = myInt; Console.WriteLine($"decimal: {myDecimal}");Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice.
Verrà visualizzato l'output seguente:
int: 3 decimal: 3La chiave di questo esempio è questa riga di codice:
decimal myDecimal = myInt;Poiché qualsiasi valore
intpuò adattarsi facilmente a un valoredecimal, il compilatore esegue la conversione.Il termine conversione con estensione significa che si sta tentando di convertire un valore da un tipo di dati che potrebbe contenere meno informazioni in un tipo di dati che può contenere altre informazioni. In questo caso, un valore archiviato in una variabile di tipo
intconvertito in una variabile di tipodecimalnon perde informazioni.Quando si sa che si sta eseguendo una conversione più ampia, è possibile basarsi sulla conversione implicita. Il compilatore gestisce le conversioni implicite.
Eseguire un cast
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:decimal myDecimal = 3.14m; Console.WriteLine($"decimal: {myDecimal}"); int myInt = (int)myDecimal; Console.WriteLine($"int: {myInt}");Per eseguire un cast, usare l'operatore di cast
()per racchiudere un tipo di dati, quindi posizionarlo accanto alla variabile che si vuole convertire (esempio:(int)myDecimal). Si esegue una conversione esplicita nel tipo di dati cast definito (int).Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice.
Verrà visualizzato l'output seguente:
decimal: 3.14 int: 3La chiave di questo esempio è questa riga di codice:
int myInt = (int)myDecimal;La variabile
myDecimalcontiene un valore con precisione dopo il separatore decimale. Aggiungendo l'istruzione di cast(int), viene indicato al compilatore C# di essere consapevoli che potrebbe verificarsi una perdita di precisione e che, in questa situazione, è accettabile. Si sta dicendo al compilatore che si sta eseguendo una conversione intenzionale, una conversione esplicita.
Determinare se una conversione sia una "conversione che supporta un maggior numero di dati" o una "conversione che supporta un minor numero di dati"
Il termine conversione riduttiva indica che si sta tentando di convertire un valore da un tipo di dati che può contenere più informazioni in un tipo di dati che può contenere meno informazioni. In questo caso, è possibile perdere informazioni come la precisione, ovvero il numero di valori dopo la virgola decimale. Un esempio è la conversione di un valore archiviato in una variabile di tipo decimal in una variabile di tipo int. Se si stampassero i due valori, è probabile che si noterebbe la perdita di informazioni.
Quando si deve eseguire una conversione che supporta un minor numero di dati, sarà necessario eseguire un cast. Il cast è un'istruzione per il compilatore C# che indica che si sa che si potrebbe verificare una perdita di precisione e che ciò è accettabile.
Se non si è certi della perdita di dati nella conversione, scrivere codice per eseguire una conversione in due modi diversi e osservare le modifiche. Gli sviluppatori scrivono spesso piccoli test per comprendere meglio i comportamenti, come illustrato nell'esempio successivo.
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:decimal myDecimal = 1.23456789m; float myFloat = (float)myDecimal; Console.WriteLine($"Decimal: {myDecimal}"); Console.WriteLine($"Float : {myFloat}");Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice.
L'output visualizzato sarà simile al seguente:
Decimal: 1.23456789 Float : 1.2345679È possibile osservare dall'output che il cast di un
decimalinfloatè una conversione che supporta un minor numero di dati, perché si perde precisione.
Esecuzione di conversioni di dati
In precedenza è stato dichiarato che una modifica di valore da un tipo di dati a un altro potrebbe causare un'eccezione di runtime e che sarà necessario convertire i dati. Per le conversioni di dati, è possibile usare tre tecniche:
- Usare un metodo helper per la variabile
- Usare un metodo helper per il tipo di dati
- Usare i metodi della classe
Convert
Usare ToString() per convertire un numero in un string
Ogni variabile del tipo di dati ha un metodo ToString(). Il comportamento del metodo ToString() dipende da come viene implementato in un determinato tipo. Tuttavia, per la maggior parte delle primitive viene eseguita una conversione che supporta un maggior numero di dati. Anche se ciò non è strettamente necessario (dal momento che nella maggior parte dei casi è possibile usare la conversione implicita), in questo modo è possibile comunicare agli altri sviluppatori che si è consapevoli di ciò che si sta facendo intenzionalmente.
Di seguito è riportato un esempio di uso del metodo ToString() per convertire in modo esplicito i valori int in string.
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:int first = 5; int second = 7; string message = first.ToString() + second.ToString(); Console.WriteLine(message);Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice. Quando si esegue il codice, l'output dovrebbe visualizzare una concatenazione dei due valori:
57
Convertire un oggetto string in un oggetto int utilizzando il metodo helper Parse()
La maggior parte dei tipi di dati numerici ha un metodo Parse(), che converte una stringa nel tipo di dati specificato. In questo caso, si userà il metodo Parse() per convertire due stringhe in valori int e quindi sommarli.
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:string first = "5"; string second = "7"; int sum = int.Parse(first) + int.Parse(second); Console.WriteLine(sum);Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice. Quando si esegue il codice, l'output dovrebbe visualizzare una somma dei due valori:
12Provare a individuare il potenziale problema con l'esempio di codice precedente. Che cosa accade se una delle variabili
firstosecondè impostata su un valore che non può essere convertito inint? Viene generata un'eccezione in fase di esecuzione. Il compilatore e il runtime C# prevedono che l'utente pianifichi in anticipo ed eviti conversioni "illegali". È possibile attenuare l'eccezione di runtime in diversi modi.Il modo più semplice per evitare questa situazione consiste nell'usare
TryParse(), che è una versione migliore del metodoParse().
Convertire un oggetto string in un oggetto int utilizzando la classe Convert
La classe Convert include molti metodi helper che consentono di convertire un valore da un tipo in un altro. Nell'esempio di codice seguente un paio di stringhe verranno convertite in valori di tipo int.
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:string value1 = "5"; string value2 = "7"; int result = Convert.ToInt32(value1) * Convert.ToInt32(value2); Console.WriteLine(result);Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice.
Verrà visualizzato l'output seguente:
35Nota
Perché il nome del metodo è
ToInt32()? Perché nonToInt()?System.Int32è il nome del tipo di dati sottostante nella libreria di classi .NET di cui il linguaggio di programmazione C# esegue il mapping alla parola chiaveint. Poiché la classeConvertfa anche parte della libreria di classi .NET, viene chiamata con il nome completo e non con il nome C#. Definendo i tipi di dati come parte della libreria di classi .NET, più linguaggi .NET, ad esempio Visual Basic, F#, IronPython e altri, possono condividere gli stessi tipi di dati e le stesse classi nella libreria di classi .NET.Il metodo
ToInt32()ha 19 versioni di overload che gli consentono di accettare praticamente tutti i tipi di dati.In questo caso è stato usato il metodo
Convert.ToInt32()con una stringa, ma, quando è possibile, è consigliabile usareTryParse().Quindi, quando si deve usare la classe
Convert? La classeConvertè la scelta migliore per convertire numeri frazionari in numeri interi (int) perché esegue gli arrotondamenti previsti.
Confrontare il cast e convertire un decimal in un int
L'esempio seguente illustra che cosa accade quando si prova a eseguire il cast di decimal in int (conversione che supporta un minor numero di dati) rispetto a quando si usa il metodo Convert.ToInt32() per convertire lo stesso decimal in int.
Eliminare o usare l'operatore di commento della riga
//per impostare come commento il codice dal passaggio dell'esercizio precedente e aggiungere il codice seguente:int value = (int)1.5m; // casting truncates Console.WriteLine(value); int value2 = Convert.ToInt32(1.5m); // converting rounds up Console.WriteLine(value2);Salvare il file di codice e quindi usare Visual Studio Code per eseguire il codice.
Verrà visualizzato l'output seguente:
1 2
Il cast tronca, mentre la conversione arrotonda
Quando si esegue il cast di int value = (int)1.5m;, il valore del float viene troncato, quindi il risultato è 1 e il valore dopo il separatore decimale viene ignorato completamente. Se si cambiasse il float letterale in 1.999m, il risultato del cast sarebbe lo stesso.
Quando si esegue la conversione usando Convert.ToInt32(), il valore float letterale viene arrotondato correttamente per eccesso a 2. Se si modificasse il valore letterale in 1.499m, verrebbe arrotondato per difetto a 1.
Riepilogo
Sono stati illustrati diversi concetti importanti relativi alla conversione e al cast dei dati:
- Impedire un errore di runtime durante l'esecuzione di una conversione dei dati
- Eseguire un cast esplicito per indicare al compilatore di essere consapevoli del rischio di perdita di dati
- Usare il compilatore per eseguire un cast implicito quando si esegue una conversione che supporta un maggior numero di dati
- Usare l'operatore di cast
()e il tipo di dati per eseguire un cast (ad esempio(int)myDecimal) - Usare la classe
Convertquando si vuole eseguire una conversione che supporta un minor numero di dati, ma si vuole eseguire l'arrotondamento senza troncare le informazioni