CodeGym /Courses /C# SELF /Discussing BinaryFormatter...

Discussing BinaryFormatter

C# SELF
Level 44 , Lesson 1
Available

1. Introduction

In many old C# tutorials and examples you can find serialization using the BinaryFormatter class. It used to be the standard: convenient, fast, less hassle. An example from the old days looked roughly like this:

// Dangerous old code! Don't do this in new projects!
var bf = new BinaryFormatter();
using (var stream = File.Open("player.dat", FileMode.Create))
{
    bf.Serialize(stream, playerObject);
}

But in modern .NET 9 you won't even be able to compile that code: BinaryFormatter has been removed from the platform.

The path from hero to outcast

Originally BinaryFormatter was designed as a universal mechanism for serializing and deserializing .NET objects, able to save complex object graphs "as is". Over time serious security and compatibility issues surfaced, and now it's a thing of the past — kind of like cassette players in the streaming era.

2. Main reasons to drop BinaryFormatter

A huge security hole

BinaryFormatter can not only serialize data but also restore types from the input stream. If you blindly deserialize untrusted data (for example, coming from the network), an attacker can inject a payload leading to remote code execution (RCE). That's why Microsoft warned for years: "Do not use BinaryFormatter". Starting with .NET 5 it was marked obsolete and dangerous ([Obsolete]), and in .NET 9 — removed.

Dependence on internal class structure

The BinaryFormatter format drags along implementation details of types: fields, boxing, versions. The slightest changes in classes (added/removed field) break compatibility with already saved files. That makes this format unsuitable for long-term storage and cross-version exchange.

Cross-platform difficulties

Data saved by BinaryFormatter is tied to .NET's internal object representation. Reading it on another platform/language or even another .NET version is often impossible.

3. How to find "old code" and what to do?

Signs of BinaryFormatter usage look like this:

using System.Runtime.Serialization.Formatters.Binary; // <-- suspicious!
BinaryFormatter bf = new BinaryFormatter();           // <-- dangerous!
bf.Serialize(...);
bf.Deserialize(...);

In modern .NET versions this code won't compile: tools will give you a "Type or namespace name could not be found" error. In legacy .NET Framework projects — at least strong warnings.

If you find such code, replace BinaryFormatter with modern, safe alternatives.

Which formats and classes to use today?

For JSON

  • System.Text.Json — fast, safe, built into .NET. Official docs
  • Newtonsoft.Json — a popular third-party library for complex cases.

For XML

For binary formats

  • System.Formats.Cbor (CBOR)
  • Protobuf.Net (Protocol Buffers), MessagePack for C#

For specific tasks choose specialized formats and libraries — there is no longer a "one-size-fits-all" binary serializer in the style of BinaryFormatter, and that's a good thing.

4. Rewriting code that used BinaryFormatter

What you must not use BinaryFormatter for

Do not:

  • Store user settings and important data.
  • Transmit data over the network (client ↔ server).
  • Deserialize data from untrusted sources.

Instead:

  • For everyday needs — System.Text.Json.
  • For configuration — JSON, XML, etc.
  • For cross-language exchange — cross-platform compatible formats (JSON, XML, Protobuf, MessagePack).

What code to write now?

JSON serialization (recommended)

using System.Text.Json;
// Your class:
public class Player
{
    public string Name { get; set; } = "";
    public int Health { get; set; }
    public bool IsAlive { get; set; }
}

// Object to serialize
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };

// Convert object to JSON string
string json = JsonSerializer.Serialize(player);

// Save to file — safe!
File.WriteAllText("player.json", json);

// To restore object from file:
string loadedJson = File.ReadAllText("player.json");
Player loadedPlayer = JsonSerializer.Deserialize<Player>(loadedJson)!;

XML serialization (when you need a strict format)

using System.Xml.Serialization;
// Class must have a public parameterless constructor

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);
}

Visual "old vs new" diagram

Task Old way (BinaryFormatter) Modern way
Serialize to file
bf.Serialize(stream, obj)
JsonSerializer.Serialize(...)
XmlSerializer.Serialize(...)
Deserialize from file
bf.Deserialize(stream)
JsonSerializer.Deserialize<T>(...)
XmlSerializer.Deserialize(...)
Security Vulnerable to attacks (RCE) Safe parsers and strict models
Cross-platform No Yes (JSON/XML/Protobuf)
Speed Fast, but dangerous Fast and safe

5. Common mistakes when working with XmlSerializer

Error #1: private properties or fields. XmlSerializer only serializes public properties; even protected will cause an error.

Error #2: missing default constructor. You need a public parameterless constructor, otherwise serialization/deserialization won't work.

Error #3: mismatch between data types. XmlSerializer works poorly with Dictionary, interface and delegate — use wrappers or other formats.

Error #4: circular references. XmlSerializer does not support graphs like A → B → A; for such cases people usually pick JSON with appropriate settings.

2
Task
C# SELF, level 44, lesson 1
Locked
Comparing JSON and XML Serialization for a Simple Object
Comparing JSON and XML Serialization for a Simple Object
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION