从 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();
}
仅捕获可以处理的异常,然后恢复或传递更有意义的信息。 如果您捕获所有异常而不处理其内容,则错误可能会悄悄隐藏。
I一次性和使用
using FileStream stream = File.OpenRead(path);
using var reader = new StreamReader(stream);
string text = reader.ReadToEnd();
当它超出使用范围时,就会调用 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;
如果您完全创建一个新设置并将其替换为现有设置,则即使加载过程中出现故障,现有状态也将保留。 异常处理的目的是使失败前后的状态和资源生命周期比捕获次数更可预测。