C# 基礎からマスターまで — 第7回
例外とIDisposableでリソース寿命を管理する
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
失敗する可能性のあるコードは、失敗した後の状態まで設計する必要があります。 例外をキャッチするだけでなく、ファイルや接続などのリソースがどのパスでも整理されるかどうかが重要です。
予想可能な失敗
bool TrySpendGold(int amount)
{
if (amount < 0 || Gold < amount)
{
return false;
}
Gold -= amount;
return true;
}
ゴールド不足のように頻繁に起こる結果は、boolや別々の結果タイプで表現できる。 例外は、ファイルの破損や契約違反など、現在のフローで正常に処理するのが難しい障害に使用されます。
例外処理
try
{
string json = File.ReadAllText(path);
settings = JsonSerializer.Deserialize<Settings>(json)
?? throw new InvalidDataException("Settings are empty");
}
catch (IOException error)
{
logger.Log(error.Message);
settings = Settings.CreateDefault();
}
処理可能な例外だけをキャッチして回復するか、より意味のある情報と共に上に渡します。 内容を処理せずにすべての例外を捕まえればバグが静かに隠れる。
IDisposableとusing
using FileStream stream = File.OpenRead(path);
using var reader = new StreamReader(stream);
string text = reader.ReadToEnd();
usingの範囲外の場合、Disposeが呼び出されます。 通常の戻りだけでなく、例外が発生したパスでもファイルハンドルがクリーンアップされます。
GCは管理オブジェクトのメモリを回収しますが、ファイル、ソケット、ネイティブバッファをすぐに閉じるという約束ではありません。 これらのリソースを所有するタイプはIDisposable契約を提供しなければなりません。
状態を後で交換する
Settings LoadSettings(string path)
{
string json = File.ReadAllText(path);
return JsonSerializer.Deserialize<Settings>(json)
?? throw new InvalidDataException("Invalid settings");
}
Settings loaded = LoadSettings(path);
currentSettings = loaded;
新しい設定を完全に作成した後、既存の設定と交換すると、ロード中に失敗しても既存の状態が残る。 例外処理は、キャッチの数よりも失敗前後の状態とリソース寿命を予測可能にすることである。