Я хотел бы предоставить класс для управления созданием и последующим удалением временного каталога. В идеале я бы хотел, чтобы он использовался в блоке использования, чтобы гарантировать, что каталог будет удален снова, независимо от того, как мы покинем блок:
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. Когда мы пытаемся удалить каталог, мы можем выйти из строя; например, потому что у нас все еще есть файл, открытый в нем. Однако, если мы разрешаем распространение исключения, оно может маскировать исключение, которое произошло внутри блока использования. В частности, если в блоке использования произошло исключение, это может привести к тому, что мы не сможем удалить каталог, но если мы его замаскируем, мы потеряли самую полезную информацию для устранения проблемы.
Кажется, у нас есть четыре варианта:
- Попытайтесь и проглатывайте любое исключение при попытке удалить каталог. Нам может быть не известно, что мы не можем очистить наш временный каталог.
- Как-то определить, выполняется ли Dispose как часть раскрутки стека, когда было выбрано исключение, и если да, то либо подавляющее исключение IOException, либо генерирует исключение, которое объединяет исключение IOException и любое другое исключение. Возможно, даже не возможно. (Я думал об этом отчасти потому, что это было бы возможно с Python контекстными менеджерами, которые во многом похожи на .NET IDisposable, используемые с С#, используя утверждение.)
- Никогда не подавляйте IOException из-за невозможности удалить каталог. Если в блоке использования было выбрано исключение, мы скроем его, несмотря на то, что есть хороший шанс, что он имеет большую диагностическую ценность, чем наше исключение IOException.
- Отказаться от удаления каталога в методе Dispose. Пользователи класса должны нести ответственность за запрос удаления каталога. Это кажется неудовлетворительным, так как значительная часть мотивации для создания класса заключалась в уменьшении бремени управления этим ресурсом. Может быть, есть еще один способ обеспечить эту функциональность, не сделав ее очень легко испортить?
Является ли один из этих вариантов наилучшим? Есть ли лучший способ предоставить эту функциональность в удобном для пользователя API?