Wee*_*ble 15 c# idisposable temporary-directory
我想提供一个类来管理创建和随后删除临时目录.理想情况下,我希望它可以在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.
}
Run Code Online (Sandbox Code Playgroud)
创建目录没问题.问题是如何编写Dispose方法.当我们尝试删除目录时,我们可能会失败; 例如,因为我们仍然在其中打开一个文件.但是,如果我们允许传播异常,它可能会掩盖使用块内发生的异常.特别是,如果在使用块内发生异常,则可能是导致我们无法删除目录的异常,但如果我们屏蔽它,则我们丢失了解决问题的最有用信息.
看来我们有四种选择:
其中一个选项显然最好吗?有没有更好的方法在用户友好的API中提供此功能?
不要将其视为一个特殊的类实现IDisposable,而是考虑在正常的程序流方面会是什么样的:
Directory dir = Directory.CreateDirectory(path);
try
{
string fileName = Path.Combine(path, "data.txt");
File.WriteAllText(fileName, myData);
UploadFile(fileName);
File.Delete(fileName);
}
finally
{
Directory.Delete(dir);
}
Run Code Online (Sandbox Code Playgroud)
这应该怎么做?这是完全相同的问题.您是否finally按原样保留块的内容,从而可能屏蔽try块中发生的异常,或者您是否将Directory.Delete其包装在自己的try-catch块中,吞下任何异常以防止屏蔽原始块?
我不认为有任何正确的答案 - 事实是,你只能有一个环境异常,所以你必须选择一个.但是,.NET Framework确实设置了一些先例; 一个例子是WCF服务代理(ICommunicationObject).如果您尝试Dispose是故障通道,它抛出一个异常,会掩盖任何异常已经在堆栈中.如果我没弄错的话,TransactionScope也可以这样做.
当然,WCF中的这种行为一直是混乱的源头; 大多数人实际上认为如果不打破它会很烦人.谷歌"WCF处理面具",你会明白我的意思.所以也许我们不应该总是尝试像微软那样做事情.
就个人而言,我的想法Dispose永远不应该掩盖堆栈上已经存在的异常.该using语句实际上是一个finally块,并且大部分时间(总是存在边缘情况),您也不希望在finally块中抛出(而不是捕获)异常.原因只是调试; 要找到问题的根源是非常困难的 - 特别是在生产中你无法单步执行的问题 - 当你甚至无法找到应用程序失败的确切位置时.我之前一直处于这个位置,我可以自信地说它会让你完全彻底疯狂.
我的建议是要么吃Dispose(当然是记录它),或者实际检查你是否因为异常而处于堆栈展开的情况下,如果你知道你的话,只会吃掉后续异常.我会掩饰它们.后者的优点是除非你真的需要,否则不要吃异常; 缺点是你已经在程序中引入了一些非确定性行为.又一个权衡.
大多数人可能会选择前一个选项,只是隐藏finally(或using)中发生的任何异常.
| 归档时间: |
|
| 查看次数: |
2059 次 |
| 最近记录: |