В приложении командной строки C#, которое я пишу, некоторые параметры имеют «да» и «нет» в качестве возможных значений.
Я сохраняю их ввод, используя тип Enum, показанный ниже.
enum YesNo
{
Yes,
No
}
Что нормально - код работает. Нет проблем.
ПРИМЕЧАНИЕ: Да, я мог бы сохранить их как bool (так оно и работало раньше). Мой дизайнерский выбор состоит в том, чтобы четко указать выбор «Да / Нет», сделанный пользователем, потому что он увидит это напечатанным в другом контексте, и я хотел бы, чтобы было более очевидным, какой был выбор.
Я задал этот вопрос относительно рано в жизни StackOverflow. Это не был фальшивый вопрос - у меня действительно была такая ситуация. Я просто подумал, что было бы неплохо использовать его, чтобы посмотреть, что сделает сообщество. Поскольку это так, я допускаю несколько странный вопрос.
Во-первых, спасибо всем, кто уделил время ответам. Я пытаюсь отплатить за это вдумчивым выводом.
Комментарии к ответам
переход на bool. Я понимаю вашу мотивацию, но чувствую, что мне нужно указать, что выбор двоичный (и под этим я подразумеваю выбор между любыми двумя значениями - живым / мертвым, женатым / незамужним и т. д.) - это не то же самое, что выбор логический между правда и ложь. Мы, программисты, находим переключение между да / нет и истиной / ложью легко - достаточно справедливо. Если бы я выбрал в этом случае, например, «Демократ» или «Репликация» (я знаю, надуманный пример), тогда вы можете увидеть возможность путаницы или, по крайней мере, неловкости. Я действительно думаю, что в этом случае допустим вариант bool, но меньше так и в других двоичных вариантах.
локализация - отличная точка. В моем конкретном случае это не имело значения - это не было и не будет локализовано, но для других ситуаций это нужно учитывать.
более трех вариантов - Фактически, позже мне пришлось добавить третье значение, вызываемое для представления действительного (в моем приложении) состояния пользователя, в частности нет, делающего выбор.
Было много хороших комментариев, всем спасибо!
Собственно что-то подобное может происходить и по другим параметрам. Примеры: Да, Нет, Авто Да, Нет, Наследовать.
Возникает вопрос: какое было бы может быть хорошим названием для перечисления, содержащего {Yes, No, Auto} или {Yes, No, Inherit} и т. д. Я на самом деле использовал первое и обнаружил, что у меня нет хорошей альтернативы имя YesNoAuto, но я ненавидел его и чувствовал себя немного глупее каждый раз, когда мне приходилось его использовать.
P.S. Я использовал Auto = -1, No = 0 и Yes = 1. Так что, возможно, мне следовало назвать это AutoNoYes. :)
Пожалуйста, не делай этого с собой. Придерживайтесь bool





EUserAction?
Вы описали это как некое действие пользователя. Однако вы могли бы быть более конкретными. Название позволяет сделать дополнительный выбор в будущем. (Имя должно соответствовать выбору, а не его)
Однако для вашего другого тонкого вопроса:
because they will see this printed in other contexts and I'd like it to be more obvious what the choice was.
на самом деле не должно иметь значения, что видит пользователь. Модель данных может сильно отличаться от той, которую вы представляете пользователю. Достаточно было бы bool. Возможны ли дополнительные действия в будущем?
См. Комментарий Буркхарда. Я также утверждаю, что «действие пользователя» очень расплывчато - учитывая имя просто, какие значения вы ожидаете увидеть?
Это связано с дизайном. Посмотрите, как он это описал :) Кроме того, название позволяет сделать некоторые дополнительные варианты выбора в будущем. Имя должно соответствовать выбору, а не его.
Муги - я понимаю, к чему вы клоните. Хотя я не уверен, что это помогает мне в этом случае (по разным причинам, связанным со спецификой приложения), я думаю, что ваше предложение имеет смысл в долгосрочной перспективе для моего кода.
@moogs: Мне все еще кажется неправильным. UserChoice был бы лучше, чем UserAction (они не предприняли никаких действий), но это все еще не говорит само за себя - он не говорит, какой выбор своего рода они сделали. Если вы не можете угадать тип значений для перечисления на основе имени, я бы сказал, что что-то не так.
@ JonSkeet - если бы он был более конкретным в отношении того, что это за действие (например, SaveDocument или KillProcess), я мог бы дать более значимое имя. наменлос?
@moogs: Нет, потому что тип ответа (да или нет) не обязательно зависит от типа вопроса. Даже BooleanChoice более нагляден, чем UserAction, но я не думаю, что он все равно должен использовать enum ...
(Кстати, я до сих пор не могу понять, откуда у вас слово «действие» - я не вижу его в вопросе или в правках к вопросу. Что мне не хватает?)
@jon skeet - ах, извините за мод. Он описал это как «выбор, сделанный пользователем». Он хранит что-то / ответ, уже сделанный пользователем. Перечитывая комментарии, возможно, мы идем той же дорогой. UserChoice и UserAction для меня непонятны. Он должен дать более подробную информацию об использовании.
Или просто используйте логическое значение.
Это нарушает обычные соглашения об именах .NET. «E» обычно не используется в качестве префикса перечисления.
Разве это не перечисление? перечислить Да Нет {Да, Нет}
@ Буркхард: Да, это перечисление. Нет, это не значит, что перед ним должна стоять буква "E". Также не должно быть множественного числа, поскольку это не перечисление флагов.
Гм, не уверен, что означает ваш последний комментарий, но я хочу сказать, что перечисления в .NET не обычно имеют префикс E, тогда как все ваши предложения.
К сожалению, сейчас я не могу снять свой голос против. Считайте, что он удалил в духе :)
Я был бы смущен, если бы увидел, что перечисление используется для логического значения. Вы говорите, что:
NOTE: Yes, I could store these as bool (that's how it used to work). My design choice is to be explicit about the Yes/No choice made by the user because they will see this
printed in other contents and I'd like it to be more obvious what the choice was.
Я не понимаю, почему «Да» или «Нет» более «явное», чем истинное или ложное.
Пользователи cmdline-app не будут так разбираться в технических вопросах - я бы предпочел, чтобы они видели что-то, что отражает то, что они набирают. Я позабочусь о внутреннем отображении на bool. Использование здесь перечисления - это для меня простой способ добиться правильного отображения вывода для конечного пользователя без особых усилий с моей стороны.
Управление данными в программе и их визуализация для пользователя - это разные вещи. Вы можете использовать логическое значение и просто переводить его пользователям при визуализации. Поскольку ваш enum не является многоязычным, это также дает вам больше возможностей.
ResponseEnum, EResponse или UserResponse в зависимости от ваших соглашений.
Я бы не стал ограничивать себя только «Да» или «Нет», так как в будущем вы, возможно, захотите добавить функциональность, которая также требует ответа «Не уверен».
Вы говорите, что не хотите использовать bool, потому что он будет распечатан, чтобы пользователь мог видеть среди прочего содержимого. Это говорит о том, что проблема не в место хранения, а в отображать. Обязательно представьте истину / ложь как Да / Нет, но нет необходимости создавать для него совершенно новый тип IMO.
Обновлено: в дополнение к предложению вам не использовать перечисление в первую очередь, я настоятельно рекомендую, если вы делать используете перечисление, вы измените порядок или используйте явные значения. Если Yes = 0, No = 1 будет действительно запутанным, если вы когда-нибудь увидите значения как целые числа.
Ваше наблюдение верно - то, что делает для меня enum, просто упрощает очень крошечную часть генерации вывода. Я мог бы легко создать функцию с именем bool_to_yes_no (), но я подумал, что будет проще написать Console.Writeline ("paramfoo: {0}", paramfoo)
Я подозреваю, что если вы ограничите свой механизм хранения, чтобы он всегда был непосредственно презентабельным для пользователей, вы собираетесь связать себя узлами в другом месте. Я бы просто перевел его там, где это нужно. В качестве бонуса то на i18n проще ...
bool answer = true; string.Format («Пользователь вводит {0}», ответ? «Да»: «Нет»);
Я думаю, что YesNo в порядке. Рассмотрим такие вещи, как «MB_OK» и «MB_YESNO» ... Я знаю, что это не тип, но все, что говорит само за себя, должно быть в порядке.
Есть ли возможность иметь вариант, отличный от да / нет. Для двух вариантов используйте логическое значение. Попробуйте изменить только область отображения.
Я прочитал ваше обновленное объяснение, но все же считаю, что это плохой выбор. Логические значения существуют как раз для этой цели. ваш отвечает за то, чтобы, когда «они увидят это напечатанным в другом содержимом», выводился соответствующий текст. Это может быть так просто:
Console.WriteLine (_ ("Использование Foo:") + (useFoo? _ ("Да"): _ ("Нет")));
при этом все еще имея полную поддержку локализации. useFoo - это, конечно, параметр, сообщающий функции, использует ли она foo. :)
_ - это сокращение от функции gettext (http://www.gnu.org/software/gettext/), которая доступна для C# (http://www.gnu.org/software/automake/manual/gettext/C_0023.html).
(Юмор - пожалуйста не воспринимай это всерьез ...)
Я удивлен, что это еще никто не предложил:
public enum UserWtf
{
No,
Yes,
FileNotFound
}
Только Паула воспользуется бриллиантом!
Я не вижу смысла в этом перечислении, если не было других значений, кроме Yes и No. Это просто bool. И создание перечисления только для того, чтобы не вводить да или нет, кажется глупым.
Я бы назвал это:
enum Boolean
{
Yes,
No
}
Нет, подождите, уже есть встроенный логический тип, который вы можете использовать.
Если ваша единственная причина для использования перечисления здесь заключается в том, что существует удобное преобразование в / из строки, которую вы хотите показать пользователю, тогда вы будете очень сильно укушены, поскольку вы будете делать более сложные вещи. Отделение модели от вида сослужит вам хорошую службу. Прочтите о шаблонах MVC и / или MVVM.
Я также мог бы предположить, что здесь может быть достаточно простого логического значения с некоторыми настраиваемыми атрибутами, которые определяют отображаемые строки для использования вместо «истина» и «ложь». Затем вы можете написать свои собственные методы передачи и из строки, которые будут искать ваши настраиваемые атрибуты.
Я бы вообще не использовал перечисление, просто развернул свой собственный преобразователь типов и использовал логические значения.
Я предполагаю, что есть проблема с отображением значений типа bool. Лучше создать простую оболочку, которая хранит логические значения, позволяя отображать их как Да / Нет или Истина / Ложь.
Я бы посоветовал вам использовать имя, которое указывает значение, для которого установлено значение «Да» или «Нет».
НАПРИМЕР.
public enum Married
{
YES,
NO
}
Было много хороших ответов, но этот прямо ответил на вопрос.
Используйте bool в сочетании с bool.TrueString и bool.FalseString для целей отображения.
Когда мне нужно что-то подобное, я использую слово Flag, как в Flag.Yes, MarriedFlag.No и т. д.
Пример того, когда это полезно: вы знаете, что сегодня есть только значения «Да» и «Нет», но подозреваете, что в будущем могут появиться дополнительные значения (например, «Может быть»).
Я использую OptionalBinaryFilter для:
Да нет все
Но если у вас есть только Yes и No, кажется более подходящим использование Boolean в члене.
Хммм, может быть, в будущем добавят "IDontKnow"? ржу не могу