C#: Conversão de tipos
1. Conversão implícita
A conversão implícita é realizada automaticamente pelo compilador, sem qualquer sintaxe adicional. Ela ocorre ao atribuir um valor de um tipo mais restrito a um tipo mais amplo e nunca resulta em perda de dados.
(1) Regras de conversão
int→longint→doublefloat→double- Qualquer tipo →
string(por meio deToString())
▶ Exemplo
int a = 100;
long b = a;
int c = 42;
double d = c;
float e = 3.14f;
double f = e;
int g = 99;
string h = g.ToString();
Console.WriteLine($"int→long: {b}");
Console.WriteLine($"int→double: {d}");
Console.WriteLine($"float→double: {f}");
Console.WriteLine($"int→string: {h}");
int→long: 100
int→double: 42
float→double: 3.14
int→string: 99
2. Conversão explícita
A conversão explícita requer uma sintaxe de conversão, colocando o tipo de destino entre parênteses antes do valor. Ela ocorre ao atribuir um valor de um tipo mais amplo para um tipo mais restrito e pode resultar na perda de dados.
(1) Sintaxe
TargetType variable = (TargetType)value;
▶ Exemplo
double pi = 3.14;
int truncated = (int)pi;
int number = 42;
double widened = (double)number;
long big = 3000000000L;
int overflow = (int)big;
Console.WriteLine($"(int)3.14 → {truncated}");
Console.WriteLine($"(double)42 → {widened}");
Console.WriteLine($"(int)3000000000L → {overflow}");
(int)3.14 → 3
(double)42 → 42
(int)3000000000L → -1294967296
Aviso: A conversão explícita pode causar perda de precisão ou estouro. Sempre verifique o intervalo dos dados antes de realizar a conversão.
3. Classe de conversão
A classe System.Convert oferece métodos estáticos para a conversão entre vários tipos básicos. É mais segura e mais expressiva do que uma conversão direta.
(1) Métodos comuns
| Método | Descrição |
|---|---|
Convert.ToInt32 |
Converte para int |
Convert.ToDouble |
Converte para double |
Convert.ToString |
Converte para string |
Convert.ToBoolean |
Converte para bool |
▶ Exemplo
string s1 = "42";
string s2 = "3.14";
string s3 = "0";
int n1 = Convert.ToInt32(s1);
double n2 = Convert.ToDouble(s2);
string n3 = Convert.ToString(n1);
bool n4 = Convert.ToBoolean(s3);
bool n5 = Convert.ToBoolean(1);
Console.WriteLine($"ToInt32: {n1}");
Console.WriteLine($"ToDouble: {n2}");
Console.WriteLine($"ToString: {n3}");
Console.WriteLine($"ToBoolean(\"0\"): {n4}");
Console.WriteLine($"ToBoolean(1): {n5}");
ToInt32: 42
ToDouble: 3.14
ToString: 42
ToBoolean("0"): False
ToBoolean(1): True
Dica:
Convert.ToBooleanreconhece apenas"True"e"False"para strings. Para valores numéricos, valores diferentes de zero correspondem atruee zero corresponde afalse.
4. Parse e TryParse
(1) Método de análise
Parse converte uma string para o tipo de destino e lança uma exceção FormatException se o formato for inválido.
Exemplo
int a = int.Parse("42");
double b = double.Parse("3.14");
Console.WriteLine($"int.Parse: {a}");
Console.WriteLine($"double.Parse: {b}");
int.Parse: 42
double.Parse: 3.14
try
{
int bad = int.Parse("hello");
}
catch (FormatException ex)
{
Console.WriteLine($"Parse failed: {ex.Message}");
}
Parse failed: Input string was not in a correct format.
(2) Método TryParse
TryParse nunca lança uma exceção. Ele retorna um bool indicando sucesso e exibe o valor analisado por meio de um parâmetro out.
Exemplo
if (int.TryParse("42", out int result1))
{
Console.WriteLine($"Parse succeeded: {result1}");
}
if (!int.TryParse("abc", out int result2))
{
Console.WriteLine($"Parse failed, result2 = {result2}");
}
Parse succeeded: 42
Parse failed, result2 = 0
Dica: Prefira
TryParseao lidar com entradas não confiáveis, como dados do usuário, para evitar o custo de desempenho associado às exceções.
5. Embalagem e desembalagem
(1) Boxe
Boxing é o processo de conversão de um tipo de valor para um tipo de referência object. O valor é copiado da pilha para o heap, o que implica uma alocação de memória.
Exemplo
int value = 42;
object boxed = value;
Console.WriteLine($"Boxed: {boxed}, Type: {boxed.GetType()}");
Boxed: 42, Type: System.Int32
(2) Desembalagem
O unboxing é o processo de converter explicitamente uma referência object de volta para um tipo de valor. Isso requer uma conversão explícita, e uma incompatibilidade de tipos gera uma exceção InvalidCastException.
Exemplo
object boxed = 42;
int unboxed = (int)boxed;
Console.WriteLine($"Unboxed: {unboxed}");
Unboxed: 42
object boxed = 42;
try
{
double wrong = (double)boxed;
}
catch (InvalidCastException ex)
{
Console.WriteLine($"Unbox type mismatch: {ex.Message}");
}
Unbox type mismatch: Specified cast is not valid.
Aviso: O tipo de destino em uma operação de desembalagem deve corresponder exatamente ao tipo embalado original; caso contrário, é lançada uma exceção
InvalidCastException.
6. Armadilhas comuns na conversão de tipos
(1) Perda de precisão na conversão de ponto flutuante para inteiro
double d = 9.99;
int i = (int)d;
Console.WriteLine($"9.99 → {i}");
9.99 → 9
(2) Transbordamento do tipo “Wide” para o tipo “Narrow”
long big = 5000000000L;
int small = (int)big;
Console.WriteLine($"5000000000L → {small}");
5000000000L → 705032704
(3) Exceção de análise ao encontrar strings inválidas
try
{
int n = int.Parse("3.14");
}
catch (FormatException)
{
Console.WriteLine("Cannot parse \"3.14\" as int");
}
Cannot parse "3.14" as int
Dica — Melhores práticas para evitar erros: verifique os intervalos de dados antes da conversão; dê preferência a
TryParse; use a palavra-chavecheckedem casos de estouro de memória.
❓ Perguntas Frequentes
P: A conversão implícita nunca causa perda de dados? R: Correto. A conversão implícita ocorre apenas em caminhos seguros, nos quais não há perda de precisão ou intervalo. P: Qual é a diferença entre o método Convert.ToInt32 e a conversão (int)? R: A conversão (int) realiza o truncamento diretamente, enquanto o método Convert.ToInt32 arredonda valores de ponto flutuante usando o arredondamento bancário. P: Como o boxing e o unboxing afetam o desempenho? R: O boxing aloca memória no heap, e o unboxing requer uma verificação de tipo e uma cópia de valor. Operações frequentes prejudicam o desempenho. P: O que é melhor: int.Parse ou Convert.ToInt32? R: Para entradas em forma de string, ambos se comportam de maneira semelhante, mas Convert.ToInt32 retorna 0 para valores nulos, enquanto int.Parse lança uma exceção. P: Qual é o valor do parâmetro
outquando oTryParsefalha? R: Ele é definido como o valor padrão do tipo; por exemplo, 0 paraint.
📖 Resumo
- A conversão implícita ocorre de tipos mais restritos para tipos mais amplos e é segura e automática
- A conversão explícita utiliza a sintaxe de conversão (cast) e pode resultar em perda de precisão ou estouro
- A classe
Convertoferece métodos seguros para conversão entre tipos - O Parse analisa diretamente as cadeias de caracteres e gera uma exceção em caso de falha; o TryParse retorna um valor booleano de forma segura
- O boxing envolve um tipo de valor como um objeto alocado no heap; o unboxing exige uma correspondência exata de tipos
- Prefira usar o TryParse no código de produção para evitar exceções e boxing implícito
📝 Exercícios
- Escreva um programa que converta implicitamente um valor
shortigual a 32767 parainte converta explicitamente um valorintigual a 32768 parashort, e observe os resultados - Use
Convert.ToInt32para converter 2,5 e 3,5 e verifique o comportamento de arredondamento do banco - Escreva um método que aceite um parâmetro do tipo string, utilize
TryParsepara analisá-lo com segurança como uminte retorne o valor analisado em caso de sucesso ou -1 em caso de falha - Escreva um código que demonstre o boxing e o unboxing; em seguida, faça um unboxing deliberadamente com o tipo errado e identifique o
InvalidCastException - Envolva uma conversão
intque gera overflow com a palavra-chavecheckede observe se é lançada uma exceçãoOverflowException