1. C# / Говнокод #3226

    +119

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    private static bool TryDeleteFile(string path)
            {
                try
                {
                    File.Delete(path);
                    return true;
                }
                catch (IOException e)
                {
                    return false;
                }
                catch (UnauthorizedAccessException e)
                {
                    return false;
                }
                catch (ArgumentException ae)
                {
                    return false;
                }
                catch (NotSupportedException e)
                {
                    return false;
                }
            }

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

    Запостил: gopher, 14 Мая 2010

    Комментарии (60) RSS

    • все правильно )) я тоже так делаю )))) правда, менять исключение на флаг, это ли не возвращение лет этац дцать назад?
      Ответить
      • Суть в том что лестница кетчей не имеет никакого смысла, ведь перехватываются все исключения. Хватило бы и catch (Exception).
        Ответить
        • Лучше просто catch без ничего.
          Ответить
        • тока хотел написать, что хз как в шарпе, а в яве я точно сделал бы catch (Exception), но собственно даже с имея необходимость в этой куче кетчей я бы сделал так
          catch (IOException e){
          }
          catch (UnauthorizedAccessException e) {
          }
          catch (ArgumentException ae){
          }
          catch (NotSupportedException e){
          }
          return false;
          Ответить
        • а вот таки всякие там сонары (на яве) ругаюца на catch (Exception)
          Ответить
    • Блин, такое действие, как удаление, можно проконтролировать и без механизма исключений.
      (например: Delete(F); Result := (IOResult = 0);) Когда вводили этот механизм (для того, чтобы упростить диагностику ошибок и сделать программы более живучими в случае ошибок), то не предполагали, что быдлокодота будет вхреначивать этот непростой по внутреннему устройству механизм во все щели.
      Единственное встретившееся мне место (возможно, если другие, но в данном говнокоде не тот случай), где исключение - именно штатная ситуация - это вычисление некоторых выражений, мне этот вопрос подвернулся при написании калькулятора. Как узнать, сосчитается ли exp(a*b), зная a и b? Только попытавшись вычислить и отловив исключение. Если есть другой способ - подскажите. А то исключение генерирует сопроцессор при попытке извлечения NANа в память, как это убрать - не знаю.
      Ответить
      • почему "такое действие как удаление"? что, проверять не надо? рискуем засориться временными файлями. А флаг за собой тянуть еще то удовольствие
        Ответить
        • Я в скобках написал, как проверять.
          Ответить
          • все равно НЕ ХОЧУ тянуть за собой флаги типа "какая хрень у меня приключилась" вместо вменяемого результата
            Ответить
            • Исключение - не есть вменяемый результат. Механизм флагов вполне удобен. К тому же херня с исключениями - это тот же механизм флагов, только ещё и с извращением над указателем на обработчик ошибок.
              Ответить
              • где извращение?
                Ответить
                • А ты посмотри, как эта хрень реализована.
                  Она изначально предназначена для отлова того, что в нормально работающей программе произойти не может. Кто ж думал, что её будет использовать все, кому не лень?
                  Ответить
                  • даже в нормально работающей программе может произойти хуета: кто-то удалил или переместил файл, нагнулась БД или еще что-то в этом роде... и, в яве, например, checked exceptions просто обязывают задумываться о таком варианте.

                    во всяком случае, еще хуже было до этого, напр. в паскале:
                    var
                    T: Text;
                    S: String;
                    begin
                    Write('Enter filename: ');
                    Readln(S);
                    Assign(T, S);
                    {$I-}
                    Reset(T); { открываем файл для чтения }
                    {$I+}
                    if IOResult <> 0 then { если не нуль, то была ошибка }
                    begin
                    Write('Error when open file!');
                    Halt;
                    end;
                    Ответить
                    • И что в этом плохого? В таком механизме? Я им ползуюсь, очень удобно.
                      Конечно, я ипользую блок try. Но только для ситуаций, которых по идее быть не должно, и для того, чтобы программа вывела все подробности ошибки.
                      Ответить
                      • А что вообще подразумевается под 'ситуации, которых по идее быть не должно'? И где начинается это 'не должно'
                        Ответить
                        • Это то, чего по мнению программиста произойти в принципе не может.
                          Ответить
                          • если программист думает что такая ситуация не произойдет зачем же он будет исключение использовать?
                            Ответить
                  • А представь ситуацию, к примеру, когда возвращаемое значение может быть любое (в том числе и инвалидно, при том что ошибки не произошло).
                    А тут бац - и ошибка. Как быть в таком случае?

                    К примеру, функция возращает интовое значение от минус до плюс бесконечности. А внутри произошла ошибка о которой пользователь должен знать однозначно. Назовешь решение с системой флагов без извращений - респект тебе и уважуха.
                    Ответить
                    • f :: a -> Either ErrorCode Integer

                      :3
                      Ответить
                    • > К примеру, функция возращает интовое значение от минус до плюс бесконечности.

                      Это место мне уже непонятно. Вы имели в виду беззнаковое 64-битное? Или длинную арифметику?
                      Ответить
                      • Нет, просто число может возвращать от максимально го до мининимального значения примитива (т.е. у байта - от 0 до 255 и т.п.)
                        Ответить
                        • Ну заводишь глобальную переменную ComputingError. Функция меняет её значение. Потом смотришь на значение флага. Какие проблемы, сто лет так делаю, и жив пока.
                          Ответить
                          • Тебя в аду уже ждут Карри, Черч и Милнер, за все побочные эффекты ответишь. :)
                            Ответить
                            • Если они так правы, то что они делают в аду? Ты лучше расскажи про побочные эфекты компиляции, когда исключение происходит внутри вложенной функции, у которой есть локальные переменные-автоуказатели.
                              Сколько там неявных траев-катчей втыкается в код.
                              Ответить
                              • >что они делают в аду?
                                а они там как приглашенные эксперты =)
                                Ответить
                              • Пример тормознутого кода запостите, плиз. Хочеться разобраться.
                                Ответить
                                • Куча вложенных процедур, внутренняя что-то делает с локальным автоуказат... Аааа, это ж церешётка, тут ГЦ. Извините.
                                  Ответить
                          • Всю жизнь однопоточные проги ваяешь?
                            Ответить
      • если бы изначально ранние языки поддерживали возвращение не одного, а нескольких значений, то никакие бы исключения никому бы в голову не пришло придумывать.

        т.е. сплошное легаси.

        можно было бы сделать так в псевдокоде с анонимными типами и паттерн-матчингом:

        method GetSomeIntResult(a: String, b: int): [ Success(value: int) | FileNotFound(message: String) | SecurityError(message: String) ] <-- возвращается вариантный анонимный тип

        и далее так:

        var r = GetSomeIntResult("blabla", 666);
        
        match(r)
        {
           case Success(value: int):
                var someOtherData = value + 666;
           case FileNotFound(message: String):
                 showMessage("oh my god, we failed.");
           default:
                /* shit we don't care */
        }


        Оверхед только через стек.
        Ответить
        • Можно возвращать данные такого типа:
          record
          KindOfRes: (Success, FileNotFound, SecurityEror);
          case byte of
          0: (Value: integer);
          1: (Message: string);
          end;
          end;
          Ответить
        • >если бы изначально ранние языки поддерживали возвращение не одного, а нескольких значений, то никакие бы исключения никому бы в голову не пришло придумывать.
          Нет. У исключений есть дополнительная возможность выйти на несколько функций вверх, и даже остаться в текущей.
          + возможность множества обработчиков, получающих исключения по принципу сообщений.
          + автоматическая классификация ошибки, например по типу объекта (для ООП исключений).
          Конечно любой из этих возможностей можно не пользоваться, но многообразие выбора увеличивает удобство и лёгкость затачивания кода под конкретную задачу.
          Ответить
          • > У исключений есть дополнительная возможность выйти на несколько функций вверх

            Это нахрен не надо. Покажите пример, чтобы это надо было. В говнокодах сойдёт.

            > и даже остаться в текущей.

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

            > возможность множества обработчиков, получающих исключения по принципу сообщений.

            Пример?

            > автоматическая классификация ошибки, например по типу объекта (для ООП исключений).

            А я привёл вариантный тип, чем не устраивает паттерн-метчинг? То же определение по (под)типу.

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

            ... и возможность для приложения за'crash'иться. Но от этого спасают проверяемые исключения как в яве. Но тогда отличия от предложенной мной схемы нету.
            Ответить
            • Для обработки нескольких возвратов одним блоков в моём гипотетическом мегакрутом языке было бы так:

              var r = GetSomeIntResult(x = "blabla", y = 666);
              var s = GetSomeOtherResult(x = "fff", y = 13.0);
              
              match(r, s) # параллельный метчинг, так сказать
              {
              
                 # уточняем, чтобы не путать
                 with r::Success(value: int) ->
                      var someOtherData = value + 666;
              
                 # уточняем, чтобы не путать
                 with s::Success(value: int) ->
                      var someOtherData2 = value + 666;
              
                 # обобщено на оба результата
                 with FileNotFound(message: String) ->
                       showMessage("oh my god, we failed.");
              
                 default ->
                      # default
              }
              Ответить
              • найдите 10 отличий:
                int someOtherData=0;
                int someOtherData2=0;
                try {
                int someOtherData+=this.GetSomeIntResult("blabla",666);
                } catch(FileNotFoundException e) {
                 this.showMessage("oh my god, we failed.");
                } finally {
                // default
                }
                try {
                int someOtherData2+=this. GetSomeOtherResult("fff",13.0);
                } catch(FileNotFoundException e) {
                 this.showMessage("oh my god, we failed.");
                } finally {
                // default
                }


                чем же лучше ваши мегакрутые гипотезы уже давно существующего механизма исключений?
                мой переписанный пример плох лишь тем, что обработчики идентичны, но можно их вынести в отдельный метод, если код усложнится
                Ответить
                • > мегакрутые гипотезы уже давно существующего механизма исключений?

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

                  > чем же лучше

                  Производительностью при кидании исключения, например. В исключениях используется туева куча дорогостоящих костылей, а тут только оверхед через стек (причём варианты они пакуются через union'ы внутренне, т.е. в основном это максимум 1 указатель на Message).

                  Отличий много, хотя бы в том, что мы не имеем лишней сущности "исключение", а имеем лишь одну сущность "результат" (который может быть фейл или не фейл), и можем ad-hoc создавать "исключения" разного типа. В с++ надо писать тонны мусора. В прочем, обезьянкам платят за количество строк кода, поэтому среди них подобное не будет популярно. Вообще идею можно развить и получить большую гибкость, я же уже привёл к примеру параллельный метчинг.
                  Алсо, тут исключение благодаря анонимному типу становится подтипом результата. Можно всё это упакованно хранить. Можно обработку исключения отложить. И т. д.
                  Ответить
                  • + возможные "нештатные" ситуации становятся частью контракта/интефрейса. хотя подобное и так есть в яве.

                    в неяве как: из функции несколько выходов, причём явный только один. не функция, а дуршлаг.
                    Ответить
                  • допустим,можно пожертвовать несколько миллисекунд, если вдруг исключение - разумеется, если не эксепшн-стайл программирование.

                    Все равно не вижу преимущества в данном контексте. Если мы хотим преимущества - нужно менять контекст (ФП тот же). Механизм исключений, при всей дороговизне, не мусорит мышления и не уводит в сторону от проблемы
                    Ответить
            • >если бы изначально ранние языки поддерживали возвращение не одного, а нескольких значений
              а разве бы это помогло? несколько значений можно возвращать массивом, но и это не спасает от необходимости ЯВНОГО возвращения какбе return [a,b,c] из каждого уровня вызова, исключения позволяют уменьшить кол-во необходимых потуг

              далее.
              вы утверждаете, что "нахрен не надо" возвращаться на несколько уровней вверх. Получается, каждую нештатную ситуацию нужно обрабатывать именно там, где она возникла? Окей. Представьте, что уровней абстракции (и соотв. вложенности вызова) скажем, 10. Значит, я вынужден писать 10 обработчиков нештатных ситуаций, умножить на кол-во таких ситуаций, причем каждый обработчик должен позаботиться не только о своей собственной реакции, но и о том, как отчитаться вышестоящим. Пардон мсье, тогда любой код будет ГК, который трудно читать и сопровождать

              По поводу паттерн-метчинга: "зачем делать сложным то, что проще простого"?
              приведенный пример при всей простоте, уже сложнее для понимания, и уже логика из "что-то произошло, надо что-то делать" превращается в "ой, а результат хорош или нет?" Метчинг можно опустить, и продолжать с неверным результатом, тогда как исключение просто не даст лопухнуться

              и еще по поводу крешинга. Знаете, уж лучше пусть крешится, чем втихомолку и с радостью выдаст неверный результат. Как сказал один мой друг, "лучше пусть громко перднет, что бы было видно откуда говно потекло, чем предательски набздит" :)
              Ответить
              • > Представьте, что уровней абстракции (и соотв. вложенности вызова) скажем, 10. Значит, я вынужден писать 10 обработчиков нештатных ситуаций, умножить на кол-во таких ситуаций

                Говно такие абстракции, если нештатная ситуация одного слоя спокойно маппится на нештатную ситуацию другого слоя (без "rethrow"ов). Скорей всего, ООП головного мозга (какие-нибудь излюбленные стопицот фабрик для двепицот адаптеров). Если что-то такое нужно, то скорей всего код - говнокод (который валится, допустим, с обобщённым index out of range). вот любят кричать об инкапсуляции данных, а орошо было задуматься об инкапсуляции нештатных ситуаций. что-то подобное было бы полезно для дебуга разве что. что ж, для дебуга существуют куда более продвинутые технологии =\

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

                > чем втихомолку и с радостью выдаст неверный результат

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

                    это что еще за ересь? ООП гойловного мозга?
                    Ответить
    • Интересно эта функция используется так?
      while (!TryDeleteFile(fielpath)){}
      Ответить
    • Пиздеж и провокация.
      OutOfMemoryException не перехватывается.
      Ответить
      • а накуя? оО

        еще кажите ArmageddonError x_x
        Ответить
      • Это в С#?
        Ответить
      • Мол если память закончилась, то делать нечего и можно делать армагедон?
        Может просто пользователь большой файл попытался прочитать. Не повод крешить из-за этого борт программу автопилота самолёта. Это повод перехватить исключение и не пытатся читать дальше этот злощасный файл.
        Ответить
        • Да, действительно, давайте везде понаставим catch (Exception) и получим меганадежное приложение.
          Ответить
        • Это повод проверить результат попытки выделить ещё кусок памяти. Или проверить размер файла перед считыванием.
          Ответить
        • я что-то сомневаюсь насчёт "неперехватывается"
          хотя единственное, что я знаю, так это то что память под new OutOfMemoryException() предаллоцируется при стартапе.
          Ответить

    Добавить комментарий