C #: должно ли значение по умолчанию для перечисления быть None или Unknown?

Допустим, у вас есть перечисление, представляющее код ошибки. Будет несколько кодов, каждый со своим собственным базовым значением int; однако значение перечисления, которое принимает значение по умолчанию 0, кажется, что его следует тщательно рассмотреть.

В случае перечисления кода ошибки я могу придумать два специальных значения: None (для случаев, когда нет ошибки) и Unknown (для случаев, когда существующий код ошибки не подходит, или, возможно, даже когда состояние ошибки не может быть обнаруженным).

Кажется, что одно из этих значений должно получить 0, тогда как другое, вероятно, получит что-то еще, например -1. Что более уместно: установить значение «Нет» на 0 или значение «Неизвестно» на 0?

public enum ErrorCode
{
    None = -1,
    Unknown = 0,
    InsufficientPermissions,
    ConnectivityError,
    ...
}

public enum ErrorCode
{
    Unknown = -1,
    None = 0,
    InsufficientPermissions,
    ConnectivityError,
    ...
}

Мой инстинкт подсказывает мне, что по умолчанию должно быть Неизвестно, но мне любопытно, сделал ли кто-нибудь это иначе.


person bwerks    schedule 01.07.2010    source источник


Ответы (9)


Определенно не лучшая практика. Но если другого пути нет ... то я бы вообще выбрал второй вариант:

public enum ErrorCode 
{ 
    Unknown = -1, 
    None = 0, 
    InsufficientPermissions, 
    ConnectivityError, 
    ... 
} 

0 соответствует условию «Нет ошибок», а -1 подходит с пониманием того, что существует некоторая ошибка (которая может быть неизвестной).

person prabhats.net    schedule 01.07.2010
comment
Спасибо, что ответили на вопрос условно, и не отвлекаетесь на то, насколько это дерьмо. - person bwerks; 01.07.2010

Поскольку вы помечаете свой вопрос рекомендациями: не используйте коды ошибок, если вы можете использовать исключения.

person Pontus Gagge    schedule 01.07.2010
comment
Еще одно сообщение, связанное с этой проблемой: Исключения или коды ошибок - person Karmastan; 01.07.2010
comment
Вы можете использовать коды исключений и ошибок, чтобы устранить неоднозначность и предоставить средство для ссылки на конкретную ошибку в документации. - person João Angelo; 01.07.2010
comment
Ошибка не обязательно является исключительной ситуацией. Код ошибки может быть возвращаемым значением метода Validate. - person Jonathan Allen; 01.07.2010
comment
Кто сказал, что он не будет использовать коды ошибок в исключительных случаях? - person spoulson; 01.07.2010
comment
@spoulson, если он это сделает, то загонит будущих разработчиков в угол с точки зрения возможности поймать самый конкретный тип исключения. Стоимость создания InsufficientPermissionsException и ConnectivitiyErorrException и т. Д. Не является чрезмерной. - person Michael Meadows; 01.07.2010
comment
@Michael, я бы действительно не рекомендовал этого делать. Представьте, сколько классов исключений вам придется иметь, если вы создадите отдельный для каждого исключения SQL, Win32 или COM. Кроме того, вы можете использовать обработчики отфильтрованных исключений Catch ex as ComExcetion Where ex.ErrorCode = 123456. - person Jonathan Allen; 01.07.2010
comment
Практическое соглашение по этой кодовой базе заключается в том, что коды ошибок используются для известных сбоев, а исключения используются только для ситуаций, когда обработка не может продолжаться. Валидация - прекрасный пример. К тому же вопрос не имел ничего общего с исключениями. - person bwerks; 01.07.2010
comment
Итак, @bwerks, может, тебе стоит поменять метку на «наименее плохая практика» ...? - person Pontus Gagge; 02.07.2010
comment
Вопрос касается объявления перечислений, а не способов их использования. Приведенный мной пример анекдотичен. Если вы не предполагаете, что использование перечислений для каких-либо целей всегда является плохой практикой, я думаю, что с тегом все в порядке. - person bwerks; 02.07.2010

На мой взгляд, оба Unknown или None означают одно и то же в контексте перечисления ErrorCode. Я считаю, что если я проверяю код ошибки, то это потому, что у меня уже есть ошибка.

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

person João Angelo    schedule 01.07.2010
comment
К сожалению, этот призыв не до меня; однако, учитывая, что эти значения будут сохраняться в базе данных, имеет смысл включить Unknown как средство преобразования в NULL в базе данных. Хотя я полагаю, что в этом случае будет работать и использование nullable. - person bwerks; 01.07.2010
comment
Почему это не ваше дело? Как вы можете изменить значения перечисления, если у вас нет доступа к коду, который перехватывает исключения и возвращает коды ошибок (в частности, для неизвестных ошибок)? Если это политическая проблема, пожалуйста, из любви к справедливости, правде и экономии денег укажите власть имущих на этот и связанные с ним сообщения SO, чтобы они увидели, что большинство профессиональных разработчиков программного обеспечения категорически против возврата кодов ошибок! - person jyoungdev; 02.07.2010

Думаю, я не согласен со всеми по этому поводу.

Нет ничего плохого в кодах ошибок, когда они используются в смысле «каково текущее состояние этой функции».

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

Для меня я бы использовал None как 0 по умолчанию. Я не вижу причин делать Неизвестное отрицательным. Неизвестно - это совершенно нормальное состояние ошибки. Вы можете просто поставить его в конец списка. На практике я сделал

public enum ErrorCode
{
    None = 0,
    InsufficientPermissions,
    ConnectivityError,
    ...
    Unknown,
}

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

person Detmar    schedule 01.07.2010

Во-первых, у вас не должно быть кода ошибки None. Вместо этого назовите это «Успех».

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

if (errorCode != Success)

или они используют сокращение

if (errorCode != 0)

Вот и все. Ваш Успешный код равен 0, у вас нет кода Нет, а Неизвестным может быть все, что вы хотите.

person Jonathan Allen    schedule 01.07.2010

Зачем вообще возвращать значение ErrorCode, если ошибки нет?

В этом нет большого смысла. Удаление этого решит вашу проблему. Вы можете просто поставить 0 для Unkown:

public enum ErrorCode
{
    Unkown = 0,
    InsufficientPermissions,
    ConnectivityError
}

ОБНОВЛЕНИЕ

Ваш комментарий немного пугающий. У вас никогда не должно быть метода, возвращающего тип ErrorCode. Это очень плохая практика. Поскольку ErrorCodes следует возвращать только в исключительных случаях, рекомендуется генерировать исключения.

Если вы хотите, вы можете иметь поле в вашем настраиваемом исключении, которое содержит значение ErrorCode.

person Justin Niessner    schedule 01.07.2010
comment
Если подпись вашей функции public ErrorCode DoFoo(), что вы вернете, когда функция завершится успешно? - person Karmastan; 01.07.2010
comment
@Karmastan - у меня никогда не было бы метода, возвращающего ErrorCode. У меня было бы настраиваемое исключение, которое генерируется и содержит внутри него код ошибки. - person Justin Niessner; 01.07.2010
comment
Платформа использует коды ошибок, если вы знаете, что при нормальных обстоятельствах операция может завершиться ошибкой. Например, Int32.TryParse возвращает значение вместо того, чтобы генерировать исключение. Я также использую коды ошибок в методах проверки, где я ожидаю проблемы. В этом случае наличие ошибки не является исключением, это предполагаемое использование. - person Jonathan Allen; 01.07.2010
comment
Переименуйте перечисление во что-нибудь менее вводящее в заблуждение для пользовательского кода. Вы возвращаете статус, а не код ошибки. Затем удалите None из уравнения, потому что такого нет. - person spoulson; 01.07.2010

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

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

На самом деле я бы посоветовал изменить «Нет» на «Успех», как было предложено, но чтобы вы сделали «Успех» значением 1 и отсюда увеличивали все остальные ошибки. Причина этого заключается в том, что в большинстве приложений баз данных столбцы состояния не допускают значения NULL и обычно отслеживаются как целые числа. Это может привести к проблемам, если вы используете статус успеха 0, потому что по умолчанию целочисленные столбцы, не допускающие значения NULL, будут установлены в 0, если пользователь явно не вставляет что-то еще. Это приведет к ложному коду статуса / ошибки и вызовет проблемы в будущем вашего приложения. Не только то, что целочисленные переменные автоматически инициализируются значением 0 по умолчанию в C #, что приводит к автоматическому успеху, но и перечисления, если вы не устанавливаете начальное значение, а это не то, что вам нужно.

Также с точки зрения кодирования 1 также может означать истину, и поэтому это хорошо сочетается с успехом. Однако есть ситуации, когда это может быть не так. В системах на основе Unix возврат 0 означает успех / отсутствие ошибок, а в других языках, таких как C ++, возврат 0 является стандартным для основной функции, также указывая на успешное выполнение основной функции.

person Benji Vesterby    schedule 12.04.2013

Код ошибки плохой. Исключения хорошие. Но чтобы ответить на заданный вопрос:

Если ваше перечисление имеет значение «Неизвестно», оно должно быть значением по умолчанию.

person Joel Coehoorn    schedule 01.07.2010
comment
Во-первых, коды ошибок часто сочетаются с исключениями. Во-вторых, вежливо предлагать метод проверки, чтобы пользователь мог видеть, какие ошибки могут возникнуть, если он предпримет какое-либо действие. Помните, что исключения требуют больших затрат как процессорного времени, так и строк кода. - person Jonathan Allen; 01.07.2010
comment
@Jonathan, я согласен, за исключением того, что с проверкой вы действительно назовете это ErrorCodes? Кроме того, обычно проверка происходит на достаточно высоком уровне, чтобы вы могли использовать константы (или локализованные строки) для представления ошибки проверки. Если он достаточно глубоко проникает в ваш фреймворк, чтобы потребовать код, тогда это действительно исключительное условие. - person Michael Meadows; 01.07.2010
comment
Раньше я возвращал строки, но это сильно усложняло поиск и фильтрацию. Итак, теперь у нас есть код ошибки для каждого сценария в дополнение к строкам. Это также не ошибки приложения, это проблемы с данными, которые бизнес-пользователю необходимо изучить и исправить вручную. - person Jonathan Allen; 01.07.2010

То же самое со всеми ответами «Я бы не стал этого делать», но если вы настаиваете, вот мои 0,02 доллара.

ErrorCodes.None не имеет смысла, поскольку ошибки нет. ErrorCodes.Unknown бесполезен. Попробуйте вернуть код ошибки, допускающий значение NULL:

public ErrorCode? DoFoo()

Теперь вы можете проверить значение null

var error = DoFoo();
if (error != null)
    // react

По-прежнему плохо, но, по крайней мере, позволяет не возвращать код ошибки, если ошибки нет.

person Michael Meadows    schedule 01.07.2010
comment
Я не согласен с этим. Во-первых, FxCop сообщает нам, что у нас всегда должно быть значение по умолчанию, когда перечисление не было явно установлено. Итак, наличие Unknown или None определенно уместно. Во-вторых, используя Nullable ‹T› или? синтаксис подрывает основную идею перечисления, заставляя потребителя выбрать ЧТО-ТО! - person Robert Seder; 01.07.2010