Должен ли я использовать исключения в C # для обеспечения совместимости базового класса? - PullRequest
1 голос
/ 11 июня 2009

С одной стороны, мне сказали, что исключения в C # «дороги», но с другой, я застрял на том, как это реализовать.

Моя проблема заключается в следующем: я делаю Stream производный, который обертывает NetworkStream. Теперь проблема, с которой я сталкиваюсь, такова: Read(byte[] buffer, int offset, int count). Из Stream документов для функции:

Возвращает:

... или ноль (0), если достигнут конец потока.

Проблема в том, что в протоколе, который я реализую, удаленная сторона может отправлять токен "конца записи" или токен "пожалуйста, ответьте". Очевидно, что если это происходит в начале Read(), это вызывает проблемы, так как мне нужно вернуться из функции, и я ничего не читал, поэтому мне нужно вернуть 0, что означает, что поток завершен, но это не ... EndOfRecordException или подобное оправдано в этом случае? И в этом случае, если он будет брошен всегда, когда встречается этот токен (в начале вызова Read() и убедитесь, что эти токены всегда в начале, возвращаясь рано), так что есть некоторый образец того, как токены должны быть обработаны.

Редактировать: Эти токены обычно стоят 3-10 раз в секунду. Самое большее, я не ожидал бы больше 25 секунд в секунду.

Ответы [ 5 ]

9 голосов
/ 11 июня 2009

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

Мне кажется, что вы на самом деле не реализуете a Stream - вы инкапсулируете поток в «читатель». Я мог бы быть склонен написать класс считывателя для протокола с подходящими методами для определения конца записи или Try... методами для получения данных или возврата false.

4 голосов
/ 11 июня 2009

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

В Java были случаи, подобные ZipInputStream, которые оказывались очень запутанными, когда в одном InputStream фактически есть несколько потоков, и вы можете пропустить их между собой. Такие API были ужасно использовать в моем опыте. Предоставление отдельного класса для реализации «разделения записей», которое может обеспечить поток для данных в пределах , и запись звучит для меня чище. Тогда каждый поток может вести себя согласованно с обычными потоками. Нет необходимости в новых исключениях.

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

1 голос
/ 11 июня 2009

Я считаю, что класс Stream должен иметь дело только с проблемами потоковой передачи и придерживаться Stream семантического контракта. Вся логика более высокого уровня (интерпретирующая токены EOF и EOR) должна быть помещена в некоторый другой класс.

1 голос
/ 11 июня 2009

Это не так уж важно для производительности, но все же ... Исключения предназначены для, ну, в общем, исключений. Ситуации, которые являются "необычными". Если именно так ведет себя базовый поток, то ваш поток должен быть в состоянии справиться с этим. Если это возможно, он должен справиться с этим самостоятельно. Если нет, пользователь может установить обратный вызов или что-то, что будет вызываться при получении токена «пожалуйста, ответьте».

0 голосов
/ 11 июня 2009

Может быть, вы можете создать перечисление, которое вы возвращаете, это перечисление может содержать элементы для EndOfRecord, EndOfStream, ReadOk или чего угодно.

Фактические считанные данные могут быть переданы как выходной параметр.

...