Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 07:02
Оценка:
В программе довольно часто используется такой паттерн:

 void ThrowException(string fmt_str, param object[] args)
 {
   throw new Exception(string.Format(fmt_str, args);
 }

 bool foo()
 {
   <любая условная конструкция>
     <условие истинно>
       return true;
     <условие ложно>
       ThrowException(<набор различных параметров>);
   }
 }


Естетсвенно при компиляции получаем ошибку 'foo': not all code paths return a value. Причем иногда в километровом тексте лапши понять в каком именно парте компилятор не нашел выход бывает весьма трудно. Кроме того, и это наиболее неприятно, приходится добавлять незначимые return-ы, что очень замутняет понимание и без того не прозрачного кода. Может имеется како-то другой паттерн для таких случаев (ну, кроме явного раскрытия ThrowException — это однозначно не подходит, т.к. ф-ция более нетривиальна, чем в примере)?
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re: Определение точек выхода компилятором C#
От: Aen Sidhe Россия Просто блог
Дата: 11.08.10 07:05
Оценка: 6 (4) +7
Здравствуйте, __gas, Вы писали:

__>В программе довольно часто используется такой паттерн:


__>
__> Exception ThrowException(string fmt_str, param object[] args)
__> {
__>   return new Exception(string.Format(fmt_str, args);
__> }

__> bool foo()
__> {
__>   <любая условная конструкция>
__>     <условие истинно>
__>       return true;
__>     <условие ложно>
__>       throw ThrowException(<набор различных параметров>);
__>   }
__> }
__>
С уважением, Анатолий Попов.
ICQ: 995-908
Re: Определение точек выхода компилятором C#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 07:05
Оценка: 1 (1)
Здравствуйте, __gas, Вы писали:

__>Может имеется како-то другой паттерн для таких случаев (ну, кроме явного раскрытия ThrowException — это однозначно не подходит, т.к. ф-ция более нетривиальна, чем в примере)?


Вместо ThrowException(<набор различных параметров>); пишем
throw NewException(<набор различных параметров>);
Re: Определение точек выхода компилятором C#
От: HowardLovekraft  
Дата: 11.08.10 07:09
Оценка: -1
Здравствуйте, __gas, Вы писали:

Иногда использую такой "костыль" (выделено полужирным):
bool ThrowException(string fmt_str, param object[] args)
{
  throw new Exception(string.Format(fmt_str, args);
}

bool foo()
{
  <любая условная конструкция>
    <условие истинно>
      return true;
    <условие ложно>
      return ThrowException(<набор различных параметров>);
}

А вообще да, интересно посмотреть на более логичные решения...
Re[2]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 07:12
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

"Как я сам не дотумкал!" (с). В общем-то так и стану, наверное, все переделывать, да только таких мест уж больно много в коде сидит . Хотелось бы какого-нибудь атрибута на ф-цию, который бы говорил компилятору, чтЖ(она бросает исключение во всех случаях.
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[2]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 07:20
Оценка: -1
Здравствуйте, HowardLovekraft, Вы писали:

Костыль явно не подходит, т.к. типов возврата, как правило, более одного. Изящнее выглядит предложение Aen Sidhe. Но еще более изящным(IMHO) было бы использование специальных compile-time атрибутов на throw-функции
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[2]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 07:26
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

__>>
__>> Exception ThrowException(string fmt_str, param object[] args)
__>> {
__>>   return new Exception(string.Format(fmt_str, args);
__>> }
__>>


Еще одна засада в том, что данная функция используется еще в стопятьсот местах, где пути выхода из методов не зависят от ее использования. Это осложняет рефакторинг, т.к. надо не проворонить все места такого использования. Ведь теперь она сама ничего бросать не станет и тогда килотонне кода придет крантец.
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[3]: Определение точек выхода компилятором C#
От: Aen Sidhe Россия Просто блог
Дата: 11.08.10 07:28
Оценка:
Здравствуйте, __gas, Вы писали:

__>Здравствуйте, Aen Sidhe, Вы писали:


__>>>
__>>> Exception ThrowException(string fmt_str, param object[] args)
__>>> {
__>>>   return new Exception(string.Format(fmt_str, args);
__>>> }
__>>>


__>Еще одна засада в том, что данная функция используется еще в стопятьсот местах, где пути выхода из методов не зависят от ее использования. Это осложняет рефакторинг, т.к. надо не проворонить все места такого использования. Ведь теперь она сама ничего бросать не станет и тогда килотонне кода придет крантец.


Решарпер поможет. Find Usage — очень удобная функция, а за месяц триала отрефакторить успеете, я думаю.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[3]: Определение точек выхода компилятором C#
От: Kalina9001  
Дата: 11.08.10 07:42
Оценка:
Здравствуйте, __gas, Вы писали:

__>Здравствуйте, Aen Sidhe, Вы писали:


__>>>
__>>> Exception ThrowException(string fmt_str, param object[] args)
__>>> {
__>>>   return new Exception(string.Format(fmt_str, args);
__>>> }
__>>>


__>Еще одна засада в том, что данная функция используется еще в стопятьсот местах, где пути выхода из методов не зависят от ее использования. Это осложняет рефакторинг, т.к. надо не проворонить все места такого использования. Ведь теперь она сама ничего бросать не станет и тогда килотонне кода придет крантец.


Делаем так: Меняем имя функции
Exception GetException(string fmt_str, param object[] args)
{
   return new Exception(string.Format(fmt_str, args);
}


Компилируем, и исправляем стопятьсот мест. Так точно ничего не забудем
... << RSDN@Home 1.2.0 alpha 4 rev. 1446>>
Re[4]: Определение точек выхода компилятором C#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 07:43
Оценка: +2
Здравствуйте, Aen Sidhe, Вы писали:

AS>Здравствуйте, __gas, Вы писали:


__>>Здравствуйте, Aen Sidhe, Вы писали:


__>>>>
__>>>> Exception ThrowException(string fmt_str, param object[] args)
__>>>> {
__>>>>   return new Exception(string.Format(fmt_str, args);
__>>>> }
__>>>>


__>>Еще одна засада в том, что данная функция используется еще в стопятьсот местах, где пути выхода из методов не зависят от ее использования. Это осложняет рефакторинг, т.к. надо не проворонить все места такого использования. Ведь теперь она сама ничего бросать не станет и тогда килотонне кода придет крантец.


AS>Решарпер поможет. Find Usage — очень удобная функция, а за месяц триала отрефакторить успеете, я думаю.


Можно и без Решарпера. ThrowException переименуем в NewException, игнорируя предложения студии в рефакторинге, потом пытаемся скомпилить. Получим кучу Error-ов. В месте каждой ошибки заменяем "ThrowException" на "throw NewException".
Re[4]: Определение точек выхода компилятором C#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 07:44
Оценка: :)
Здравствуйте, Kalina9001, Вы писали:

K>Компилируем, и исправляем стопятьсот мест. Так точно ничего не забудем

+1
Опять я опоздал
Re[4]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 08:09
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>Решарпер поможет. Find Usage — очень удобная функция, а за месяц триала отрефакторить успеете, я думаю.


С нашим отделом тестирования нужна вечность триала . Вот вроде бы неплохое (хоть и некрасивое) решение:

    static Exception ThrowException(<blabla>)
    {
      var e = new Exception();
      switch(e != null)
      {
        case true:
          throw e;
        default:
          return e;
      }
    }


Тогда ThrowException можно юзать и так и сяк и без исправления в куче мест:

throw ThrowException(<....>); //используется по-умному в новых местах кода

ThrowException(<....>); //Обеспечивается совместимость со старой лапшой
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[5]: Определение точек выхода компилятором C#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 08:13
Оценка:
Здравствуйте, __gas, Вы писали:

__>Здравствуйте, Aen Sidhe, Вы писали:


AS>>Решарпер поможет. Find Usage — очень удобная функция, а за месяц триала отрефакторить успеете, я думаю.


__>С нашим отделом тестирования нужна вечность триала . Вот вроде бы неплохое (хоть и некрасивое) решение:


__>
__>    static Exception ThrowException(<blabla>)
__>    {
__>      var e = new Exception();
__>      switch(e != null)
__>      {
__>        case true:
__>          throw e;
__>        default:
__>          return e;
__>      }
__>    }
__>


Решение чего?

__>Тогда ThrowException можно юзать и так и сяк и без исправления в куче мест:

__>

__>throw ThrowException(<....>); //используется по-умному в новых местах кода

__>ThrowException(<....>); //Обеспечивается совместимость со старой лапшой
__>


Совместимости не будет. Кто возбудит исключение-то?
Re[6]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 08:18
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, __gas, Вы писали:


S>Опять я опоздал

Теперь Вы явно поспешили .

S>Совместимости не будет. Кто возбудит исключение-то?


var e = new Exception();
switch(e != null)
{
  case true:
    throw e;
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[7]: Определение точек выхода компилятором C#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 08:31
Оценка: 1 (1)
Здравствуйте, __gas, Вы писали:

__>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, __gas, Вы писали:


S>>Опять я опоздал

__>Теперь Вы явно поспешили .

S>>Совместимости не будет. Кто возбудит исключение-то?


__>
__>var e = new Exception();
__>switch(e != null)
__>{
__>  case true:
__>    throw e;

__>

эээ, понятно. А для чего проверка-то?
Re[8]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 08:36
Оценка:
Здравствуйте, samius, Вы писали:

S>эээ, понятно. А для чего проверка-то?


Ну это типа финт ушами (потому и некрасивое решение). Просто иначе return e воспримется компилятором как недостижимый код — а это лишнее предупреждение, которое в релизе будет зачтено за ошибку. Можно, конечно и условной компиляцией побаловаться, или отключением ворнинга, но это вообще не гуд.

Основной недостаток в использовании такой ф-ции заключен в том, что компилятор не распознает недостижимый код после нее. Соответственно потенциальные UB и опять же неудовлетворительное автодокументирование кода.
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[9]: Определение точек выхода компилятором C#
От: samius Япония http://sams-tricks.blogspot.com
Дата: 11.08.10 08:39
Оценка:
Здравствуйте, __gas, Вы писали:

__>Здравствуйте, samius, Вы писали:


S>>эээ, понятно. А для чего проверка-то?


__>Ну это типа финт ушами (потому и некрасивое решение). Просто иначе return e воспримется компилятором как недостижимый код — а это лишнее предупреждение, которое в релизе будет зачтено за ошибку. Можно, конечно и условной компиляцией побаловаться, или отключением ворнинга, но это вообще не гуд.


__>Основной недостаток в использовании такой ф-ции заключен в том, что компилятор не распознает недостижимый код после нее. Соответственно потенциальные UB и опять же неудовлетворительное автодокументирование кода.


Можно было бы сделать throw без проверки, и потом, после исправления всех мест использования, вместо throw в методе заменить return-ом.
Re[8]: Определение точек выхода компилятором C#
От: __gas  
Дата: 11.08.10 08:40
Оценка:
Здравствуйте, samius, Вы писали:

S>эээ, понятно. А для чего проверка-то?


Да, Вы правы. Лучше так

Exception ThrowException(<blabla>)
{
  throw new Exception();
}
Как известно, 90% людей верят утверждениям, начинающимся со слов «как известно».
Re[2]: Определение точек выхода компилятором C#
От: _FRED_ Черногория
Дата: 11.08.10 08:46
Оценка: +1
Здравствуйте, Aen Sidhe, Вы писали:

__>>В программе довольно часто используется такой паттерн:

__>>       throw ThrowException(<набор различных параметров>);


throw внутри хелпера не просто что бы затруднить использование кода. Метод, в котором есть throw с большой долей вероятности не будет заинлайнен, тогда как даже достаточно развесистые но простые методы a-la
bool foo()
 {
   <любая условная конструкция>
     <условие истинно>
       return true;
     <условие ложно>
       ThrowException(<набор различных параметров>);
       return anything;
   }
 }

очень даже могут быть. В релизе и когда полчается приличный стек вызовов это очень заметно.
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Определение точек выхода компилятором C#
От: cvetkov  
Дата: 11.08.10 08:46
Оценка:
Здравствуйте, __gas, Вы писали:


__>
__>    static Exception ThrowException(<blabla>)
__>    {
__>      var e = new Exception();
__>      switch(e != null)
__>      {
__>        case true:
__>          throw e;
__>        default:
__>          return e;
__>      }
__>    }
__>


а разве условие e != null не всегда true?
... << RSDN@Home 1.2.0 alpha 4 rev. 1227>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.