Por que esta pergunta é tão popular no Stack Overflow?
Se você já programou em C# e precisou converter uma string em um array de bytes, certamente já se perguntou: "Por que eu preciso especificar a codificação? Afinal, uma string é apenas uma string!". Esta pergunta acumulou milhares de visualizações no Stack Overflow não por acaso. Ela aborda um mal-entendido fundamental entre como vemos o texto e como o computador o vê.
Neste artigo, não vamos apenas fornecer o código pronto, mas também explicar por que Encoding.UTF8.GetBytes("hello") não é uma gambiarra, mas sim a única maneira correta. Você aprenderá como obter a representação de bytes de strings em C# sem risco de perder dados, e o que está por trás da mágica da "seleção automática de codificação".
O mito da "string sem codificação"
Muitos iniciantes pensam que uma string em C# é apenas uma sequência de bytes. Isso não é verdade. Internamente, a string no .NET é armazenada como UTF-16 (caracteres de dois bytes). Quando você escreve "Привет", na memória são 12 bytes (6 caracteres × 2 bytes). Mas se você tentar enviar essa string para um arquivo, rede ou banco de dados, quase sempre precisará de outro formato — geralmente UTF-8.
Tentar obter bytes "sem codificação" é como perguntar: "Como traduzir um livro do russo para o inglês sem especificar o idioma?". Impossível. A codificação são as regras de conversão de caracteres em bytes. Sem elas, você terá uma bagunça.
Como NÃO fazer (erro típico)
string text = "Hello, мир!";byte[] wrongBytes = System.Text.Encoding.Default.GetBytes(text); // RUIM!Este código usa a codificação padrão do sistema (geralmente Windows-1251 no Windows em russo). Se você executar este código em outra máquina ou no Linux — obterá bytes diferentes. Sua aplicação se tornará imprevisível.
Abordagem correta: especificação explícita da codificação
A única maneira confiável de obter uma representação de bytes consistente para strings é especificar explicitamente a codificação. A opção mais popular e recomendada é UTF-8:
string text = "Hello, мир!";byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(text);// Resultado: [72, 101, 108, 108, 111, 44, 32, 208, 188, 208, 184, 209, 128, 33]Este código sempre dará o mesmo resultado em qualquer plataforma. Por quê? Porque UTF-8 é um padrão internacional que funciona da mesma forma em todos os lugares.
Outras opções de codificação (quando são necessárias)
- ASCII — apenas latim, descarta todos os caracteres >127.
- Unicode (UTF-16LE) — formato interno do C#, mas ineficiente para armazenamento.
- Windows-1251 — legado, apenas para compatibilidade com sistemas antigos.
Para 99% das tarefas modernas, use Encoding.UTF8.
E se eu quiser "sem especificar"? Existe um hack?
Tecnicamente, você pode usar BitConverter.ToString() ou código unsafe com ponteiros, mas isso fornecerá os bytes brutos do UTF-16 armazenados na memória. Isso é uma má ideia por vários motivos:
- O resultado depende da plataforma (Little-Endian vs Big-Endian).
- Você obterá bytes nulos extras para caracteres latinos (cada caractere ocupará 2 bytes).
- Com a mudança de versão do .NET, a representação interna pode mudar (improvável, mas possível).
Exemplo de código perigoso que não deve ser repetido:
unsafe{ string text = "Hello"; fixed (char* ptr = text) { byte* bytePtr = (byte*)ptr; // Trabalhando com bytes brutos do UTF-16 }}Isso funciona, mas viola o princípio "não mexa nos internos se você não entende as consequências".