Это в порядке для ловли всех типов исключительной ситуации, если Вы повторно бросаете их, перенес другое исключение?

Я знаю, что Вы не, предполагают для написания кода что кэши все типы исключительной ситуации как это.

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() метод ниже я пишу как часть класса Каталога. Есть ли что-то не так со мной ловящий все типы исключительной ситуации и возвращающий единственный пользовательский CatalogIOException за исходным исключением как внутреннее исключение?

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

Спасибо за все ответы до сих пор. Это кажется, что согласие, я не должен делать этого, и я должен только ловить исключения, если я на самом деле имею некоторое отношение к ним. В случае этого Сохранения () метод там действительно не является никаким исключением, которое может быть выдано, что я хочу обработать в Сохранении () сам метод. Главным образом я просто хочу уведомить пользователя, почему они не смогли сохранить.

Я думаю, что моя настоящая проблема, я использую исключения в качестве способа уведомить пользователя относительно проблем, и я позволяю этому сообщить, как я создаю и обрабатываю исключения немного слишком много. Так вместо этого должен это казаться, что было бы лучше не поймать любые исключения и позволить уровню UI выяснить, как уведомить пользователя, и или катастрофический отказ. Это корректно? Рассмотрите обработчик событий Меню Сохранения ниже.

    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

Еще одна вещь. Ответ изменился бы вообще, если бы Сохранение () метод было частью общедоступного API по сравнению с внутренним кодом? Например, если бы это была часть общедоступного API затем, то я должен был бы выяснить и документ все возможные исключения, которые Сохраняют (), может бросить. Это было бы намного легче, если бы знал, что Сохраняют (), то мог только возможно выдать одно из моих трех пользовательских исключений.

Также, если бы Сохраняют (), была часть общедоступного API, безопасность также не была бы беспокойством? Возможно, я хотел бы позволить потребителю API знать, что сохранение не было успешно, но я не хочу, выставляют что-либо о том, как Сохраняют () работы, позволяя им достигнуть исключения, которые, возможно, были сгенерированы.

15
задан John Saunders 26 February 2010 в 00:19
поделиться

11 ответов

Использование общего улова и перекройки в качестве исключения нового типа на самом деле не решает вашу проблему и не дает вам ничего.

Что вам действительно нужно сделать, так это уловить исключения, с которыми вы можете справиться, а затем справиться с ними (на соответствующем уровне - именно здесь может быть полезно перевооружение). Все остальные исключения либо должны регистрироваться в журнале, чтобы можно было отлаживать причины их возникновения, либо не должны происходить в первую очередь (например, убедитесь, что вы проверяете ввод данных пользователем и т.д.). Если вы поймаете все исключения, вы никогда не узнаете, почему вы получаете исключения, которые вы получаете, и, таким образом, не можете исправить их.

Обновленный ответ

В ответ на обновление вашего вопроса (особенно в том, как вы хотите обработать случай сохранения), мой вопрос к вам будет - почему вы используете исключения в качестве средства определения пути, по которому идет ваша программа? Например, возьмем "FileNotFoundException". Очевидно, что это может случиться иногда. Но, вместо того, чтобы допустить возникновение проблемы и уведомить пользователя о ней, перед сохранением (или чем угодно) с файлом, почему бы сначала не проверить, что файл можно найти. Вы все еще получаете тот же эффект, но не используете исключения для управления потоком программ.

Надеюсь, все это имеет смысл. Дайте мне знать, если у вас есть какие-либо дополнительные вопросы.

-121--2406205-

Да, это так.

:]

-121--3995572-

При повторной передаче исходного исключения в качестве внутреннего исключения теряется исходная трассировка стека, которая является важной отладочной информацией.

Я иногда делаю то, что вы предлагаете, но я всегда регистрирую исходное исключение сначала, чтобы сохранить трассировку стека.

5
ответ дан 1 December 2019 в 03:52
поделиться

Я не вижу проблем в том, что вы делаете. Причина включения исключений в пользовательские типы исключений - создать абстракцию между уровнями кода, чтобы преобразовать ошибки более низкого уровня в контекст более высокого уровня. Это избавляет вызывающий код от необходимости слишком много знать детали реализации того, что делает Save .

Ваше обновление №1 является примером того, как вызывающий код должен слишком много знать о деталях реализации Save () . Отвечая на ваше второе обновление, я согласен на 100%

PS
Я не говорю делать это в каждом сценарии, где вы сталкиваетесь с исключениями. Только тогда, когда выгода превышает стоимость (обычно на границах модуля).

Примеры сценариев, когда это особенно полезно: вы обертываете стороннюю библиотеку, вы еще не знаете всех основных исключений, которые могут возникнуть, у вас нет исходного кода или какой-либо документации и т. Д. .

Кроме того, он обертывает базовое исключение, и никакая информация не теряется . Исключение по-прежнему можно регистрировать соответствующим образом (хотя вам потребуется рекурсия через InnerException s).

3
ответ дан 1 December 2019 в 03:52
поделиться

Из Википедии Не повторять себя (DRY) или Дублирование - это зло (DIE)

В некоторых контекстах усилия, необходимые для применения философии DRY, могут быть больше, чем усилия по поддержанию отдельных копий данных. В некоторых других контекстах дублированная информация является неизменной или поддерживается под контролем, достаточно жестким, чтобы сделать DRY не требуемым.

Вероятно, нет ответа или техники для предотвращения подобных проблем.

-121--880933-

О Да. + 1

-121--3995573-

Я не думаю, что это хорошая идея.

Вы должны добавить только свой тип исключения, если у вас есть что добавить.

И кроме того, вы должны только ловить исключения, которые вы ожидаете, и что вы в состоянии справиться - все остальные исключения должны быть разрешены, чтобы пузырь вверх.

Как разработчик я должен сказать, я злюсь, если вы пытаетесь «скрыть» исключения от меня, проглотив или завернув их.

1
ответ дан 1 December 2019 в 03:52
поделиться

Выполнение общего перехвата и повторного отбрасывания как нового типа исключения на самом деле не решает вашу проблему и ничего вам не дает.

Что вам действительно нужно сделать, так это поймать исключения, которые вы можете обработать, и затем обработать их (на соответствующем уровне - вот где повторное бросание может быть полезным). Все остальные исключения либо должны быть зарегистрированы, чтобы вы могли отладить, почему они произошли, либо не должны происходить вообще (например, убедитесь, что вы проверяете ввод пользователя и т.д.). Если вы будете ловить все исключения, вы никогда не узнаете, почему вы получаете те исключения, которые получаете, и, следовательно, не сможете их исправить.

Обновленный ответ

В ответ на обновление вашего вопроса (особенно в том, как вы хотите обрабатывать случай сохранения), мой вопрос к вам следующий - почему вы используете исключения как средство определения пути, по которому движется ваша программа? Например, возьмем "FileNotFoundException". Очевидно, что такое может иногда случаться. Но вместо того, чтобы допускать возникновение проблемы и уведомлять об этом пользователя, прежде чем сохранять (или делать что-либо еще) с файлом, почему бы сначала не проверить, что файл может быть найден. Вы получите тот же эффект, но не будете использовать исключения для управления потоком программы.

Надеюсь, все это имеет смысл. Дайте мне знать, если у вас возникнут дополнительные вопросы.

7
ответ дан 1 December 2019 в 03:52
поделиться

Для получения дополнительной информации о том, почему ловушка (исключение) является плохой, ознакомьтесь с этой статьей: http://blogs.msdn.com/clrteam/ архив / 2009/02/19 / почему-поймать-исключение-пустой-улов-это-плохо.aspx

По сути, перехват «исключения» - это как сказать «если что-то пойдет не так, мне все равно, продолжай», а перехват «исключения» и его упаковка - это все равно что сказать «если что-то пойдет не так, относись к ним так, как будто все они пошли не так, как надо». та же самая причина'.

Это не может быть правильным, либо вы справляетесь с этим, потому что наполовину этого ожидали, либо вы совершенно не думаете, что это когда-либо должно произойти (или не знали, что это произойдет). В этом случае вам нужно какое-то ведение журнала на уровне приложения, чтобы указать вам на проблему, которой вы никогда не ожидали, а не просто одно решение, подходящее для всех.

1
ответ дан 1 December 2019 в 03:52
поделиться

В данном конкретном случае исключения должны быть достаточно редкими, чтобы обертывание их не было полезным и, скорее всего, только помешает обработке ошибок в дальнейшем. Во фреймворке .Net есть множество примеров, когда конкретное исключение, которое я могу обработать, обертывается в более общее, и это значительно усложняет (хотя и не делает невозможным) обработку конкретного случая.

0
ответ дан 1 December 2019 в 03:52
поделиться

Я уже писал статью на эту тему раньше. В нем я еще раз подчеркиваю важность сбора как можно большего количества данных об исключении. Вот URL-адрес статьи:

http://it.toolbox.com/blogs/paytonbyrd/improve-exception-handling-with-reflection-and-generics-8718

0
ответ дан 1 December 2019 в 03:52
поделиться

Какие преимущества дает пользователю сообщение «Произошла проблема при сериализации каталога»? Я полагаю, ваша проблемная область может быть экстраординарным случаем, но каждая группа пользователей, для которой я когда-либо программировал, отреагирует одинаково при чтении этого сообщения: «Программа взорвалась. Что-то в каталоге».

Я не знаю ». я не хочу быть снисходительным по отношению к моим пользователям; Я не. Просто, вообще говоря, у моих пользователей больше внимания уделяется своему вниманию, чем растрачивать его, строя детальную мысленную модель того, что происходит внутри моего программного обеспечения. Были времена, когда моим пользователям приходилось строить такое понимание, чтобы использовать программу, которую я написал, и я могу сказать вам, что этот опыт не был полезен ни им, ни мне.

Я думаю, что ваше время было бы гораздо лучше потратить на выяснение того, как надежно регистрировать исключения и соответствующее состояние приложения в форме, к которой вы можете получить доступ, когда ваши пользователи сообщают вам, что что-то сломалось, чем на разработку сложной структуры для создания ошибки. сообщения, которые люди вряд ли поймут.

0
ответ дан 1 December 2019 в 03:52
поделиться

Чтобы ответить на этот вопрос, вам нужно понять , почему перехват System.Exception - плохая идея, и понять свои собственные мотивы действий что вы предлагаете.

Это плохая идея, потому что в ней говорится, что все , что могло пойти не так, нормально, и что приложение находится в хорошем состоянии, чтобы продолжать работу после этого. Это очень смелое заявление.

Возникает вопрос: эквивалентно ли то, что вы предлагаете, перехвату System.Exception? Дает ли это потребителю вашего API больше знаний, чтобы он мог лучше судить? Это просто побуждает их перехватить YourWrappedException, что в этом случае является моральным эквивалентом перехвата System.Exception, за исключением того, что он не запускает предупреждения FXCop?

В большинстве случаев, если вы знаете, что есть правило, запрещающее что-либо делать, и хотите знать, если что-то подобное - «хорошо», вам следует начать с понимания логики исходного правила.

0
ответ дан 1 December 2019 в 03:52
поделиться

Это стандартная практика в .NET и то, как должны обрабатываться исключения, особенно исключения, которые можно восстановить.

Edit: Я действительно не имею понятия, почему меня понижают в голосовании, возможно, я читаю больше в намерениях авторов, чем все остальные. Но то, как я читаю код, тот факт, что он оборачивает эти исключения в свое пользовательское исключение, подразумевает, что потребитель этого метода оснащен оборудованием для обработки этих исключений, и что потребитель несет ответственность за обработку ошибок.

Ни один человек из DV не оставил никаких фактических возражений. Я остаюсь при своем мнении, что это вполне приемлемо, потому что потребитель должен знать о потенциальных исключениях, которые могут возникнуть, и быть оснащенным для их обработки, что показано явной упаковкой исключения. Это также сохраняет исходное исключение, так что трассировка стека доступна и основное исключение доступно.

-1
ответ дан 1 December 2019 в 03:52
поделиться

Мое практическое правило - ловить и переносить Исключение только в том случае, если у меня есть какой-то полезный контекст, который я могу добавить, например имя файла Я пытался получить доступ, или строку подключения и т. Д. Если InvalidOperationException выскакивает в вашем пользовательском интерфейсе без какой-либо другой информации, у вас будет чертовски много времени на отслеживание ошибки.

Я перехватываю определенные типы исключений только в том случае, если контекст или сообщение, которое я хочу добавить, можно сделать более полезным для этого исключения по сравнению с тем, что я бы сказал для Exception в целом.

В противном случае я позволяю исключению всплывать на другой метод, который может добавить что-то полезное. Я не хочу связывать себя узлами, пытаясь поймать, объявить и обработать все возможные типы исключений, тем более что вы никогда не знаете, когда среда выполнения может выдать скрытую ThreadAbortException или OutOfMemoryException .

Итак, в вашем примере я бы сделал что-то вроде этого:

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)
// Don't catch this because I have nothing specific to add that 
// I wouldn't also say for all exceptions.
catch (Exception exp)
{
    throw new CatalogIOException(
        string.Format("There was a problem accessing catalog file '{0}'. ({1})",
            _catfileStream.Name, exp.Message), exp);
}

Подумайте о добавлении сообщения о внутреннем исключении в исключение оболочки, чтобы, если пользователь просто отправит вам снимок экрана с диалоговым окном об ошибке, у вас, по крайней мере, есть все сообщения, а не только верхнее; и, если можете, запишите все ex.ToString () где-нибудь в файл журнала.

1
ответ дан 1 December 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: