【C#】BinaryFormatterは.NET8以降で削除されるらしい

オブジェクトをバイナリ形式でシリアライズするための BinaryFormatter は昔から存在して、また昔からセキュリティに問題があると指摘され続けていましたがとうとう .NET 8 で今後削除予定としてマークされました。

既に.NET 8環境ではコンパイル時にObsoleteの旨のエラーが発生し、エラーメッセージにアナウンスのリンクが出る親切設計になっていますが、今後型が削除されたら型が見つからないエラーになると思われます。

// 非推奨の旨が表示されるようにマークされた
[Obsolete(
    Obsoletions.BinaryFormatterMessage, 
    DiagnosticId = Obsoletions.BinaryFormatterDiagId, 
    UrlFormat = Obsoletions.SharedUrlFormat
)]
public sealed partial class BinaryFormatter : IFormatter
{
    // ...
}

// 使用箇所でこんな感じのメッセージが出る
// > SYSLIB0051: 'Exception.Exception(SerializationInfo, StreamingContext)' は旧形式です
// > ('This API supports obsolete formatter-based serialization. 
// >  It should not be called or extended by application code.')
// > (https://aka.ms/dotnet-warnings/SYSLIB0051)

Unity の解説で BinaryFormatter を使ってセーブデータ管理を行うという記述を見かけますが、タイトルの通り将来性がないので便利かもしれないですが新規には使用しないほうがいいと思います。

変換結果は一見するとバイナリっぽくになってますが、実際は内容が暗号化されているわけではないので(おおよそシリアライズ元のプロパティ名を復元できるレベルで内容が見えます) JSON で保存するのと安全性の観点では大差ないと思います(それにメンバーが増えたり減ったりしたときのマイグレーションの対応がかなり面倒なのでメリット無いですし…)Unity であれば最も一般的なシリアライズの方法は JsonUtility を使用するのが王道で、暗号化が必要な場合は、JSONに対して暗号化処理を実装するのがベターだと思います。

また、明示的に BinaryFormatter でシリアライズ・デシリアライズしている以外に Exception クラスをスニペットから作成している場合以下のようにコードが生成されていると思いますが、これも警告が出るようになっています。

この対応方法は、以下の通りコメントアウトするだけです。

// [Serializable] ★コメントアウトする
public class MyException : Exception, IErrorInfo
{
    public MyException() { }
    public MyException(string message) : base(message) { }
    public MyException(string message, Exception inner) : base(message, inner) { }
    // protected MyException(
    //     SerializationInfo info, 
    //     StreamingContext context
    // ) : base(info, context) { } // このコンストラクターをコメントアウトする
}

SerializableAttribute が非推奨となり [Serializable] を使用していた箇所はすべてコメントアウトするように推奨されています。

代替手段として、.NET 標準クラスでも System.Text.Json 名前空間の JsonSerializer などのシリアライザーが複数あるので別のものを探して使用するようにしましょう。

既に.NET 7から影響を受けていると思いますが、この対応でデータ保存形式が変更となり既存の処理に大きな影響があるため完全に削除される前にほかの形式にデータをコンバートを計画したほうが良いと思います。

参考

Breaking change: Legacy serialization infrastructure APIs marked obsolete #34893

https://github.com/dotnet/docs/issues/34893