File.WriteAllでセーブデータの書き込みを行っていると、書き込み中にクラッシュした際にファイルが破損することがある

起こったこと

System.IO.File.WriteAllBytesAsync("SaveData", data); のようなコードでセーブデータの書き込みを行っていました。
しかし、あるときちょうど書き込み中にクラッシュが発生し、SaveDataがサイズは正しいのにすべて0で埋まった状態になってしまいました。
(0埋めになるか0byteになるか、ここはなんでも起こりうる。)

原因

File.WriteAllText / File.WriteAllBytesは既存ファイルに対して上書きする場合、FileMode.Create相当でファイルを開くため ファイルが存在する場合は内容を0byteに切り詰めてから書き込む(Truncate)挙動をするそうです。
ここでFileMode.Createで開いているかららしい。)
.NETの内部実装やwin32 apiに疎いので細かい解説は詳しい方にお任せします。
適当なこと書いてるかもしれないのでツッコミください。

解決策

File.Replaceはatomicな操作らしいので、一旦一時ファイルにデータを書き出してからこれで置き換えてやります。 (参考:【C#】File.Replaceはatomicに更新を行うのか?

こうすることで、なるべく安全にファイルを書き換えることができます。
File.Replaceが本当にatomicなら問題ないはずですが、読み込み時も元のファイルを読んでみて失敗したら.bakを読むのが良さそうです。