Преобразовать строку в перечисление в C #
539966 просмотра
22 ответа
Каков наилучший способ преобразования строки в значение перечисления в C #?
У меня есть HTML-тег выбора, содержащий значения перечисления. Когда страница будет опубликована, я хочу выбрать значение (которое будет в форме строки) и преобразовать его в значение перечисления.
В идеальном мире я мог бы сделать что-то вроде этого:
StatusEnum MyStatus = StatusEnum.Parse("Active");
но это не правильный код
Автор: Ben Mills Источник Размещён: 23.05.2019 12:04Ответы (22)
1191 плюса
В .NET Core и .NET> 4 есть универсальный метод разбора :
Enum.TryParse("Active", out StatusEnum myStatus);
Это также включает в себя новые встроенные out
переменные C # 7 , так что это делает try-parse, преобразование в явный тип enum и инициализирует + заполняет myStatus
переменную.
Если у вас есть доступ к C # 7 и последней версии .NET, это лучший способ.
Оригинальный ответ
В .NET это довольно некрасиво (до 4 или выше):
StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);
Я склонен упростить это с помощью:
public static T ParseEnum<T>(string value)
{
return (T) Enum.Parse(typeof(T), value, true);
}
Тогда я могу сделать:
StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");
Один из предложенных вариантов в комментариях - добавить расширение, которое достаточно просто:
public static T ToEnum<T>(this string value)
{
return (T) Enum.Parse(typeof(T), value, true);
}
StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();
Наконец, вы можете захотеть использовать перечисление по умолчанию, если строка не может быть проанализирована:
public static T ToEnum<T>(this string value, T defaultValue)
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
T result;
return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}
Что делает этот вызов:
StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);
Тем не менее, я бы осторожно добавил такой метод расширения, string
поскольку (без управления пространством имен) он будет отображаться во всех случаях, string
независимо от того, содержат ли они перечисление или нет (поэтому 1234.ToString().ToEnum(StatusEnum.None)
будет допустимым, но бессмысленным). Часто лучше избегать загромождения основных классов Microsoft дополнительными методами, которые применяются только в очень специфических контекстах, если ваша команда разработчиков не очень хорошо понимает, что делают эти расширения.
282 плюса
Используйте Enum.TryParse<T>(String, T)
(≥ .NET 4.0):
StatusEnum myStatus;
Enum.TryParse("Active", out myStatus);
Это можно еще больше упростить с помощью встроенного типа параметра в C # 7.0 :
Enum.TryParse("Active", out StatusEnum myStatus);
Автор: Erwin Mayer
Размещён: 05.12.2013 08:22
174 плюса
Обратите внимание, что производительность Enum.Parse () ужасна, потому что она реализована с помощью отражения. (То же самое относится и к Enum.ToString, который идет другим путем.)
Если вам нужно преобразовать строки в Enums в чувствительном к производительности коде, лучше всего Dictionary<String,YourEnum>
при запуске создать его и использовать для конвертации.
82 плюса
Вы ищете Enum.Parse .
SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");
Автор: DavidWhitney
Размещён: 19.08.2008 12:53
26 плюса
Вы можете использовать методы расширения сейчас:
public static T ToEnum<T>(this string value, bool ignoreCase = true)
{
return (T) Enum.Parse(typeof (T), value, ignoreCase);
}
И вы можете вызвать их по следующему коду (здесь FilterType
это тип enum):
FilterType filterType = type.ToEnum<FilterType>();
Автор: Foyzul Karim
Размещён: 10.02.2014 10:12
16 плюса
object Enum.Parse(System.Type enumType, string value, bool ignoreCase);
Так что, если у вас есть перечисление с именем настроение, это будет выглядеть так
enum Mood
{
Angry,
Happy,
Sad
}
// ...
Mood m = (Mood) Enum.Parse(typeof(Mood), "Happy", true);
Console.WriteLine("My mood is: {0}", m.ToString());
Автор: brendan
Размещён: 19.08.2008 12:58
16 плюса
BEWARE:
enum Example
{
One = 1,
Two = 2,
Three = 3
}
Enum.(Try)Parse()
принимает несколько аргументов, разделенных запятыми, и объединяет их с двоичным «или»|
. Вы не можете отключить это, и, по моему мнению, вы почти никогда не хотите этого.
var x = Enum.Parse("One,Two"); // x is now Three
Даже если Three
он не был определен, x
все равно получит значение int 3
. Это еще хуже: Enum.Parse () может дать вам значение, которое даже не определено для enum!
Я не хотел бы испытывать последствия пользователей, добровольно или невольно, запускающих это поведение.
Кроме того, как упоминалось другими, производительность не идеальна для больших перечислений, а именно линейна по числу возможных значений.
Я предлагаю следующее:
public static bool TryParse<T>(string value, out T result)
where T : struct
{
var cacheKey = "Enum_" + typeof(T).FullName;
// [Use MemoryCache to retrieve or create&store a dictionary for this enum, permanently or temporarily.
// [Implementation off-topic.]
var enumDictionary = CacheHelper.GetCacheItem(cacheKey, CreateEnumDictionary<T>, EnumCacheExpiration);
return enumDictionary.TryGetValue(value.Trim(), out result);
}
private static Dictionary<string, T> CreateEnumDictionary<T>()
{
return Enum.GetValues(typeof(T))
.Cast<T>()
.ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase);
}
Автор: Timo
Размещён: 14.12.2015 12:31
15 плюса
Enum.Parse твой друг:
StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");
Автор: tags2k
Размещён: 19.08.2008 12:55
12 плюса
Вы можете расширить принятый ответ значением по умолчанию, чтобы избежать исключений:
public static T ParseEnum<T>(string value, T defaultValue) where T : struct
{
try
{
T enumValue;
if (!Enum.TryParse(value, true, out enumValue))
{
return defaultValue;
}
return enumValue;
}
catch (Exception)
{
return defaultValue;
}
}
Тогда вы называете это как:
StatusEnum MyStatus = EnumUtil.ParseEnum("Active", StatusEnum.None);
Автор: Nelly
Размещён: 09.12.2014 11:43
9 плюса
Мы не могли предположить совершенно достоверный ввод и пошли с этим вариантом ответа @ Keith:
public static TEnum ParseEnum<TEnum>(string value) where TEnum : struct
{
TEnum tmp;
if (!Enum.TryParse<TEnum>(value, true, out tmp))
{
tmp = new TEnum();
}
return tmp;
}
Автор: gap
Размещён: 30.08.2012 03:07
7 плюса
// str.ToEnum<EnumType>()
T static ToEnum<T>(this string str)
{
return (T) Enum.Parse(typeof(T), str);
}
Автор: Mark Cidade
Размещён: 19.08.2008 01:13
5 плюса
Разбирает строку в TEnum без try / catch и без метода TryParse () из .NET 4.5
/// <summary>
/// Parses string to TEnum without try/catch and .NET 4.5 TryParse()
/// </summary>
public static bool TryParseToEnum<TEnum>(string probablyEnumAsString_, out TEnum enumValue_) where TEnum : struct
{
enumValue_ = (TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0);
if(!Enum.IsDefined(typeof(TEnum), probablyEnumAsString_))
return false;
enumValue_ = (TEnum) Enum.Parse(typeof(TEnum), probablyEnumAsString_);
return true;
}
Автор: jite.gs
Размещён: 17.10.2013 04:04
3 плюса
Супер простой код с использованием TryParse:
var value = "Active";
StatusEnum status;
if (!Enum.TryParse<StatusEnum>(value, out status))
status = StatusEnum.Unknown;
Автор: Brian Rice
Размещён: 25.11.2016 02:30
2 плюса
Мне нравится решение метода расширения ..
namespace System
{
public static class StringExtensions
{
public static bool TryParseAsEnum<T>(this string value, out T output) where T : struct
{
T result;
var isEnum = Enum.TryParse(value, out result);
output = isEnum ? result : default(T);
return isEnum;
}
}
}
Здесь ниже моя реализация с тестами.
using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
using static System.Console;
private enum Countries
{
NorthAmerica,
Europe,
Rusia,
Brasil,
China,
Asia,
Australia
}
[TestMethod]
public void StringExtensions_On_TryParseAsEnum()
{
var countryName = "Rusia";
Countries country;
var isCountry = countryName.TryParseAsEnum(out country);
WriteLine(country);
IsTrue(isCountry);
AreEqual(Countries.Rusia, country);
countryName = "Don't exist";
isCountry = countryName.TryParseAsEnum(out country);
WriteLine(country);
IsFalse(isCountry);
AreEqual(Countries.NorthAmerica, country); // the 1rst one in the enumeration
}
Автор: alhpe
Размещён: 01.10.2015 09:57
1 плюс
public static T ParseEnum<T>(string value) //function declaration
{
return (T) Enum.Parse(typeof(T), value);
}
Importance imp = EnumUtil.ParseEnum<Importance>("Active"); //function call
==================== Полная программа ====================
using System;
class Program
{
enum PetType
{
None,
Cat = 1,
Dog = 2
}
static void Main()
{
// Possible user input:
string value = "Dog";
// Try to convert the string to an enum:
PetType pet = (PetType)Enum.Parse(typeof(PetType), value);
// See if the conversion succeeded:
if (pet == PetType.Dog)
{
Console.WriteLine("Equals dog.");
}
}
}
-------------
Output
Equals dog.
Автор: Rae Lee
Размещён: 18.08.2015 05:28
1 плюс
Я использовал класс (строго типизированная версия Enum с разбором и улучшением производительности). Я нашел его на GitHub, и он должен работать и для .NET 3.5. Он имеет некоторые накладные расходы памяти, поскольку он буферизует словарь.
StatusEnum MyStatus = Enum<StatusEnum>.Parse("Active");
Блог пост Enums - лучший синтаксис, улучшенная производительность и TryParse в NET 3.5 .
И код: https://github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/System/EnumT.cs
Автор: Patrik Lindström Размещён: 01.07.2015 09:391 плюс
Для производительности это может помочь:
private static Dictionary<Type, Dictionary<string, object>> dicEnum = new Dictionary<Type, Dictionary<string, object>>();
public static T ToEnum<T>(this string value, T defaultValue)
{
var t = typeof(T);
Dictionary<string, object> dic;
if (!dicEnum.ContainsKey(t))
{
dic = new Dictionary<string, object>();
dicEnum.Add(t, dic);
foreach (var en in Enum.GetValues(t))
dic.Add(en.ToString(), en);
}
else
dic = dicEnum[t];
if (!dic.ContainsKey(value))
return defaultValue;
else
return (T)dic[value];
}
Автор: Koray
Размещён: 22.06.2016 02:10
1 плюс
Я обнаружил, что здесь случай со значениями перечисления, которые имеют значение EnumMember, не рассматривался. Итак, поехали:
using System.Runtime.Serialization;
public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue) where TEnum : struct
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
TEnum result;
var enumType = typeof(TEnum);
foreach (var enumName in Enum.GetNames(enumType))
{
var fieldInfo = enumType.GetField(enumName);
var enumMemberAttribute = ((EnumMemberAttribute[]) fieldInfo.GetCustomAttributes(typeof(EnumMemberAttribute), true)).FirstOrDefault();
if (enumMemberAttribute?.Value == value)
{
return Enum.TryParse(enumName, true, out result) ? result : defaultValue;
}
}
return Enum.TryParse(value, true, out result) ? result : defaultValue;
}
И пример этого перечисления:
public enum OracleInstanceStatus
{
Unknown = -1,
Started = 1,
Mounted = 2,
Open = 3,
[EnumMember(Value = "OPEN MIGRATE")]
OpenMigrate = 4
}
Автор: isxaker
Размещён: 04.10.2016 04:40
1 плюс
Вы должны использовать Enum.Parse, чтобы получить значение объекта из Enum, после этого вы должны изменить значение объекта на конкретное значение перечисления. Приведение к перечисляемому значению можно выполнить с помощью Convert.ChangeType. Пожалуйста, взгляните на следующий фрагмент кода
public T ConvertStringValueToEnum<T>(string valueToParse){
return Convert.ChangeType(Enum.Parse(typeof(T), valueToParse, true), typeof(T));
}
Автор: Bartosz Gawron
Размещён: 08.02.2017 11:33
1 плюс
Попробуйте этот образец:
public static T GetEnum<T>(string model)
{
var newModel = GetStringForEnum(model);
if (!Enum.IsDefined(typeof(T), newModel))
{
return (T)Enum.Parse(typeof(T), "None", true);
}
return (T)Enum.Parse(typeof(T), newModel.Result, true);
}
private static Task<string> GetStringForEnum(string model)
{
return Task.Run(() =>
{
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
var nonAlphanumericData = rgx.Matches(model);
if (nonAlphanumericData.Count < 1)
{
return model;
}
foreach (var item in nonAlphanumericData)
{
model = model.Replace((string)item, "");
}
return model;
});
}
В этом примере вы можете отправить каждую строку и установить свой Enum
. Если у вас Enum
есть данные, которые вы хотели, верните их как ваш Enum
тип.
0 плюса
<Extension()>
Public Function ToEnum(Of TEnum)(ByVal value As String, ByVal defaultValue As TEnum) As TEnum
If String.IsNullOrEmpty(value) Then
Return defaultValue
End If
Return [Enum].Parse(GetType(TEnum), value, True)
End Function
Автор: AHMED RABEE
Размещён: 22.05.2019 07:15
0 плюса
public TEnum ToEnum<TEnum>(this string value, TEnum defaultValue){
if (string.IsNullOrEmpty(value))
return defaultValue;
return Enum.Parse(typeof(TEnum), value, true);}
Автор: AHMED RABEE
Размещён: 22.05.2019 07:19
Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- string В чем разница между строкой и строкой в ??C #?
- string Почему в Ruby нет реального StringBuffer или StringIO?
- string Преобразовать строку в перечисление в C #
- string Преобразование списка <Integer> в список <String>
- string Самый эффективный способ объединения строк?
- string Экранирование строк HTML с помощью jQuery
- enums Что означает атрибут Enum [Flags] в C #?
- enums Проверить перечисление значений
- enums Приведите int к перечислению в C #
- enums 64-битное перечисление в C ++?
- enums Создать общий метод, ограничивающий перечисление