Является ли это веской причиной для пустой попытки try или есть более элегантное решение? - PullRequest
1 голос
/ 28 июня 2011

Предположим, у меня есть следующая иерархия классов:

Объект Person содержит объект Customer, а объект Customer содержит объект Address.

Мне все равно, есть ли у клиента адрес илинет, но если они это сделают, я хочу сохранить его в базе данных.Так что в этом случае вполне нормально иметь что-то вроде:

try
{
     Address addr = person.Customer.Address;
     db.SaveAddress(addr);
}
catch
{
    //I don't care, but if it is there, just save it.
}

В вышеприведенном случае мне все равно, если Customer равен нулю или Address равен нулю.Другой вариант, который у меня был, был

 if(person.Customer != null)
 {
     if(person.Customer.Address != null)
     {

     }
 }

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

Ответы [ 5 ]

5 голосов
/ 28 июня 2011

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

Вы можете объединить 2-й пример в 1 строку с большинством языков с коротким замыканием.

 if(person.Customer != null && person.Customer.Address != null)
 {

 }

Пример:

 bool isAddressValid = person.Customer != null && person.Customer.Address != null;
 if (isAddressIsValid) { }

Переключение контекста: http://en.wikipedia.org/wiki/Context_switch

3 голосов
/ 28 июня 2011

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

  1. Как и другие упомянутые люди, использование исключений имеет очень высокую стоимость производительности (когда на самом деле создаются исключения). Для действительного и распространенного сценария вы обычно предпочитаете получать указание об ошибке через некоторое возвращаемое значение условия или метода.

  2. Даже если вы обнаружите возможное условие путем перехвата исключения, рекомендуется генерировать определенный тип исключения и перехватывать только тот тип исключения, который вы разрешаете. Потому что, если что-то пошло не так, и было выдано другое исключение? (например, что если сохранить через OutOfMemoryException? Вы бы его поймали и проигнорировали). В вашем случае, даже если вы пошли на перехват и игнорирование исключения, было бы лучше только поймать NullReferenceException и игнорировать все остальное. Еще лучше было бы определить свой собственный тип исключения (например, CustomerHasNoAddressException) и только поймать его.

2 голосов
/ 28 июня 2011

Это очень плохое использование Исключения. Иногда есть "сомнительные" и "подлые" места, но это просто совершенно ... плохо .

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

Что, если SavePerson не сможет спасти человека? :( Все бы благополучно продолжилось (ну, кроме мистера Фреда, который не спасен ... он может быть расстроен.)

Код с явной «проверкой на ноль» не связан с этой проблемой, и добавляет самодокументирование. очевидно , что ожидается случай null (является ли это обоснование обоснованным или нет, это другая история). Если количество уровней отступов является проблемой, рассмотрите внутренние методы с контрактом о непринятии null значений .

Удачного кодирования.

2 голосов
/ 28 июня 2011

Вы должны всегда проверять null (или любое другое условие), если вы знаете, что оно может произойти, и вы можете избежать исключения, причина в том, что исключения являются медленными и, как вы указываете, неэлегансными.Просто используйте:

if(person.Customer != null && person.Customer.Address != null) {
    // ...
}
1 голос
/ 28 июня 2011

Крайне плохая практика - использовать исключения для обычного потока управления.Вариант try-catch может быть в 1000 раз медленнее, чем при нулевых проверках из-за разматывания стека.

...