Serializable属性の基本と注意点

システム開発

C#でオブジェクトをシリアライズ(直列化)する方法を知っていますか?[Serializable]属性を使うことで、オブジェクトの状態をファイルやデータベース、ネットワーク通信などに保存・復元できるようになります。本記事では、Serializable属性の基本的な使い方から、実際のコード例、注意点までを詳しく解説します。C#でデータの保存や転送を扱う際に必須の知識なので、ぜひ最後までご覧ください。


Serializable属性とは?

[Serializable]属性は、C#においてオブジェクトをシリアライズ(直列化)可能にするためのキーワードです。クラスや構造体にこの属性を付けることで、その型のインスタンスをバイナリ形式や他のフォーマットに変換して保存・転送することができます。

✅ シリアライズの目的:

  • 永続化:オブジェクトの状態をファイルやデータベースに保存。
  • 通信:ネットワーク経由でデータを送受信する際のデータ変換。
  • コピー処理:ディープコピーを実現するための手段として利用。

✅ どう使うのか?

クラスに[Serializable]を付けるだけで、そのクラスのインスタンスはバイナリ形式のシリアライズ対象となります。

[Serializable]
public class User
{
    public string Name;
    public int Age;
}

✅ 適用範囲についての注意点:

  • [Serializable]は主にバイナリ形式のシリアライズに必要です。
  • JSONやXMLのシリアライズにはこの属性は不要で、別のアプローチ(属性)を使用します。
  • インターフェースや抽象クラスには直接付けることはできませんが、それを実装・継承する具象クラスに付ければOKです。

✅ 利用される主な場面:

  • ファイルに設定情報や状態を保存するアプリ
  • ソケット通信やWeb APIでデータをやり取りするアプリケーション
  • オブジェクトの状態を一時的に保持して、あとで復元するケース

SErializableを使うとなにがうれしいのか?

[Serializable]属性を使うことで、オブジェクトの状態を簡単に保存・復元できるようになります。これにより、C#アプリケーションの開発がぐっと楽になります。

✅ こんなときに便利!

  • 設定ファイルとして保存

    ユーザーが入力した設定情報などを、アプリ終了時に保存 → 起動時に復元、というような用途で活躍します。

  • セッション情報の保持

    Webアプリケーションでは、ユーザーの一時的な状態(ログイン情報やカートの中身など)をセッションに保存する際に便利です。

  • ディープコピーの実装

    シリアライズ → デシリアライズの流れを使うことで、オブジェクトをまるごとコピーすることができます。

  • ネットワーク通信でのデータ送受信

    オブジェクトをシリアライズしてJSONやバイナリに変換し、APIやTCP通信で送ることが可能になります。

✅ ASP.NET MVCの例(セッションへの保存)

[Serializable]
public class Cart
{
    public List<string> Items { get; set; }
}

// セッションに保存
var cart = new Cart { Items = new List<string> { "Apple", "Banana" } };
Session["Cart"] = cart;

// セッションから取得
var savedCart = (Cart)Session["Cart"];

✅ ポイント

  • クラスに[Serializable]を付けるだけで、ファイル保存やセッション保存など、様々な用途に利用可能になります。
  • シリアライズ処理を共通化することで、メンテナンスもしやすくなります。

このように、シリアライズは一見地味ですが、アプリの信頼性や利便性を高めるための重要な仕組みの一つです。次の章では、具体的な使い方とコード例を紹介していきます。


Serializableの基本的な使い方

Serializable属性は非常にシンプルに使える機能ですが、いくつかのポイントを押さえておくことで、より安全で柔軟に利用できます。

✅ 属性の適用方法

クラスまたは構造体の宣言に[Serializable]を付けることで、その型はバイナリシリアライズの対象になります。

[Serializable]
public class User
{
    public string Name;
    public int Age;
}

✅ バイナリシリアライゼーションの例

.NET Frameworkでのバイナリ形式のシリアライズでは、BinaryFormatterを使用します。ただし、これはセキュリティの観点から非推奨になっているため、後ほど紹介する代替手段の使用を推奨します。

// 非推奨:BinaryFormatterの例
User user = new User { Name = "Alice", Age = 30 };
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new FileStream("user.dat", FileMode.Create))
{
    formatter.Serialize(stream, user);
}

✅ JSONシリアライゼーションの例

System.Text.Jsonを使えば、Serializable属性がなくてもJSON形式でシリアライズできます。ですが、クラスに属性を付けておくことで、バイナリ形式との互換性も確保できます。

// JSONシリアライズ
var user = new User { Name = "Alice", Age = 30 };
string json = JsonSerializer.Serialize(user);
File.WriteAllText("user.json", json);

✅ NonSerializedを使ったフィールドの除外

バイナリシリアライズ時に、特定のフィールドだけを除外したい場合は、[NonSerialized]属性を使います。これはセキュリティやプライバシー対策としても有効です。

[Serializable]
public class Account
{
    public string Username;

    [NonSerialized]
    public string Password; // 保存したくない機密情報
}

注意点:

  • [NonSerialized]はバイナリシリアライズにのみ有効です。
  • JSONの場合は代わりに [JsonIgnore] を使用します。

Serializableを使う際の注意点

BinaryFormatterは非推奨

.NET 5以降、BinaryFormatterはセキュリティ上のリスクから非推奨となっています。

代替手段:

  • System.Text.Json:軽量で高速なJSONシリアライザー。
  • XmlSerializer:XML形式でのシリアライズに適しています。
  • MessagePack:効率的なバイナリシリアライザー。

推奨されるシリアライズ方法のコード例:

System.Text.Jsonを使用したシリアライズの例

using System.Text.Json;

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

var user = new User { Name = "Alice", Age = 30 };
string jsonString = JsonSerializer.Serialize(user);

Serializable属性の適用範囲

[Serializable]属性は、主にバイナリシリアライズで使用されます。

ポイント:

  • バイナリシリアライズ[Serializable]属性が必要です。
  • JSONやXMLのシリアライズ[Serializable]属性は不要で、各シリアライザー固有の属性を使用します。

シリアライズ対象外のフィールド

機密情報はシリアライズしない

  • バイナリシリアライズ[NonSerialized]属性を使用してフィールドを除外します。
    [Serializable]
    public class User
    {
        public string Name;
        [NonSerialized]
        public string Password;
    }
    
  • JSONシリアライズ[JsonIgnore]属性を使用します。
    public class User
    {
        public string Name { get; set; }
        [JsonIgnore]
        public string Password { get; set; }
    }
    
  • XMLシリアライズ[XmlIgnore]属性を使用します。
    public class User
    {
        public string Name { get; set; }
        [XmlIgnore]
        public string Password { get; set; }
    }
    

注意点:

  • [NonSerialized]:バイナリシリアライズでのみ有効です。
  • [JsonIgnore]:JSONシリアライズで使用します。
  • [XmlIgnore]:XMLシリアライズで使用します。

バージョン互換性の考慮

フィールドの追加・削除によるデシリアライズエラーのリスク

対策:

  • JSONやXMLのシリアライズを利用:これらはフィールドの変更に対して柔軟性があります。
  • 新規フィールドのデフォルト値設定:新しいフィールドにはデフォルト値を設定しておくと安全です。
  • デシリアライズ時のエラーハンドリング:例外処理を適切に実装して、エラーに対応します。

静的フィールド(static)はシリアライズされない

ポイント:

  • staticフィールドはシリアライズの対象外です。
  • シリアライズ後に手動で復元が必要です。

具体的なコード例:

[Serializable]
public class User
{
    public string Name;
    [NonSerialized]
    public static int InstanceCount;
}

注意点:

  • staticフィールドはクラス全体で共有されるため、シリアライズの対象外となります。
  • 必要に応じて、シリアライズ後に手動で値を設定する必要があります。

まとめ

Serializable属性を使ったシリアライズには多くの利点がありますが、いくつかの重要な注意点も存在します。以下に、よくある課題とその解決策を表にまとめました。

注意点 解決策
BinaryFormatterは非推奨 System.Text.JsonXmlSerializerなど、安全なシリアライザーを使用する
Serializableはバイナリ専用 JSONやXMLシリアライズでは属性なしでも利用可能。専用の属性(JsonIgnoreなど)を使う
機密情報の除外 バイナリ:[NonSerialized]JSON:[JsonIgnore]XML:[XmlIgnore]を使う
バージョン互換性 新規フィールドにはデフォルト値を設定JSON/XMLを使うことで柔軟性を確保
staticフィールドの非対応 シリアライズ後に手動で復元処理を行う必要あり

✅ シリアライズの基本を理解し、適切に設計することで、データの保存・転送・再利用がスムーズに行えるようになります。開発の現場でもよく使われる技術なので、ぜひ今回の内容を参考に活用してみてください。

コメント

タイトルとURLをコピーしました