Я знаю, что вы не должны писать код, который кэширует все типы исключений, подобные этому.
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(), позволяя им получить исключения, которые могут быть сгенерированы.