Я знаю, что вы не должны писать код, который кэширует все типы исключений, подобные этому.
try
{
//code that can throw an exception
}
catch
{
//what? I don't see no
}
Вместо этого вы должны сделать что-то более похожее на приведенный ниже код, разрешив любое другое исключение, которое вы не ожидали всплыть.
try
{
//code that can throw an exception
}
catch(TypeAException)
{
//TypeA specific code
}
catch(TypeBException)
{
//TypeB specific code
}
Но нормально ли перехватывать все типы исключений, если вы заключаете их в другое исключение?
Рассмотрим этот Save()
метод ниже, который я пишу как часть класса Catalog. Что-то не так со мной, перехватывая все типы исключений и возвращая единственное пользовательское исключение CatalogIOException с исходным исключением как внутреннее исключение?
По сути, я не хочу, чтобы какой-либо вызывающий код знал что-либо обо всех конкретных исключениях, которые могут быть выброшены внутри метода Save (). Им нужно только знать, пытались ли они сохранить каталог только для чтения (CatalogReadOnlyException), не удалось сериализовать каталог (CatalogSerializationException) или возникла какая-то проблема с записью в файл (CatalogIOException).
Это хороший или плохой способ обработки исключений?
/// <summary>
/// Saves the catalog
/// </summary>
/// <exception cref="CatalogReadOnlyException"></exception>
/// <exception cref="CatalogIOException"></exception>
/// <exception cref="CatalogSerializingExeption"></exception>
public void Save()
{
if (!this.ReadOnly)
{
try
{
System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
this._catfileStream.SetLength(0); //clears the file stream
serializer.Serialize(this._catfileStream, this);
}
catch (InvalidOperationException exp)
{
throw new CatalogSerializationException("There was a problem serializing the catalog", exp);
}
catch (Exception exp)
{
throw new CatalogIOException("There was a problem accessing the catalog file", exp);
}
}
else
{
throw new CatalogReadOnlyException();
}
}
Обновление 1
Спасибо за все ответы до сих пор. Похоже, консенсус в том, что я не должен этого делать, и я должен ловить исключения, только если я действительно имею к ним какое-то отношение. В случае этого метода Save () действительно нет никакого исключения, которое я могу обработать в самом методе Save (). В основном я просто хочу уведомить пользователей, почему они не смогли сохранить.
Я думаю, что моя настоящая проблема в том, что я использую исключения как способ уведомления пользователя о проблемах, и я позволяю этому сообщать, как я создаю и обрабатываю исключения слишком много. Поэтому вместо этого должно звучать так, что было бы лучше не перехватывать какие-либо исключения и позволить слою пользовательского интерфейса выяснить, как уведомить пользователя, или произошел сбой. Это правильно? Рассмотрим обработчик событий Save Menu ниже.
private void saveCatalogToolStripMenuItem_Click(object sender, EventArgs e)
{
//Check if the catalog is read only
if (this.Catalog.ReadOnly)
{
MessageBox.Show("The currently opened catalog is readonly and can not be saved");
return;
}
//attempts to save
try
{
//Save method doesn't catch anything it can't deal with directly
this.Catalog.Save();
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show("The catalog file could not be found");
}
catch (InvalidOperationException exp)
{
MessageBox.Show("There was a problem serializing the catalog for saving: " + exp.Message);
}
catch (System.IO.IOException exp)
{
MessageBox.Show("There was a problem accessing the catalog file: " + exp.Message);
}
catch (Exception exp)
{
MessageBox.Show("There was a problem saving the catalog:" + exp.Message);
}
}
Обновление 2
Еще одна вещь. Изменился бы ответ вообще, если бы метод Save () был частью открытого API против внутреннего кода? Например, если бы он был частью общедоступного API, мне пришлось бы выяснить и задокументировать все возможные исключения, которые может выдавать Save (). Это было бы намного проще, если бы знал, что Save () может выдать только одно из моих трех пользовательских исключений.
Кроме того, если Save () является частью общедоступного API, не будет ли проблема безопасности? Возможно, я бы хотел, чтобы потребитель API знал, что сохранение не было успешным, но я не хочу раскрывать что-либо о том, как работает Save (), позволяя им получить исключения, которые могли быть сгенерированы.