У меня есть следующее перечисление:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
Проблема, однако, в том, что мне нужно слово «FORMS», когда я спрашиваю AuthenticationMethod.FORMS, а не id 1.
Я нашел следующее решение этой проблемы ( ссылка ):
Сначала мне нужно создать собственный атрибут с именем «StringValue»:
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Затем я могу добавить этот атрибут в мой перечислитель:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
И, конечно, мне нужно что-то, чтобы получить это StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Хорошо, теперь у меня есть инструменты для получения строкового значения для перечислителя. Затем я могу использовать это так:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Хорошо, теперь все это работает как шарм, но я считаю, что это большая работа. Мне было интересно, есть ли лучшее решение для этого.
Я также попробовал кое-что со словарем и статическими свойствами, но это было не лучше.
this
передEnum
вашим статическим методом. Тогда вы можете сделатьAuthenticationMethod.Forms.GetStringValue();
Ответы:
Попробуйте тип-безопасный-enum шаблон.
Обновление явного (или неявного) преобразования типа может быть выполнено
добавление статического поля с отображением
заполняя это отображение в конструкторе экземпляра
и добавление пользовательского оператора преобразования типов
источник
Используйте метод
как в (Предположим
Shipper
, это определенный Enum)Есть множество других статических методов в классе Enum, которые тоже стоит исследовать ...
источник
Вы можете ссылаться на имя, а не на значение, используя ToString ()
Документация здесь:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
... и если вы называете свои перечисления в Pascal Case (как я, например ThisIsMyEnumValue = 1 и т. д.), вы можете использовать очень простое регулярное выражение для печати дружественной формы:
который можно легко вызвать из любой строки:
Выходы:
Это избавляет от необходимости обходить дома, создавая собственные атрибуты и прикрепляя их к своим перечислениям или используя таблицы поиска, чтобы объединить значение перечисления с дружественной строкой и, что лучше всего, оно самоуправляется и может использоваться для любой строки Pascal Case, которая бесконечно более многоразового использования. Конечно, это не позволяет вам иметь другой дружественное имя, от вашего enum, которое предоставляет ваше решение.
Мне нравится ваше оригинальное решение, хотя для более сложных сценариев, хотя. Вы можете продвинуть свое решение на один шаг вперед и сделать свой GetStringValue методом расширения вашего перечисления, и тогда вам не нужно будет ссылаться на него как StringEnum.GetStringValue ...
Вы можете легко получить к нему доступ прямо из вашего экземпляра enum:
источник
"(?!^)([^A-Z])([A-Z])", "$1 $2"
, ТакHereIsATEST
становитсяHere Is ATEST
.К сожалению, размышления о получении атрибутов в перечислениях довольно медленные:
Посмотрите на этот вопрос: Кто-нибудь знает быстрый способ получить пользовательские атрибуты для значения перечисления?
.ToString()
Довольно медленно на перечислениях тоже.Вы можете написать методы расширения для перечислений:
Это не очень хорошо, но будет быстрым и не потребует отражения для атрибутов или имени поля.
Обновление C # 6
Если вы можете использовать C # 6, тогда новый
nameof
оператор работает для перечислений, поэтомуnameof(MyEnum.WINDOWSAUTHENTICATION)
он будет преобразован"WINDOWSAUTHENTICATION"
во время компиляции , что сделает его самым быстрым способом получения имен перечислений.Обратите внимание, что это преобразует явное перечисление во встроенную константу, поэтому оно не работает для перечислений, которые есть в переменной. Так:
Но...
источник
Я использую метод расширения:
Теперь украсить с
enum
помощью:Когда вы звоните
AuthenticationMethod.FORMS.ToDescription()
вы получите"FORMS"
.источник
using System.ComponentModel;
, что этот метод работает, только если вы хотите, чтобы значение String совпадало с именем Enum. ОП хотел другое значение.AuthenticationMethod.FORMS.ToDescription()
?Просто используйте
ToString()
методДля ссылки на строку
Tomato
просто используйтеисточник
.ToString()
значение, отличное от того, которое вам нужно.any fruit = any.Tomato;
string tomato = fruit.ToString();
Очень простое решение для этого с .Net 4.0 и выше. Никакого другого кода не требуется.
Чтобы получить строку о просто использовать:
или
Значение будет «Активно» или «Архивировано».
Чтобы увидеть различные строковые форматы ("f" сверху) при вызове,
Enum.ToString
посмотрите эту страницу Строки формата перечисленияисточник
Я использую атрибут Description из пространства имен System.ComponentModel. Просто украсьте перечисление, а затем используйте этот код для его получения:
Например:
Этот код прекрасно обслуживает перечисления, в которых вам не нужно «дружественное имя», и возвращает только .ToString () перечисления.
источник
Мне очень нравится ответ Якуба Штурца, но его недостаток в том, что вы не можете использовать его с оператором switch-case. Вот слегка измененная версия его ответа, которую можно использовать с оператором switch:
Таким образом, вы получите все преимущества ответа Якуба Штурца, плюс мы можем использовать его с оператором switch следующим образом:
источник
public static int nextAvailable { get; private set; }
тогда в конструктореthis.Value = nextAvailable++;
=
оператора, чтобы позволить переключателю работать? Я сделал это в VB и теперь могу использовать это вselect case
заявлении.Я использую комбинацию нескольких предложений, приведенных выше, в сочетании с некоторым кэшированием. Теперь я получил идею из некоторого кода, который нашел где-то в сети, но я не могу ни вспомнить, где я его получил, ни найти его. Так что, если кто-нибудь когда-нибудь найдет что-то похожее, пожалуйста, прокомментируйте с атрибуцией.
В любом случае, использование включает преобразователи типов, поэтому, если вы привязываетесь к пользовательскому интерфейсу, он «просто работает». Вы можете расширить шаблон Jakub для быстрого поиска кода путем инициализации из преобразователя типов в статические методы.
Базовое использование будет выглядеть так
Ниже приведен код для пользовательского преобразователя типов enum:
}
источник
В своем вопросе вы никогда не говорили, что вам действительно нужно числовое значение перечисления в любом месте.
Если вы не нуждаетесь и просто нуждаетесь в перечислении типа string (которое не является целочисленным типом, поэтому не может быть основой перечисления), вот способ:
вы можете использовать тот же синтаксис, что и enum, чтобы ссылаться на него
Это будет немного медленнее, чем с числовыми значениями (сравнение строк вместо чисел), но, с другой стороны, он не использует отражение (медленно) для доступа к строке.
источник
Как я решил это как метод расширения:
Enum:
Использование (где o.OrderType - свойство с тем же именем, что и enum):
Который дает мне строку «Новая карта» или «Перезагрузить» вместо фактического значения перечисления NewCard и Refill.
источник
Обновление: посещение этой страницы, 8 лет спустя, после того, как долго не трогал C #, похоже, мой ответ больше не является лучшим решением. Мне очень нравится конвертер, связанный с атрибутами-функциями.
Если вы читаете это, пожалуйста, не забудьте проверить другие ответы.
(подсказка: они выше этого)
Как и большинству из вас, мне очень понравился выбранный ответ Якуба Штурца , но я также очень ненавижу копировать-вставлять код и стараюсь делать это как можно меньше.
Поэтому я решил, что мне нужен класс EnumBase, от которого большая часть функциональных возможностей унаследована / встроена, поэтому мне пришлось сосредоточиться на содержании, а не на поведении.
Основная проблема с этим подходом основана на том факте, что, хотя значения Enum являются типобезопасными экземплярами, взаимодействие происходит с статической реализацией типа Enum Class. Так что с небольшой помощью магии дженериков, я думаю, я наконец-то получил правильный микс. Надеюсь, кто-то найдет это столь же полезным, как и я.
Я начну с примера Якуба, но с использованием наследования и обобщений:
А вот и базовый класс:
источник
Я согласен с Китом, но не могу голосовать (пока).
Я использую статический метод и оператор swith, чтобы вернуть именно то, что я хочу. В базе данных я храню tinyint, и мой код использует только фактическое перечисление, поэтому строки соответствуют требованиям пользовательского интерфейса. После многочисленных испытаний это привело к лучшей производительности и большей степени контроля над выходом.
Однако, по некоторым данным, это приводит к возможному кошмару обслуживания и некоторому запаху кода. Я стараюсь следить за длинными и многочисленными перечислениями или за часто меняющимися. В противном случае, это было отличное решение для меня.
источник
Если вы пришли сюда в поисках простого «Enum», но значения которого являются строками, а не целыми, вот самое простое решение:
Реализация:
источник
static readonly
.Когда я сталкиваюсь с этой проблемой, я сначала пытаюсь найти ответы на несколько вопросов:
Простейший способ сделать это с помощью
Enum.GetValue
(и поддерживать использование кругового отключенияEnum.Parse
). ТакжеTypeConverter
, как предполагает Стив Митчам, часто стоит создать поддержку связывания пользовательского интерфейса. (Не нужно строитьTypeConverter
когда вы используете листы свойств, что является одной из приятных вещей в листах свойств. Хотя лорд знает, что у них есть свои проблемы.)В общем, если ответы на приведенные выше вопросы показывают, что это не сработает, мой следующий шаг - создать и заполнить статический объект
Dictionary<MyEnum, string>
, или, возможно, aDictionary<Type, Dictionary<int, string>>
. Я склонен пропустить промежуточный шаг decorate-the-code-with-attribute, потому что следующим шагом обычно является необходимость изменения дружественных значений после развертывания (часто, но не всегда, из-за локализации).источник
Я хотел опубликовать это как комментарий к сообщению, указанному ниже, но не смог, потому что у меня недостаточно представителей - поэтому, пожалуйста, не голосуйте. Код содержал ошибку, и я хотел указать на это людям, которые пытаются использовать это решение:
должно быть
Brillant!
источник
Мой вариант
Код выглядит немного некрасиво, но использование этой структуры довольно показательно.
Кроме того, я думаю, что если потребуется много таких перечислений, можно использовать генерацию кода (например, T4).
источник
Опция 1:
а потом
Вариант 2:
источник
Если вы думаете о проблеме, которую мы пытаемся решить, это вовсе не то, что нам нужно. Нам нужен объект, который позволяет определенному количеству значений быть связанным друг с другом; другими словами, чтобы определить класс.
Типичный для enum шаблон Jakub Šturc - лучший вариант, который я здесь вижу.
Посмотри на это:
источник
для меня прагматический подход - класс внутри класса, пример:
источник
Я создал базовый класс для создания строковых перечислений в .NET. Это всего лишь один файл C #, который вы можете скопировать и вставить в свои проекты или установить через пакет NuGet с именем StringEnum . GitHub Repo
<completitionlist>
. (Работает как в C #, так и в VB)Переустановленное:
.Net Standard 1.0
что он работает на.Net Core
> = 1.0,.Net Framework
> = 4.5,Mono
> = 4.6 и т. Д.источник
Вот еще один способ выполнить задачу связывания строк с перечислениями:
Этот метод называется так:
Вы можете группировать связанные перечисления в их собственной структуре. Поскольку этот метод использует тип enum, вы можете использовать Intellisense для отображения списка перечислений при создании
GetString()
вызова.При желании вы можете использовать оператор new в
DATABASE
структуре. Неиспользование означает, что строкиList
не выделяются до первогоGetString()
вызова.источник
Здесь много хороших ответов, но в моем случае не удалось найти то, что я хотел, из «перечисления строк», которое было:
1,2 и 4 могут быть решены с помощью C # Typedef строки (поскольку строки можно переключать в c #)
3 может быть решена с помощью статических константных строк. Так что, если у вас есть те же потребности, это самый простой подход:
Это позволяет, например:
а также
Где CreateType может быть вызван со строкой или типом. Однако недостатком является то, что любая строка автоматически является допустимым перечислением , это можно изменить, но тогда это потребует какой-то функции инициализации ... или, возможно, сделать их явным приведением внутреннего?
Теперь, если значение int было для вас важно (возможно, для скорости сравнения), вы можете использовать некоторые идеи из фантастического ответа Якуба Штурца и сделать что-то немного сумасшедшее, это мой удар в этом:
но, конечно, "Типы Боб = 4;" было бы бессмысленно, если бы вы сначала не инициализировали их, что бы как-то победило ...
Но в теории TypeA == TypeB будет быстрее ...
источник
Если я вас правильно понимаю, вы можете просто использовать .ToString () для получения имени перечисления из значения (при условии, что оно уже приведено как Enum); Если у вас был голый int (скажем, из базы данных или чего-то еще), вы можете сначала привести его к перечислению. Оба метода ниже приведут вас к имени enum.
Имейте в виду, однако, что во втором методе предполагается, что вы используете целые числа, и ваш индекс основан на 1 (а не на 0). Функция GetNames также довольно тяжелая для сравнения: вы генерируете целый массив каждый раз, когда он вызывается. Как вы можете видеть в первом методе, .ToString () фактически вызывается неявно. Обе они уже упоминались в ответах, конечно, я просто пытаюсь уточнить различия между ними.
источник
старый пост, но ...
Ответ на этот вопрос может быть очень простым. Используйте Enum.ToString () функция
Существует 6 перегрузок этой функции, вы можете использовать Enum.Tostring ("F") или Enum.ToString (), чтобы вернуть строковое значение. Не нужно беспокоиться ни о чем другом. Вот рабочая демка
Обратите внимание, что это решение может работать не для всех компиляторов ( эта демонстрация не работает должным образом ), но, по крайней мере, оно работает для последнего компилятора.
источник
на основе MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
str будет именами полей
источник
Что ж, после прочтения всего вышесказанного я чувствую, что ребята слишком усложнили вопрос преобразования счетчиков в строки. Мне понравилась идея иметь атрибуты над перечисляемыми полями, но я думаю, что атрибуты в основном используются для метаданных, но в вашем случае я думаю, что все, что вам нужно, это какая-то локализация.
Теперь, если мы попытаемся вызвать вышеуказанный метод, мы можем вызвать его таким образом
Все, что вам нужно сделать, это просто создать файл ресурсов, содержащий все значения перечислителя и соответствующие строки
Что на самом деле очень приятно, так это то, что будет очень полезно, если вам нужно локализовать ваше приложение, поскольку все, что вам нужно сделать, это просто создать еще один файл ресурсов с вашим новым языком! и во-ля!
источник
Когда я нахожусь в такой ситуации, я предлагаю решение ниже.
И как потребительский класс вы могли бы иметь
И используя двунаправленный словарь: на основе этого ( https://stackoverflow.com/a/255638/986160 ), предполагая, что ключи будут связаны с отдельными значениями в словаре и аналогично ( https://stackoverflow.com/a / 255630/986160 ) но чуть изящнее. Этот словарь также перечисляем, и вы можете переходить от целых к строкам. Также вам не нужно иметь какую-либо строку в вашей кодовой базе, за исключением этого класса.
источник
Для больших наборов перечислений строк перечисленные примеры могут стать утомительными. Если вам нужен список кодов состояния или список других перечислений на основе строк, система атрибутов раздражает в использовании, а статический класс с экземплярами самого себя раздражает в настройке. Для моего собственного решения я использую шаблоны T4, чтобы упростить создание перечислений на основе строк. Результат получается аналогичным тому, как работает класс HttpMethod.
Вы можете использовать это так:
Вы начинаете с файла Enum.tt.
Затем вы добавляете в свой файл StringEnum.ttinclude.
Наконец, вы перекомпилируете свой файл Enum.tt, и результат будет выглядеть так:
источник