Convert.ChangeType并转换为枚举?


70

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

这样,它最终Convert.ChangeType将以无效的强制转换异常调用失败。

我发现了我认为很臭的解决方法,如下所示:

String name = Enum.GetName(destinationType, value);
Object enumValue = Enum.Parse(destinationType, name, false);

有没有更好的方法,这样我就不必遍历此String操作了?

这是一个简短但完整的程序,如果有人需要实验,可以使用该程序:

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);
    }
}

1
哎呀……在我喝咖啡之前,我需要停止尝试回答这样的问题……
Daniel Schaffer

我现在看到,Console.WriteLine也在无法访问枚举类型的图层中。我完全误会了。删除了我(愚蠢的)答案。
GvS

Answers:


92

Enum.ToObject(.... 是您要寻找的!

C#

StringComparison enumValue = (StringComparison)Enum.ToObject(typeof(StringComparison), 5);

VB.NET

Dim enumValue As StringComparison = CType([Enum].ToObject(GetType(StringComparison), 5), StringComparison)

如果您进行大量的Enum转换,请尝试使用以下类,它将为您节省大量代码。

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);


4
传说!对此一无所知。stackoverflow不是很漂亮吗?:-)
琼斯医生2010年

经历了一个多小时的类似问题,终于解决了!即使在发布后两年,也
能赚

1
ToObject()似乎允许该枚举中不存在的值,以及超出基础类型范围的值:Enum.ToObject(typeof(IntEnumType), (long)Int32.MaxValue + 1)
Nelson Rothermel 2012年

1
@NelsonRothermel:C#本身允许在枚举中未定义的枚举值,因此在此不足为奇。与强制转换相比,您的另一点更为准确,但似乎只是您的第一点的特殊情况(似乎首先强制转换为基础类型?)
Michael Bray 2014年

我(在智能感知中)多次见过这种方法,但是对它的任务有所了解。设计人员可以为这种方法取一个更直观的名称。
佐尔坦陶马希

0

基于该@彼得的回答这里是方法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)在许多情况下,使用变得很有用。例如,Asp.NET中的WebApi控制器没有针对无效枚举参数的默认保护。Asp.NET将只使用default(YourEnumType)值,即使有些传球null-1000500000"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
    }

0

如果要在数据表中存储枚举,但不知道哪一列是枚举,哪一个是字符串/整数,则可以通过以下方式访问值:

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));
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.