Share via

Basic serialization


Binary serialization can be dangerous. For more information, see BinaryFormatter security guide.

The easiest way to make a class binary serializable is to mark it with the SerializableAttribute as follows.

public class MyObject {
  public int n1 = 0;
  public int n2 = 0;
  public String str = null;

The following code example shows how an instance of this class can be serialized to a file.

MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);

This example uses a binary formatter to do the serialization. All you need to do is create an instance of the stream and the formatter you intend to use, and then call the Serialize method on the formatter. The stream and the object to serialize are provided as parameters to this call. Although it is not explicitly demonstrated in this example, all member variables of a class will be serialized—even variables marked as private. In this aspect, binary serialization differs from the XmlSerializer class, which only serializes public fields. For information on excluding member variables from binary serialization, see Selective Serialization.

Restoring the object back to its former state is just as easy. First, create a stream for reading and a Formatter, and then instruct the formatter to deserialize the object. The code example below shows how this is done.

IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(stream);

// Here's the proof.
Console.WriteLine("n1: {0}", obj.n1);
Console.WriteLine("n2: {0}", obj.n2);
Console.WriteLine("str: {0}", obj.str);

The BinaryFormatter used in the preceding code is efficient and produces a compact byte stream. All objects serialized with this formatter can also be deserialized with it, which makes it an ideal tool for serializing objects that will be deserialized on .NET. It's important to note that constructors are not called when an object is deserialized. This constraint is placed on deserialization for performance reasons. However, this violates some of the usual contracts the runtime makes with the object writer, and developers should ensure that they understand the ramifications when marking an object as serializable.

If portability is a requirement, use the SoapFormatter instead. Simply replace the BinaryFormatter in the previous code with SoapFormatter, and call Serialize and Deserialize as before. This formatter produces the following output for the example used previously.


    <a1:MyObject id="ref-1">
      <str id="ref-3">Some String</str>

It's important to note that the Serializable attribute cannot be inherited. If you derive a new class from MyObject, the new class must be marked with the attribute as well, or it cannot be serialized. For example, when you attempt to serialize an instance of the following class, you'll get a SerializationException informing you that the MyStuff type is not marked as serializable.

public class MyStuff : MyObject
  public int n3;

Using the Serializable attribute is convenient, but it has limitations as previously demonstrated. Refer to the Serialization guidelines for information about when you should mark a class for binary serialization. Binary serialization cannot be added to a class after it's been compiled.