Конвертировать.Тип изменения и преобразование в перечисления?
у меня есть Int16
значение из базы данных, и нужно преобразовать к типу enum. К сожалению, это делается в слое кода, который очень мало знает об объектах, за исключением того, что он может собрать через отражение.
таким образом, он заканчивает вызов Convert.ChangeType
который выдает недопустимый литой исключение.
Я нашел то, что я считаю вонючим обходным путем, например:
String name = Enum.GetName(destinationType, value);
Object enumValue = Enum.Parse(destinationType, name, false);
есть ли лучший способ, так что мне не нужно двигаться через эта строковая операция?
вот короткая, но полная программа, которую можно использовать, если кому-то нужно поэкспериментировать:
using System;
public class MyClass
{
public enum DummyEnum
{
Value0,
Value1
}
public static void Main()
{
Int16 value = 1;
Type destinationType = typeof(DummyEnum);
String name = Enum.GetName(destinationType, value);
Object enumValue = Enum.Parse(destinationType, name, false);
Console.WriteLine("" + value + " = " + enumValue);
}
}
3 ответа:
Enum.ToObject(....
- это то, что вы ищете!C#
StringComparison enumValue = (StringComparison)Enum.ToObject(typeof(StringComparison), 5);
VB.NET
Dim enumValue As StringComparison = CType([Enum].ToObject(GetType(StringComparison), 5), StringComparison)
если вы делаете много перечислений преобразования попробуйте использовать следующий класс это сэкономит вам много кода.
public class Enum<EnumType> where EnumType : struct, IConvertible { /// <summary> /// Retrieves an array of the values of the constants in a specified enumeration. /// </summary> /// <returns></returns> /// <remarks></remarks> public static EnumType[] GetValues() { return (EnumType[])Enum.GetValues(typeof(EnumType)); } /// <summary> /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. /// </summary> /// <param name="name"></param> /// <returns></returns> /// <remarks></remarks> public static EnumType Parse(string name) { return (EnumType)Enum.Parse(typeof(EnumType), name); } /// <summary> /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. /// </summary> /// <param name="name"></param> /// <param name="ignoreCase"></param> /// <returns></returns> /// <remarks></remarks> public static EnumType Parse(string name, bool ignoreCase) { return (EnumType)Enum.Parse(typeof(EnumType), name, ignoreCase); } /// <summary> /// Converts the specified object with an integer value to an enumeration member. /// </summary> /// <param name="value"></param> /// <returns></returns> /// <remarks></remarks> public static EnumType ToObject(object value) { return (EnumType)Enum.ToObject(typeof(EnumType), value); } }
теперь вместо того, чтобы писать
(StringComparison)Enum.ToObject(typeof(StringComparison), 5);
вы можете просто написатьEnum<StringComparison>.ToObject(5);
.
на основе ответа @Peter вот метод для
Nullable<int>
доEnum
преобразования:public static class EnumUtils { public static bool TryParse<TEnum>(int? value, out TEnum result) where TEnum: struct, IConvertible { if(!value.HasValue || !Enum.IsDefined(typeof(TEnum), value)){ result = default(TEnum); return false; } result = (TEnum)Enum.ToObject(typeof(TEnum), value); return true; } }
используя
EnumUtils.TryParse<YourEnumType>(someNumber, out result)
становится полезным для многих сценариев. Например, контроллер WebApi в Asp.NET не имеет защиты по умолчанию от недопустимых параметров перечисления. Asp.NET будет просто использоватьdefault(YourEnumType)
значение, даже если некоторые проходитnull
,-1000
,500000
,"garbage string"
или полностью игнорирует параметр. Более того,ModelState
будет действителен во всех этих случаях, поэтому одним из решений является использованиеint?
тип с пользовательской проверкиpublic class MyApiController: Controller { [HttpGet] public IActionResult Get(int? myEnumParam){ MyEnumType myEnumParamParsed; if(!EnumUtils.TryParse<MyEnumType>(myEnumParam, out myEnumParamParsed)){ return BadRequest($"Error: parameter '{nameof(myEnumParam)}' is not specified or incorrect"); } return this.Get(washingServiceTypeParsed); } private IActionResult Get(MyEnumType myEnumParam){ // here we can guarantee that myEnumParam is valid }
Если вы храните перечисление в DataTable, но не знаете, какой столбец является перечислением, а какой строкой/int, вы можете получить доступ к значению следующим образом:
foreach (DataRow dataRow in myDataTable.Rows) { Trace.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); foreach (DataColumn dataCol in myDataTable.Columns) { object v = dataRow[dataCol]; Type t = dataCol.DataType; bool e = false; if (t.IsEnum) e = true; Trace.WriteLine((dataCol.ColumnName + ":").PadRight(30) + (e ? Enum.ToObject(t, v) : v)); } }