基本的なシリアル化

クラスをシリアル化可能にするための最も簡単な方法は、次に示すように Serializable 属性でマークすることです。

[Serializable]
public class MyObject {
  public int n1 = 0;
  public int n2 = 0;
  public String str = null;
}

このクラスのインスタンスをファイルにシリアル化する方法を次のコード例で示します。

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);
stream.Close();

この例では、バイナリ フォーマッタを使用してシリアル化を実行します。必要な作業は、使用するストリームとフォーマッタのインスタンスを作成し、フォーマッタで Serialize メソッドを呼び出すことだけです。ストリームと、シリアル化対象のオブジェクトを、この呼び出しのパラメータとして指定します。この例では明示的には示されていませんが、クラスのすべてのメンバ変数は、変数が private としてマークされている場合でもシリアル化されます。この点で、バイナリ シリアル化は、パブリック フィールドだけをシリアル化する XMLSerializer クラスとは異なります。バイナリ シリアル化からメンバ変数を除外する方法については、「選択的シリアル化」を参照してください。

このオブジェクトを元の状態に復元することも、同じように簡単です。最初に、読み取るストリームとフォーマッタを作成した後、フォーマッタに対してオブジェクトを逆シリアル化するように指示します。この処理を実行するコード例を次に示します。

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

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

上の例で使われている BinaryFormatter は効率的であり、コンパクトなバイト ストリームを生成します。このフォーマッタでシリアル化されたすべてのオブジェクトは、このフォーマッタで逆シリアル化することもできるため、このフォーマッタは .NET Framework で逆シリアル化されるオブジェクトをシリアル化するための理想的なツールです。オブジェクトが逆シリアル化されるときは、コンストラクタは呼び出されません。逆シリアル化に対するこの制約は、パフォーマンス上の理由から設けられています。ただし、この制約はランタイムとオブジェクト作成者との通常のコントラクトの一部に抵触するため、開発者は、オブジェクトをシリアル化可能としてマークするときに生じる副作用について、オブジェクト作成者に明確に知らせる必要があります。

移植性が必要な場合には、その代わりに SoapFormatter を使用します。その場合は、上のコードの BinaryFormatterSoapFormatter に置き換え、上のコードと同様に Serialize および Deserialize を呼び出します。上の例の場合、このフォーマッタは次のような出力を生成します。

<SOAP-ENV:Envelope
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:SOAP- ENC="https://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP- ENV="https://schemas.xmlsoap.org/soap/envelope/"
  SOAP-ENV:encodingStyle=
  "https://schemas.microsoft.com/soap/encoding/clr/1.0"
  "https://schemas.xmlsoap.org/soap/encoding/"
  xmlns:a1="https://schemas.microsoft.com/clr/assem/ToFile">

  <SOAP-ENV:Body>
    <a1:MyObject id="ref-1">
      <n1>1</n1>
      <n2>24</n2>
      <str id="ref-3">Some String</str>
    </a1:MyObject>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Serializable 属性は継承できません。MyObject から新しいクラスを派生させる場合は、その新しいクラスもこの属性でマークする必要があります。マークしないと、このクラスはシリアル化できなくなります。たとえば、次に示すクラスのインスタンスをシリアル化しようとすると、MyStuff 型がシリアル化可能としてマークされていないことを知らせる SerializationException がスローされます。

public class MyStuff : MyObject 
{
  public int n3;
}

Serializable 属性を使用することは便利ですが、上で示したような制限があります。どのような場合にクラスをシリアル化可能なクラスとしてマークする必要があるかについては、「シリアル化のガイドライン」を参照してください。クラスをコンパイルした後にはシリアル化を追加できません。

参照

その他の技術情報

バイナリ シリアル化
リモート オブジェクト
XML シリアル化および SOAP シリアル化