CodeGym /Cursos /C# SELF /Discutindo BinaryFormatter...

Discutindo BinaryFormatter

C# SELF
Nível 44 , Lição 1
Disponível

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

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
bf.Serialize(stream, obj)
JsonSerializer.Serialize(...)
XmlSerializer.Serialize(...)
Desserializar de arquivo
bf.Deserialize(stream)
JsonSerializer.Deserialize<T>(...)
XmlSerializer.Deserialize(...)
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.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION