1. Introduction
Dans beaucoup de vieux manuels et d'exemples en C#, on trouve la sérialisation avec la classe BinaryFormatter. À une époque c'était la norme : pratique, rapide, moins de soucis. Un exemple d'antan ressemblait à ceci :
// Vieux code dangereux ! Ne faites pas ça dans de nouveaux projets !
var bf = new BinaryFormatter();
using (var stream = File.Open("player.dat", FileMode.Create))
{
bf.Serialize(stream, playerObject);
}
Mais dans le .NET 9 moderne vous ne pourrez même pas compiler ce code : BinaryFormatter a été retiré de la plateforme.
Du héros au paria
À l'origine BinaryFormatter était pensé comme un mécanisme universel de sérialisation et désérialisation des objets .NET, capable de sauvegarder des graphes d'objets complexes « tels quels ». Avec le temps des problèmes sérieux de sécurité et de compatibilité sont apparus, et maintenant il appartient au passé — comme les magnétophones à cassette à l'ère du streaming.
2. Principales raisons d'abandonner BinaryFormatter
Une énorme faille de sécurité
BinaryFormatter sait non seulement sérialiser des données, mais aussi reconstruire des types depuis le flux d'entrée. Si vous désérialisez sans réflexion des données non vérifiées (par exemple reçues depuis le réseau), un attaquant peut injecter une charge utile provoquant l'exécution de code à distance (RCE). C'est pourquoi Microsoft a pendant des années mis en garde : « N'utilisez pas BinaryFormatter ». Depuis .NET 5 il est marqué comme obsolète et dangereux ([Obsolete]), et dans .NET 9 — supprimé.
Dépendance à la structure interne des classes
Le format BinaryFormatter embarque des détails d'implémentation des types : champs, boxing, versions. Le moindre changement dans les classes (ajout/suppression d'un champ) casse la compatibilité avec les fichiers déjà enregistrés. Ça rend ce format inadapté au stockage long terme et à l'échange inter‑versions.
Difficultés de cross‑platform
Les données sauvegardées avec BinaryFormatter sont liées à la représentation interne des objets .NET. Les lire sur une autre plateforme/langage ou même une autre version de .NET est souvent impossible.
3. Comment détecter le « vieux code » et que faire ?
Les signes d'utilisation de BinaryFormatter ressemblent à ceci :
using System.Runtime.Serialization.Formatters.Binary; // <-- suspect !
BinaryFormatter bf = new BinaryFormatter(); // <-- dangereux !
bf.Serialize(...);
bf.Deserialize(...);
Dans les versions modernes de .NET ce code ne compile pas : les outils renverront une erreur "Type ou nom introuvable". Dans les projets legacy sur .NET Framework — au minimum de fortes alertes.
Si vous tombez sur ce code, remplacez BinaryFormatter par des alternatives modernes et sûres.
Quels formats et classes utiliser aujourd'hui ?
Pour JSON
- System.Text.Json — rapide, sûr, intégré à .NET. Documentation officielle
- Newtonsoft.Json — bibliothèque tierce populaire pour les cas complexes.
Pour XML
- XmlSerializer — sérialisation en XML. Documentation
Pour les formats binaires
- System.Formats.Cbor (CBOR)
- Protobuf.Net (Protocol Buffers), MessagePack for C#
Pour des besoins spécifiques choisissez des formats et bibliothèques spécialisés — il n'existe plus de sérialiseur binaire « universel » à la manière de BinaryFormatter, et c'est tant mieux.
4. Réécrire le code depuis BinaryFormatter
À quoi il ne faut pas utiliser BinaryFormatter
Ne pas :
- Sauvegarder les paramètres utilisateur et les données importantes.
- Transmettre des données sur le réseau (client ↔ serveur).
- Désérialiser des données depuis des sources non vérifiées.
À la place :
- Pour l'usage courant — System.Text.Json.
- Pour les configurations — JSON, XML, etc.
- Pour l'échange interlangage — formats cross‑platform (JSON, XML, Protobuf, MessagePack).
Quel code écrire maintenant ?
Sérialisation en JSON (méthode recommandée)
using System.Text.Json;
// Votre classe :
public class Player
{
public string Name { get; set; } = "";
public int Health { get; set; }
public bool IsAlive { get; set; }
}
// Objet à sérialiser
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
// Convertir l'objet en chaîne JSON
string json = JsonSerializer.Serialize(player);
// Sauvegarder dans un fichier — sécurisé !
File.WriteAllText("player.json", json);
// Pour restaurer l'objet depuis le fichier :
string loadedJson = File.ReadAllText("player.json");
Player loadedPlayer = JsonSerializer.Deserialize<Player>(loadedJson)!;
Sérialisation en XML (si un format strict est nécessaire)
using System.Xml.Serialization;
// La classe doit avoir un constructeur public sans paramètres
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);
}
Schéma visuel « ancien vs nouveau »
| Tâche | Ancienne méthode (BinaryFormatter) | Méthode moderne |
|---|---|---|
| Sérialisation dans un fichier | |
|
| Désérialisation depuis un fichier | |
|
| Sécurité | Vulnérable aux attaques (RCE) | Parsers sûrs et modèles stricts |
| Cross‑platform | Non | Oui (JSON/XML/Protobuf) |
| Vitesse | Rapide, mais dangereux | Rapide et sûr |
5. Erreurs typiques en travaillant avec XmlSerializer
Erreur n°1 : propriétés ou champs privés. XmlSerializer sérialise uniquement les propriétés public ; même protected provoquera une erreur.
Erreur n°2 : absence d'un constructeur par défaut. Il faut un constructeur public sans paramètres, sinon la sérialisation/désérialisation ne fonctionnera pas.
Erreur n°3 : incompatibilité entre les types de données. XmlSerializer gère mal Dictionary, interface et delegate — utilisez des wrappers ou d'autres formats.
Erreur n°4 : références cycliques (circular reference). XmlSerializer ne supporte pas les graphes du type A → B → A ; pour ces cas on préfère souvent le JSON avec des réglages appropriés.
GO TO FULL VERSION