Си диез / Говнокод #12321 Ссылка на оригинал

0

  1. 1
public virtual int ReadByte()

Тут в соседнем треде появилась такая тема:

http://msdn.microsoft.com/ru-ru/library/system.io.stream.readbyte.aspx
http://govnokod.ru/12311#comment164854

Запостил: LispGovno LispGovno, (Updated )

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

  • Зато лентяям можно делать так:
    while (bt = stream.ReadByte() > 0)
    {
        //...
    }
    Ответить
      • Не, здесь будет что-нибудь типа "Error: cannot convert from 'bool' to 'byte'". Тут вам не там.
        Ответить
      • Вы хоть по ссылке сходили?
        Возвращаемое значение
        [qoute]Тип: System.Int32
        Байт без знака, приведенный к Int32, или значение -1, если достигнут конец потока.[/qoute]
        Другой вопрос, что писал без IDE и есть ошибки.

        int bt = 0;
        FileStream stream = new FileStream(@"d:\test.txt", FileMode.Open);
        while ((bt = stream.ReadByte()) >= 0)
        {
            Console.WriteLine(bt);
        }
        Ответить
    • >Зато лентяям можно делать так:
      >while (bt = stream.ReadByte() > 0)
      Зато ты лентяй и сразу ошибся. Вот что я называю нихрена непродуманным интерфейсом, что приводит к таким банальным глупым ошибкам.
      Ответить
      • Ну подумаешь, забыл, что у присваивания самый низкий приоритет )
        Конкретно этот код даже не скомпилируется, выдаёт ошибку "Cannot implicitly convert type 'bool' to 'int'" (строгая типизация, это вам не сишка )
        И из того, что я привёл этот пример ещё не следует, что я его использую.
        Ответить
      • Не знаю. У меня в независимо от языка руки так и чешутся поставить там скобки, чтоб понятней было.
        Это раз.
        Во-вторых, используешь сишный side-effect инкрементов и присваиваний, тогда yoda-style твой лучший друг.
        В-третьих, читать по байту - мелковато.
        В-четвертых, есть LINQ.
        Ответить
  • Ну дык... конец файла — это нормальная рабочая ситуация. А исключения предназначены для исключительных ситуаций.
    В Питоне другая философия, там даже из цикла выход осуществляется через исключение.
    Ответить
    • >Ну дык... конец файла — это нормальная рабочая ситуация.
      Ты не поверишь:
      while(stream.NotEnd())
      {
        byte bt = stream.ReadByte();
        ...
      }
      Ответить
      • Ну получается тогда такая бяка:
        while(stream.NotEnd())
        {
          byte bt = stream.ReadByte();
          if (stream.eos()) 
            break;
        
          /*process byte*/
        }
        Ответить
        • Не понял. Предполагается же, что раз NotEnd(), то байт гарантированно* прочитать можно.
          Другой вопрос, что в Stream такого свойства нет. А почему так сделано... Ну, возможно, для облегчения реализации интерфейса. Да и в общем случае не всегда можно узнать, достигнут ли конец данных, не фактически прочитав байт.
          Ответить
          • > байт гарантированно* прочитать можно.
            И что вы можете гарантировать в сокете?
            Ответить
              • Когда буфер чтения исчерпается, но сокет еще открыт и сообщение еще не до конца принято, то что должна возвращать NotEnd()?
                Ответить
                • Ну вот если байт нету, а сокет открыт, то что еще надо делать?
                  Очевидно же.
                  Пока буфер вновь не наполнится хотя байтом или не закроется сокет.
                  Ответить
                  • А. Теперь понятно объяснил.
                    Просто я привык, что блокирующий у нас read()
                    Ответить
                    • В таких делах вроде как любое чтение блокирующее.
                      Или я что-то упустил?
                      Ответить
      • In the colapicmted world we live in, it's good to find simple solutions. http://kvgydlm.com [url=http://dnmtkzqfq.com]dnmtkzqfq[/url] [link=http://enjjyltk.com]enjjyltk[/link]
        Ответить
    • На самом деле есть две ситуации:

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

      А другая ситуация - я читаю из файла определенную структуру, вызывая всякие-там getInt, getFloat, getDouble и т.п. И вот тут конец файла до окончания структуры это именно исключительная ситуация. И именно ее я хотел показать как пример об удобстве исключений в соседнем треде.
      Ответить
  • В конце концов напиши:
    public virtual byte? ReadByte()
    Что типа public virtual Maybe<byte> ReadByte()
    Но зачем городить такое говно, что они сделали?
    Ответить
    • "?" во фреймворке нигде не используется, насколько я знаю.
      Ответить
        • Да, что-то типа. Только 1.0 и 2.0 не совместимы, и что им мешало использовать его, не понятно. Nullable там встречается, но только в неявном виде.
          Ответить
          • То есть заменить int ReadByte() на byte? ReadByte() ? Это было бы слишком кардинальное изменение для такого базового API.
            Ответить
            • Я не конкретно про этот случай, я вообще имел ввиду. Имхо, тут всё вполне нормально.
              Ответить
    • А вот откуда это все пошло:

      fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error.

      #define EOF (-1)
      Ответить
  • Что-то все попрятались и на уютненький не заходят.
    Конца Светы что-ли ждут?
    Ответить
    • bormand только что #
      Разлогинило ;(
      А пароль, в который раз, забыл сохранить на рабочей машине.
      Ответить
  • @bormand:
    > В нормальных компиляторах (аля гцц) плата за экцепшн берется только при его вбросе и раскрутке [...]

    Производительность - да. Но есть еще проблема с размером кода.

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

    Самая центральная функция: ~5К асма на саму логику против ~15К асма (после последнего `ret`а) на обработку исключений. Если сильно в эти 15К всматриваться, то можно реально разглядеть что тут есть кусок кода соответствующий каждому месту функции которое может бросать исключения. Подавляющая часть этого кода: вызов деструкторов для временных/локальных объектов.

    И это я здесь говорю про код. Exception handling tables по старой памяти так много места не занимают - да и в любом случае IIRC они лежат в своем собственном сегменте и сегмент кода не засоряют.

    ЗЫ Я сомневаюсь что C# может это сделать намного лучше.
    Ответить
    • Вы так гойворите будто ifы не увеличивают размер кода.
      Я уже говорил и повторю еще раз: нужно ключевое слово, оператор, флаг или там аннотация, чтобы включать и выключать исключения на блоке кода.
      Ответить
      • > Выключать исключения на блоке кода
        Чтобы превратить "ой упало, вот вам стектрейс" в "кровь-кишки-молча-распидорасило-внутреннее-состояние-проги-и-об-этом-узнали-через-год"?

        Разве что добавить на функции и блоки атрибут типа nothrow, показывающий, что она не может вбросить никаких исключений, даже RuntimeException. И разрешать из таких функций вызывать только меченные... Тогда будет гарантия, что хуйню не напишешь.
        public void do1() nothrow {
        }
        ...
        public void test() {
            nothrow {
                do1();
                do2();
                do3();
            }
        }
        P.S. К сожалению любой блок, в котором есть new, пометить как nothrow уже не получится ;(
        Ответить
        • И получим java checked exceptions. В самой хуёвой форме.
          Моё мнение такое если и уж делали checked exceptions, то надо было сделать их настраиваемыми как опция компилятора ignore/warn/error. Вместо того чтобы тупо запрещать коду компилится.

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

          В жабе если run() в треде кидалось исключение (куда ему дальше идти? тоже игнорится) то стектрейс писался в System.err.
          Несколько версий спустя туда добавили возможность задать default handler для таких вот неуловимых ошибок.
          Так что разрулить можно.
          Ответить
        • > P.S. К сожалению любой блок, в котором есть new, пометить как nothrow уже не получится ;(

          Почему? Ааа, жаба...
          Ответить
          • Ну в крестах ты можешь попросить, чтобы new возвращало тебе null. Но будешь ли ты его проверять при каждом вызове? Что ты будешь делать, если там null? Вызовешь ассерт? Будешь закрывать ресурсы и возвращать ошибку на уровень выше? Так и исключениями можно сделать тоже самое... только меньшими усилиями.
            Ответить
      • "Вы так гойворите будто ifы не увеличивают размер кода."

        if'ы есть часть нормального кода. обработка исколючений - 99% кода генирится самим компилером и никакого отношения к остальному коду или логике не имеет.

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

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

        еще раз повторю - "Подавляющая часть этого кода: вызов деструкторов для временных/локальных объектов." другими словами этот авто-сгенерированый код как бы никакого непосредственного отношения к исключениям не имеет, он имеет непосредственное отношение к коду функции. но этот код нужен только исключительно для обработки исключений, что бы гарантировать что даже в этом случае объекты/етц ведут себя согласно С++ стандартам.
        Ответить
        • Я о ключевом слове, которое позволит тупо игнорить исключения и просто продолжать своё выполнение, в отдельно взятом за жопу куске кода. Ближайший аналог приснопамятный On Error Resume Next.
          Сишный аналог - каждая операция обернута в try, с кетчем который вызывает единый, заданный кодером обработчик ошибок.

          >этот код нужен только исключительно для обработки исключений, что бы гарантировать что объекты ведут себя согласно С++ стандартам.

          За удобство в любом случае придется чем-то заплатить, будь то скорость и/или размер программы. Не спорю.
          Ответить
        • > if'ы есть часть нормального кода
          Вот кстати не всегда... Ифы, проверяющие коды возврата, закрывающие всякие ресурсы и освобождающие память это как раз обработка исключений. Только она, к сожалению, не генерируется компилятором, а пишется руками.

          > согласно С++ стандартам
          Согласно здравому смыслу. Иначе приходится городить конструкции с goto в конец и закрыванием всех файлов. А готофобам и того хуже...
          Ответить
  • - Что тут у вас творится? Даня заперся в комнате и, судя по голосу, рыдает.
    Ответить

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

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8