我想提供一个类来管理临时目录的创建和后续删除。理想情况下,我希望它可以在 using 块中使用,以确保目录被再次删除,无论我们如何离开块:
static void DoSomethingThatNeedsATemporaryDirectory()
{
using (var tempDir = new TemporaryDirectory())
{
// Use the directory here...
File.WriteAllText(Path.Combine(tempDir.Path, "example.txt"), "foo\nbar\nbaz\n");
// ...
if (SomeCondition)
{
return;
}
if (SomethingIsWrong)
{
throw new Exception("This is an example of something going wrong.");
}
}
// Regardless of whether we leave the using block via the return,
// by throwing and exception or just normally dropping out the end,
// the directory gets deleted by TemporaryDirectory.Dispose.
}
创建目录没有问题。问题是如何编写 Dispose 方法。当我们尝试删除目录时,我们可能会失败;例如,因为我们仍然在其中打开了一个文件。但是,如果我们允许异常传播,它可能会掩盖在 using 块内发生的异常。特别是,如果 using 块内部发生异常,可能是导致我们无法删除目录的异常,但如果我们屏蔽它,我们就丢失了修复问题的最有用信息。
看来我们有四个选择:
- 尝试删除目录时捕获并吞下任何异常。我们可能没有意识到我们未能清理我们的临时目录。
- 以某种方式检测 Dispose 是否在引发异常时作为堆栈展开的一部分运行,如果是,则抑制 IOException 或引发合并 IOException 和引发的任何其他异常的异常。甚至可能都不可能。(我之所以想到这一点,部分原因是它可以使用 Python 的上下文管理器,它在很多方面类似于与 C# 的 using 语句一起使用的 .NET 的 IDisposable。)
- 永远不要抑制 IOException 无法删除目录。如果在 using 块中抛出异常,我们将隐藏它,尽管它很有可能比我们的 IOException 具有更多的诊断价值。
- 放弃在 Dispose 方法中删除目录。该类的用户必须继续负责请求删除目录。这似乎不能令人满意,因为创建类的很大一部分动机是减轻管理此资源的负担。也许还有另一种方法可以提供此功能而不会很容易搞砸?
这些选项之一显然是最好的吗?有没有更好的方法在用户友好的 API 中提供此功能?