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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/507059/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:05:52  来源:igfitidea点击:

Convert.ChangeType and converting to enums?

c#enumschangetype

提问by Lasse V. Karlsen

I got an Int16value, from the database, and need to convert this to an enum type. This is unfortunately done in a layer of the code that knows very little about the objects except for what it can gather through reflection.

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

As such, it ends up calling Convert.ChangeTypewhich fails with an invalid cast exception.

因此,它最终会调用Convert.ChangeType失败并出现无效的强制转换异常。

I found what I consider a smelly workaround, like this:

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

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

Is there a better way, so that I don't have to move through this String operation?

有没有更好的方法,这样我就不必通过这个 String 操作?

Here's a short, but complete, program that can be used if anyone need to experiment:

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

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

采纳答案by Peter

Enum.ToObject(....is what you're looking for!

Enum.ToObject(....就是你要找的!

C#

C#

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

VB.NET

网络

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

If you do a lot of Enum converting try using the following class it will save you alot of code.

如果您尝试使用以下类进行大量 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);
    }
}

Now instead of writing (StringComparison)Enum.ToObject(typeof(StringComparison), 5);you can simply write Enum<StringComparison>.ToObject(5);.

现在,(StringComparison)Enum.ToObject(typeof(StringComparison), 5);您可以简单地编写Enum<StringComparison>.ToObject(5);.

回答by Artru

Based on the @Peter's answer here is the method for Nullable<int>to Enumconversion:

基于该@彼得的回答这里是方法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;
        }
}

Using EnumUtils.TryParse<YourEnumType>(someNumber, out result)becomes useful for many scenarios. For example, WebApi Controller in Asp.NET does not have default protection against invalid Enum params. Asp.NET will just use default(YourEnumType)value, even if some passes null, -1000, 500000, "garbage string"or totally ignores the parameter. Moreover, ModelStatewill be valid in all these cases, so one of the solution is to use int?type with custom check

EnumUtils.TryParse<YourEnumType>(someNumber, out result)在许多场景中使用变得有用。例如,Asp.NET 中的 WebApi 控制器没有针对无效 Enum 参数的默认保护。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
    }

回答by Cassova

If you are storing an Enum in a DataTable but don't know which column is an enum and which is a string/int, you can access the value this way:

如果您将 Enum 存储在 DataTable 中,但不知道哪一列是枚举,哪一列是字符串/整数,则可以通过以下方式访问该值:

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