2010-06-03 3 views
4

После того, как я прочитал MSDN article, что стимулировала следующую парадигму программирования (это не 100% верно ... см редактировать):Исключение бросает: инкапсулировать их или нет?

public class MyClass 
{ 
    public void Method1() 
    { 
     NewCustomException(); 
    } 

    public void Method2() 
    { 
     NewCustomException(); 
    } 

    void NewCustomException() 
    { 
     throw new CustomException("Exception message"); 
    } 
} 

Как вы думаете, эта парадигма имеет смысл? Не было бы достаточно, чтобы сохранить сообщение об исключении в поле static const, а затем передать его конструктору исключения вместо инкапсуляции всего исключения?

EDIT:

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

Я просто заметил (см цитата), что статья рассказывает возвращения исключение:

public class MyClass 
{ 
    public void Method1() 
    { 
     throw NewCustomException(); 
    } 

    public void Method2() 
    { 
     throw NewCustomException(); 
    } 

    CustomException NewCustomException() 
    { 
     return new CustomException("Exception message"); 
    } 
} 

Что вы думаете об этом?

+0

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

+0

А, ок. Но я действительно имею в виду только исключение, без какой-либо логики. – Simon

+0

У вас есть ссылка на статью случайно? Было бы неплохо прочитать контекст, в котором кто-то рекомендовал это. –

ответ

10

Мое понимание заключается в том, что передача экземпляра исключений - это faux pas, если только по той причине, что вы теряете трассировку стека, связанную с исключением. Вызов другого метода изменит трассировку стека и тем самым сделает ее бесполезной. Я бы рекомендовал как минимум получить трассировку стека за исключением и передать ее в качестве аргумента для какого-то помощника, если это путь, по которому вы собираетесь спуститься.

+0

Он не говорит о передаче экземпляра исключения, просто помещая его сообщение в 'const'. –

4

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

+0

Infact Вы не можете поместить исключение в поле 'const'. 'static readonly' является ближайшим вы можете получить. –

+2

@Matti: Он не говорил об исключении, просто это сообщение об ошибке. –

+1

Ох. Я думаю, это помогло бы, если бы я правильно прочитал материал ¬__¬ –

0

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

0

Это удобно, если вы не знаете, как вы планируете обрабатывать исключения. Вы хотите просто бросить его? Или, возможно, позже вы собираетесь регистрировать исключение где-нибудь, а затем бросить его? Или, может быть, передать некоторые аргументы (т. Е. Имя метода и т. Д.), Которые входят в комплект с исключением?

В этом случае создание отдельного метода, который обрабатывает ситуацию с исключением, удобно, когда вы хотите его изменить.

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

2

У меня был бы метод, который строит исключение, а не тот, который его бросает. Как и в примере ниже. Кажется, я помню, что руководство Microsoft рекомендовало это, но я не могу вспомнить, где.

С помощью этой методики, если вы хотите изменить тип исключения по какой-либо причине, вам нужно сделать это только в одном месте (например, изменение с ConfigurationException до ConfigurationErrorsException при обновлении с .NET 1.x до .NET 2.0) ,

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

Вы, очевидно, не будет делать это в тривиальных случаях (например, вы не заменит throw new ArgumentNullException("myParamName") на throw BuildArgumentNullException("myParamName"))

private static Exception BuildSomeException(... parameters with info to include in the exception ...) 
{ 
    string message = String.Format(...); 
    return new SomeException(message, ...); 
} 

... 
throw BuildSomeException(...); 
3

Еще одна проблема, которую вы получите, что делать то, что там будет много мест, где вы не будете даже быть в состоянии выбросить исключение, потому что компилятор не допустит этого. Рассмотрим эти два метода, добавленные в ваш класс:

public string GetFoo1(bool bar) 
    { 
     if (bar) 
      return ""; 
     else 
      NewCustomException(); 
    } 

    public string GetFoo2(bool bar) 
    { 
     if (bar) 
      return ""; 
     else 
      throw new CustomException("Exception message"); 
    } 

GetFoo1 не будет компилироваться, пока GetFoo2 будет.

+1

+1 хороший момент о том, что компилятор не увидит бросок, если он инкапсулирован в метод. – Joe

0

Обычно я предпочитаю хранить исключение сообщения как ресурсы. Это служит нескольким целям:

  • Если требование сводится к локализации сообщений об исключениях, это не требует больших усилий.
  • Сообщения об исключении, как правило, более стандартизированы для разработчиков, поскольку это дополнительная работа для создания нового, но только немного другого сообщения.
  • Если вы гарантируете, что сообщения ссылаются на идентификатор и включают в себя идентификатор с исключением при его броске, то трассировка сообщения на код, который его бросил, проще.

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

Смежные вопросы