C# Convert.ChangeType并转换为枚举?

C# Convert.ChangeType并转换为枚举?,c#,enums,changetype,C#,Enums,Changetype,我从数据库中获得了一个Int16值,需要将其转换为枚举类型。不幸的是,这是在一层代码中完成的,除了通过反射可以收集到的内容外,它对对象知之甚少 因此,它最终调用了Convert.ChangeType,该调用失败,并出现无效的强制转换异常 我发现我觉得一种臭气熏天的工作方式是这样的: String name = Enum.GetName(destinationType, value); Object enumValue = Enum.Parse(destinationType, name, fal

我从数据库中获得了一个
Int16
值,需要将其转换为枚举类型。不幸的是,这是在一层代码中完成的,除了通过反射可以收集到的内容外,它对对象知之甚少

因此,它最终调用了
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);
    }
}
Enum.ToObject(..
就是您要找的

C#

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);
    }
}
公共类枚举,其中枚举类型:struct,IConvertible
{
/// 
///检索指定枚举中常量值的数组。
/// 
/// 
/// 
公共静态枚举类型[]GetValues()
{
返回(EnumType[])Enum.GetValues(typeof(EnumType));
}
/// 
///将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象。
/// 
/// 
/// 
/// 
公共静态枚举类型解析(字符串名称)
{
return(EnumType)Enum.Parse(typeof(EnumType),name);
}
/// 
///将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象。
/// 
/// 
/// 
/// 
/// 
公共静态枚举类型解析(字符串名称,bool ignoreCase)
{
return(EnumType)Enum.Parse(typeof(EnumType)、name、ignoreCase);
}
/// 
///将具有整数值的指定对象转换为枚举成员。
/// 
/// 
/// 
/// 
公共静态枚举类型对象(对象值)
{
返回(EnumType)Enum.ToObject(typeof(EnumType),value);
}
}

现在不需要编写
(StringComparison)Enum.ToObject(typeof(StringComparison),5);
您只需编写
Enum.ToObject(5);

基于@Peter的答案,以下是将
可为null的
转换为
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;
        }
}

如果在数据表中存储枚举,但不知道哪列是枚举,哪列是字符串/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));
    }
}

哎哟……在我喝咖啡之前,我需要停止尝试回答这样的问题……我现在明白了,Console.WriteLine也在一个无法访问枚举类型的层中。我完全误解了。删除了我的(愚蠢的)答案。Legend!不知道这一点。stackoverflow brill不是吗?!:-)一个多小时以来,我一直在为一个类似的问题苦苦挣扎,这就解决了它!即使在发布后两年,也可以获得丰厚的+1;)
ToObject()
似乎允许枚举中不存在的值,也允许基础类型范围之外的值:
enum.ToObject(typeof(IntEnumType),(long)Int32.MaxValue+1)
@NelsonRothermel:C本身允许枚举中未定义的枚举值,因此这并不奇怪。与强制转换相比,您的另一个点更精确,但这似乎只是您的第一个点的一个特例(它似乎是先强制转换到基础类型?)我见过很多次这种方法(在intellisense中),但对它的任务已经有了概念。设计者本可以给这种方法起一个更直观的名字。
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
    }
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));
    }
}