Exercício – Explorar a coerção e a conversão de tipo de dados
- 30 minutos
Há diversas técnicas para executar uma conversão de tipo de dados. A técnica escolhida depende de sua resposta a duas perguntas importantes:
- É possível, dependendo do valor, que a tentativa de alterar o tipo de dados do valor gerasse uma exceção em tempo de execução?
- É possível, dependendo do valor, que a tentativa de alterar o tipo de dados do valor resultasse em uma perda de informações?
Neste exercício, você analisa essas questões, as implicações de suas respostas e qual técnica você deve usar quando precisar alterar o tipo de dados.
Preparar o ambiente de codificação
Este módulo inclui atividades práticas que orientam você durante o processo de criação e execução do código de demonstração. Incentivamos você a concluir essas atividades usando o Visual Studio Code como ambiente de desenvolvimento. O uso do Visual Studio Code para essas atividades introduz você ao trabalho de elaboração e execução de códigos em um ambiente de desenvolvedor que é usado por profissionais em todo o mundo.
Observação
Se você realizou outros módulos do Microsoft Learn nesta série de C#, talvez já tenha criado uma pasta de projeto para exemplos de código. Nesse caso, é possível ignorar a seção a seguir e excluir o código no arquivo Program.cs usado em um exercício anterior.
Observação
Os exemplos de código neste exercício são projetados com base nas configurações de cultura dos EUA e usam um ponto (.) como separador decimal. Criar e executar o código com uma configuração de cultura que usa separadores decimais diferentes (como vírgula ,) pode fornecer resultados ou erros inesperados. Para corrigir esse problema, substitua os separadores decimais de ponto nos exemplos de código pelo separador decimal local (como ,).
Como alternativa, para executar um programa usando a configuração de cultura dos EUA, adicione o seguinte código à parte superior do programa: using System.Globalization;, e depois de quaisquer outras instruções using, adicione CultureInfo.CurrentCulture = new CultureInfo("en-US");.
Abra o Visual Studio Code.
Você pode usar o menu Iniciar do Windows (ou recurso equivalente em outro sistema operacional) para abrir o Visual Studio Code.
No menu Arquivo do Visual Studio Code, selecione Abrir Pasta.
Na caixa de diálogo Abrir Pasta , navegue até a pasta Área de Trabalho do Windows.
Se você tiver um local de pasta diferente no qual mantém os projetos de código, poderá usar esse local de pasta. Neste treinamento, o importante é ter um local que seja fácil de localizar e lembrar.
Na caixa de diálogo Abrir Pasta, selecione Selecionar Pasta.
Se você vir uma caixa de diálogo de segurança perguntando se confia nos autores, selecione Sim.
No menu Terminal do Visual Studio Code, selecione Novo Terminal.
Observe que o prompt de comando no painel Terminal exibe o caminho da pasta atual. Por exemplo:
C:\Users\someuser\Desktop>Para criar um aplicativo de console em uma pasta especificada, no prompt de comando do Terminal, digite:
dotnet new console -o ./CsharpProjects/TestProjecte pressione Enter.Este comando da CLI do .NET usa um modelo de programa .NET para criar o novo projeto de aplicativo de console C# no local da pasta especificada. O comando cria as pastas CsharpProjects e TestProject para você e usa TestProject como o nome do arquivo
.csproj.No painel EXPLORER, expanda a pasta CsharpProjects.
Você deverá ver a pasta TestProject e dois arquivos, o arquivo de programa C# denominado Program.cs e o arquivo de projeto C# denominado TestProject.csproj.
No painel EXPLORER, para exibir o arquivo de código no painel Editor, selecione Program.cs.
Exclua as linhas de código existentes.
Você usa este projeto de console em C# para criar, compilar e executar exemplos de código durante este módulo.
Feche o painel do Terminal.
Pergunta: Tentar alterar o tipo de dados do valor geraria uma exceção no tempo de execução?
O compilador C# tenta acomodar o código, mas não compila operações que resultariam em uma exceção. Ao entender a principal preocupação do compilador C#, fica mais fácil entender por que ele funciona dessa maneira.
Escreva um código que tente somar um int com uma string e salve o resultado em um int
Verifique se o Visual Studio Code está aberto e se o arquivo Program.cs está sendo exibido no painel do Editor.
Observação
Program.cs deve estar vazio. Se não estiver, selecione e exclua todas as linhas de código existentes.
Digite o código de exemplo a seguir no Editor do Visual Studio Code:
int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);Aqui, você tentará adicionar os valores
2e4. O valor4é do tipostring. Isso funcionará?No menu Arquivo do Visual Studio Code, selecione Salvar.
O arquivo Program.cs deve ser salvo antes da compilação ou execução do código.
No painel EXPLORER, para abrir um Terminal no local da pasta TestProject, clique com o botão direito do mouse em TestProject e selecione Abrir no Terminal Integrado.
Um painel “Terminal” deve ser aberto e incluir um prompt de comando que mostra que o terminal está aberto no local da pasta TestProject.
No prompt de comando do Terminal, para executar o código, digite
dotnet rune pressione Enter.Você verá a seguinte saída aproximada
C:\Users\someuser\Desktop\csharpprojects\TestProject\Program.cs(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int'Observação
Se você vir a mensagem "Não foi possível encontrar um projeto para executar", verifique se o prompt de comando do Terminal exibe o local esperado da pasta TestProject. Por exemplo:
C:\Users\someuser\Desktop\csharpprojects\TestProject>Considere cuidadosamente por que o compilador não conseguiu executar o primeiro exemplo de código.
A parte importante da mensagem de erro,
(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int', informa que o problema está no uso do tipo de dadosstring.Mas por que o compilador C# não pode simplesmente lidar com o erro? Afinal, você pode fazer o contrário para concatenar um número a um
stringe salvá-lo em uma variável de cadeia de caracteres. Aqui, você altera o tipo de dados da variávelresultdeintparastring.Atualize o código no Editor do Visual Studio Code da seguinte maneira:
int first = 2; string second = "4"; string result = first + second; Console.WriteLine(result);Salve o arquivo de código e use o Visual Studio Code para executar o código.
A seguinte saída deve ser exibida:
24A saída é matematicamente incorreta, mas foi concluída combinando os valores como os caracteres "2" e "4".
Examine, mais uma vez, o primeiro exemplo de código em que a variável
resulté do tipoint. O código com a mensagem de erro.int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);Por que o compilador C# não consegue descobrir que você deseja abordar a variável
secondque contém4como um número, não como umstring?
Compiladores fazem conversões seguras
O compilador C# vê um possível problema na criação. A variável second é do tipo string, portanto, é possível defini-la com um valor diferente, como "hello". Se o compilador C# tentou converter "hello" em um número que causaria uma exceção em tempo de execução. Para evitar essa possibilidade, o compilador C# não executa implicitamente a conversão de string para int por você.
Da perspectiva do compilador C#, a operação mais segura seria converter int em um string e executar a concatenação em vez disso.
Se a sua intenção é fazer uma adição usando uma cadeia de caracteres, o compilador C# exige que você assuma um controle mais explícito do processo de conversão de dados. Em outras palavras, ele força você a ficar mais envolvido para poder tomar as precauções adequadas a fim de lidar com a possibilidade de que a conversão possa gerar uma exceção.
Se você precisar alterar um valor do tipo de dados original para um novo tipo de dados e a alteração puder produzir uma exceção em tempo de execução, você deverá executar uma conversão de dados.
Para executar a conversão de dados, você pode usar uma de várias técnicas:
- Usar um método auxiliar no tipo de dados
- Usar um método auxiliar na variável
- Use os métodos da classe
Convert
Você verá alguns exemplos dessas técnicas para conversão de dados posteriormente na unidade.
Pergunta: Tentar alterar o tipo de dados do valor resultaria em uma perda de informações?
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:int myInt = 3; Console.WriteLine($"int: {myInt}"); decimal myDecimal = myInt; Console.WriteLine($"decimal: {myDecimal}");Salve o arquivo de código e use o Visual Studio Code para executar o código.
A seguinte saída deve ser exibida:
int: 3 decimal: 3O segredo desse exemplo é esta linha de código:
decimal myDecimal = myInt;Como qualquer valor
intpode se ajustar facilmente dentro de umdecimal, o compilador executa a conversão.O termo conversão de expansão significa que você está tentando converter um valor de um tipo de dados que pode armazenar menos informações em um tipo de dados que pode armazenar mais informações. Neste caso, um valor armazenado em uma variável do tipo
intconvertida em uma variável do tipodecimalnão perde informação.Quando você sabe que está realizando uma conversão de expansão, pode confiar na conversão implícita. O compilador lida com conversões implícitas.
Executar uma coerção
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:decimal myDecimal = 3.14m; Console.WriteLine($"decimal: {myDecimal}"); int myInt = (int)myDecimal; Console.WriteLine($"int: {myInt}");Para executar uma coerção, use o operador de coerção
()para cercar um tipo de dados e coloque-o ao lado da variável que deseja converter (por exemplo:(int)myDecimal). Você executará uma conversão explícita para o tipo de dados de coerção definido (int).Salve o arquivo de código e use o Visual Studio Code para executar o código.
A seguinte saída deve ser exibida:
decimal: 3.14 int: 3O segredo desse exemplo é esta linha de código:
int myInt = (int)myDecimal;A variável
myDecimalcontém um valor que tem precisão após o ponto decimal. Ao adicionar a instrução de coerção(int), você está dizendo ao compilador C# que entende que é possível perder essa precisão e, caso isso aconteça, não será um problema. Você está dizendo ao compilador que está executando uma conversão intencional, uma conversão explícita.
Determine se sua conversão é uma "conversão de expansão" ou uma "conversão de restrição"
A conversão restritiva significa que você está tentando converter um valor de um tipo de dados que pode conter mais informações para um tipo de dados que pode conter menos informações. Nesse caso, você pode perder informações como precisão (ou seja, o número de valores após o ponto decimal). Um exemplo é converter o valor armazenado em uma variável do tipo decimal em uma variável do tipo int. Se você imprimir os dois valores, provavelmente notará a perda de informações.
Quando você sabe que está realizando uma conversão de restrição, precisa realizar uma coerção. A conversão cast é uma instrução ao compilador C# de que você sabe que talvez a precisão seja perdida, mas que se dispõe a aceitar isso.
Se você não tiver certeza se perde dados na conversão, escreva um código para executar uma conversão de duas maneiras diferentes e observe as alterações. Os desenvolvedores frequentemente escrevem pequenos testes para entender melhor os comportamentos, conforme ilustrado no próximo exemplo.
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:decimal myDecimal = 1.23456789m; float myFloat = (float)myDecimal; Console.WriteLine($"Decimal: {myDecimal}"); Console.WriteLine($"Float : {myFloat}");Salve o arquivo de código e use o Visual Studio Code para executar o código.
Você deve ver uma saída semelhante a:
Decimal: 1.23456789 Float : 1.2345679Observe na saída que a coerção de
decimalemfloaté uma conversão de restrição porque você está perdendo a precisão.
Executar conversões de dados
Anteriormente, foi declarado que uma alteração de valor de um tipo de dados para outro poderia causar uma exceção de runtime e é necessário realizar a conversão de dados. Para conversões de dados, há três técnicas que podem ser usadas:
- Usar um método auxiliar na variável
- Usar um método auxiliar no tipo de dados
- Use os métodos da classe
Convert
Use ToString() para converter um número em um string
Cada variável de tipo de dados tem um método ToString(). O que o método ToString() faz depende de como ele é implementado em um determinado tipo. No entanto, na maioria dos primitivos, ele executa uma conversão de expansão. Embora isso não seja estritamente necessário (já que é possível confiar na conversão implícita na maioria dos casos), pode comunicar a outros desenvolvedores que você entende o que está fazendo e é intencional.
Veja um exemplo rápido de como usar o método ToString() para converter explicitamente valores int em strings.
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:int first = 5; int second = 7; string message = first.ToString() + second.ToString(); Console.WriteLine(message);Salve o arquivo de código e use o Visual Studio Code para executar o código. Ao executar o código, a saída deve exibir uma concatenação dos dois valores:
57
Converter um string em um int usando o método auxiliar Parse()
A maioria dos tipos de dados numéricos tem um método Parse(), que converte uma cadeia de caracteres no tipo de dado especificado. Nesse caso, você usa o método Parse() para converter duas cadeias de caracteres em valores int e, em seguida, adiciona esses valores.
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:string first = "5"; string second = "7"; int sum = int.Parse(first) + int.Parse(second); Console.WriteLine(sum);Salve o arquivo de código e use o Visual Studio Code para executar o código. Quando você executa o código, a saída deve exibir uma soma dos dois valores:
12Reserve um minuto para tentar identificar o possível problema com o exemplo de código anterior. E se uma das variáveis
firstousecondestiver definida como valores que não podem ser convertidos em umint? Uma exceção é lançada no runtime. O compilador C# e o runtime esperam que você se antecipe e evite conversões "ilegais". É possível resolver a exceção do runtime de diversas maneiras.A maneira mais fácil é usar
TryParse(), que é uma versão melhorada do métodoParse().
Converter um string em um int usando a classe Convert
A classe Convert tem vários métodos auxiliares para converter um valor de um tipo em outro. No exemplo de código a seguir, você converterá algumas cadeias de caracteres em valores do tipo int.
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:string value1 = "5"; string value2 = "7"; int result = Convert.ToInt32(value1) * Convert.ToInt32(value2); Console.WriteLine(result);Salve o arquivo de código e use o Visual Studio Code para executar o código.
A seguinte saída deve ser exibida:
35Observação
Por que o nome do método é
ToInt32()? Por que nãoToInt()?System.Int32é o nome do tipo de dados subjacente na Biblioteca de Classes do .NET que a linguagem de programação C# mapeia para a palavra-chaveint. Como a classeConverttambém faz parte da Biblioteca de Classes do .NET, ela é chamada por seu nome completo, não pelo seu nome em C#. Definindo tipos de dados como parte da Biblioteca de Classes do .NET, várias linguagens .NET como Visual Basic, F#, IronPython e outras podem compartilhar os mesmos tipos de dados e as mesmas classes na Biblioteca de Classes do .NET.O método
ToInt32()tem 19 versões sobrecarregadas, o que permite aceitar praticamente todos os tipos de dados.Você usou o método
Convert.ToInt32()com uma cadeia de caracteres aqui, mas provavelmente deve usarTryParse()quando possível.Então, quando usar a classe
Convert? A classeConverté melhor para converter números fracionários em números inteiros (int) porque os arredonda da maneira esperada.
Comparar a coerção e a conversão de um decimal em um int
O exemplo a seguir demonstra o que acontece quando você tenta converter em cast um decimal em um int (uma conversão de restrição) em vez de usar o método Convert.ToInt32() para converter o mesmo decimal em um int.
Exclua ou use o operador de comentário de linha
//para remover o código da etapa do exercício anterior e adicione o seguinte código:int value = (int)1.5m; // casting truncates Console.WriteLine(value); int value2 = Convert.ToInt32(1.5m); // converting rounds up Console.WriteLine(value2);Salve o arquivo de código e use o Visual Studio Code para executar o código.
A seguinte saída deve ser exibida:
1 2
A coerção resulta em truncamentos e a conversão resulta em valores arredondados
Ao fazer a coerção de int value = (int)1.5m;, o valor do float é truncado para que o resultado seja 1, o que significa que o valor após o decimal é completamente ignorado. Você poderia alterar o float do literal para 1.999m e o resultado da conversão seria o mesmo.
Ao fazer a conversão usando Convert.ToInt32(), o valor do float literal é arredondado corretamente para 2. Se você alterar o valor literal para 1.499m, ele será arredondado para baixo para 1.
Recapitulação
Você aprendeu sobre diversos conceitos importantes de conversão e coerção de dados, como os seguintes:
- Evitar um erro de runtime ao executar uma conversão de dados
- Executar uma coerção explícita para informar ao compilador que você entende o risco de perda de dados
- Confiar no compilador para executar uma coerção implícita ao executar uma conversão de expansão
- Usar o operador de coerção
()e o tipo de dados para executar uma coerção (por exemplo,(int)myDecimal) - Usar a classe
Convertpara realizar uma conversão de restrição quando você deseja realizar um arredondamento, não um truncamento de informações