Я прочитал много блогов/статей/глав книги о правильной обработке исключений, и эта тема для меня пока не ясна. Я попытаюсь проиллюстрировать свой вопрос следующим примером.
Рассмотрим метод класса, который имеет следующие требования:
- получить список путей файла как параметр
- прочитать содержимое файла для каждого файла или пропустить, если есть какие-либо проблемы с попыткой сделать это
- возвращает список объектов, представляющих содержимое файла
Итак, спецификации просты и вот как я могу начать кодирование:
public class FileContent
{
public string FilePath { get; set; }
public byte[] Content { get; set; }
public FileContent(string filePath, byte[] content)
{
this.FilePath = filePath;
this.Content = content;
}
}
static List<FileContent> GetFileContents(List<string> paths)
{
var resultList = new List<FileContent>();
foreach (var path in paths)
{
// open file pointed by "path"
// read file to FileContent object
// add FileContent to resultList
// close file
}
return resultList;
}
Теперь обратите внимание, что 2. из спецификаций говорит, что метод должен "пропускать любой файл, содержимое которого не может быть прочитано по какой-либо причине". Поэтому может возникнуть много разных причин (например, файл не существует, доступ к файлам запрещен из-за отсутствия разрешений безопасности, блокировка файла и использование другим приложением и т.д.), Но дело в том, что я должен неважно, в чем причина, я просто хочу прочитать содержимое файла, если это возможно, или пропустить файл, если нет. Мне все равно, что ошибка...
Итак, как правильно реализовать этот метод?
ОК, первое правило правильной обработки исключений никогда не будет ловить общее исключение. Поэтому этот код не подходит:
static List<FileContent> GetFileContents(List<string> paths)
{
var resultList = new List<FileContent>();
foreach (var path in paths)
{
try
{
using (FileStream stream = File.Open(path, FileMode.Open))
using (BinaryReader reader = new BinaryReader(stream))
{
int fileLength = (int)stream.Length;
byte[] buffer = new byte[fileLength];
reader.Read(buffer, 0, fileLength);
resultList.Add(new FileContent(path, buffer));
}
}
catch (Exception ex)
{
// this file can't be read, do nothing... just skip the file
}
}
return resultList;
}
Следующее правило правильной команды исключений говорит: улавливайте только определенные исключения, которые вы можете обрабатывать. Ну, я не забочусь о том, чтобы обрабатывать какие-либо исключения, которые могут быть выброшены, я просто хочу проверить, можно ли читать файл или нет. Как я могу сделать это правильно, наилучшим образом?