1. Introdução
Em muitos livros e exemplos antigos sobre C# você pode encontrar serialização usando a classe BinaryFormatter. Um dia isso foi padrão: prático, rápido, menos preocupações. Um exemplo dos velhos tempos parecia mais ou menos assim:
// Código antigo perigoso! Não faça isso em projetos novos!
var bf = new BinaryFormatter();
using (var stream = File.Open("player.dat", FileMode.Create))
{
bf.Serialize(stream, playerObject);
}
Mas no .NET 9 moderno você já não vai nem conseguir compilar esse código: BinaryFormatter foi removido da plataforma.
Caminho de herói a pária
Inicialmente BinaryFormatter foi pensado como um mecanismo universal de serialização e desserialização de objetos .NET, capaz de salvar grafos de objetos complexos "como estão". Com o tempo surgiram problemas sérios de segurança e compatibilidade, e agora ele ficou no passado — tipo fitas cassete na era do streaming.
2. Principais razões para abandonar o BinaryFormatter
Buraco gigante de segurança
BinaryFormatter não só serializa dados, mas também restaura tipos a partir do fluxo de entrada. Se você desserializar sem checar dados não confiáveis (por exemplo, recebidos da rede), um atacante pode injetar payload que leva à execução remota de código (RCE). Por isso a Microsoft por anos avisou: "Não use BinaryFormatter". A partir do .NET 5 ele foi marcado como obsoleto e perigoso ([Obsolete]), e no .NET 9 — removido.
Dependência da estrutura interna das classes
O formato do BinaryFormatter carrega detalhes de implementação dos tipos: campos, boxing, versões. Pequenas mudanças nas classes (adicionar/remover campo) quebram compatibilidade com arquivos já salvos. Isso torna o formato impróprio para armazenamento a longo prazo e troca entre versões.
Dificuldades de cross-platform
Dados salvos com BinaryFormatter estão amarrados à representação interna de objetos .NET. Ler esses dados em outra plataforma/linguagem ou mesmo em outra versão do .NET frequentemente é impossível.
3. Como encontrar "código antigo" e o que fazer?
Sinais de uso de BinaryFormatter parecem com isto:
using System.Runtime.Serialization.Formatters.Binary; // <-- suspeito!
BinaryFormatter bf = new BinaryFormatter(); // <-- perigoso!
bf.Serialize(...);
bf.Deserialize(...);
Em versões modernas do .NET esse código não compila: as ferramentas vão dar erro "Tipo ou nome não encontrado". Em projetos legacy no .NET Framework — pelo menos avisos severos.
Se você encontrar esse código, troque BinaryFormatter por alternativas modernas e seguras.
Quais formatos e classes usar hoje?
Para JSON
- System.Text.Json — rápido, seguro, embutido no .NET. Documentação oficial
- Newtonsoft.Json — biblioteca externa popular para casos complexos.
Para XML
- XmlSerializer — serialização em XML. Documentação
Para formatos binários
- System.Formats.Cbor (CBOR)
- Protobuf.Net (Protocol Buffers), MessagePack for C#
Para tarefas específicas escolha formatos e bibliotecas especializadas — não existe mais um "serializador binário universal" no estilo do BinaryFormatter, e isso é bom.
4. Reescrevendo código que usava BinaryFormatter
Para que não usar BinaryFormatter
Não usar para:
- Salvar configurações de usuário e dados sensíveis.
- Transferir dados pela rede (cliente ↔ servidor).
- Desserializar dados de fontes não confiáveis.
Ao invés disso:
- Para necessidades do dia a dia — System.Text.Json.
- Para configurações — JSON, XML etc.
- Para troca entre linguagens — formatos cross-platform (JSON, XML, Protobuf, MessagePack).
Que código escrever agora?
Serialização para JSON (método recomendado)
using System.Text.Json;
// Sua classe:
public class Player
{
public string Name { get; set; } = "";
public int Health { get; set; }
public bool IsAlive { get; set; }
}
// Objeto para serializar
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
// Convertemos o objeto em string JSON
string json = JsonSerializer.Serialize(player);
// Salvamos em arquivo — seguro!
File.WriteAllText("player.json", json);
// Para recuperar o objeto do arquivo:
string loadedJson = File.ReadAllText("player.json");
Player loadedPlayer = JsonSerializer.Deserialize<Player>(loadedJson)!;
Serialização para XML (se você precisa de um formato estrito)
using System.Xml.Serialization;
// A classe deve ter um construtor público sem parâmetros
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
var serializer = new XmlSerializer(typeof(Player));
using (var fs = File.Create("player.xml"))
{
serializer.Serialize(fs, player);
}
Esquema visual "antigo vs novo"
| Tarefa | Método antigo (BinaryFormatter) | Método moderno |
|---|---|---|
| Serializar para arquivo | |
|
| Desserializar de arquivo | |
|
| Segurança | Vulnerável a ataques (RCE) | Parsers seguros e modelos estritos |
| Cross-platform | Não | Sim (JSON/XML/Protobuf) |
| Velocidade | Rápido, mas perigoso | Rápido e seguro |
5. Erros típicos ao trabalhar com XmlSerializer
Erro Nº1: propriedades ou campos privados. XmlSerializer serializa apenas propriedades public; até mesmo protected pode causar erro.
Erro Nº2: ausência de construtor padrão. É preciso um construtor público sem parâmetros, caso contrário serialização/desserialização não vai funcionar.
Erro Nº3: incompatibilidade entre tipos de dados. XmlSerializer tem problemas com Dictionary, interface e delegate — use wrappers ou outros formatos.
Erro Nº4: referências cíclicas (circular reference). XmlSerializer não suporta grafos do tipo A → B → A; para esses casos costuma-se usar JSON com as configurações adequadas.
GO TO FULL VERSION