繁体   English   中英

C# 将对象转换为枚举

[英]C# Casting with objects to Enums

这个问题与通用方法中的枚举转换有关

给定一个枚举

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

我可以简单地创建我的枚举实例

short val = 4;
Crustaceans crusty = (Crustaceans) val;

然而,如果

short val = 4;
object obj = (object) val;
Crustaceans crusty = (Crustaceans)obj;

试图执行硬皮的初始化时抛出运行时异常。

谁能解释为什么会发生这种情况,以及为什么这样做是不合法的。

并不是说我真的想这样做,但是我在尝试使用泛型实现类似的事情时遇到了一个问题,实际上这就是幕后发生的事情。 IE

public T dosomething<T>(short val) where T : new()
{
    T result = (T)(object) val;
    return result;
}

所以我试图做的是有一个通用函数,它可以与枚举和非枚举一起工作(不是那么重要 - 但会很好),可以设置为一个短值而不抛出异常并实际初始化正确的枚举值。

像这样的事情可能会帮助你:

public T dosomething<T>(object o)
{
   T enumVal= (T)Enum.Parse(typeof(T), o.ToString());
   return enumVal;
}

但这仅适用于枚举,因为使用Enum.Parse(..)

并使用它,例如:

object o = 4;
dosomething<Crustaceans>(o);

您的情况下,这将返回Toad

在某些情况下,您不能使用泛型(例如在 WPF 转换器中,当您将值作为object )。 在这种情况下,您不能强制转换为int因为枚举类型可能不是int 这是没有泛型的通用方法。 该示例在 WPF 转换器中给出,但里面的代码是通用的:

using System;
using System.Windows;
using System.Windows.Data;

.
.
.

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var enumType = value.GetType();
    var underlyingType = Enum.GetUnderlyingType(enumType);
    var numericValue = System.Convert.ChangeType(value, underlyingType);
    return numericValue;
}

如果整数类型装箱为对象,正确的转换方法是使用Enum.ToObject方法:

public T Convert<T>(object o)
{
   T enumVal= (T)Enum.ToObject(typeof(T), o);
   return enumVal;
}

默认情况下,枚举数字值具有 type = int。 在您的代码中,您希望将具有短类型的值转换为枚举类型。 为此,您必须将短类型设置为您的枚举值。 这将起作用:

public enum Crustaceans : short // <--
{
    Frog = 1,
    Toad = 4
}

short  @short = 1;
object @object = @short;

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog   

如果您不想更改默认枚举值类型

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

object @object = Crustaceans.Frog;

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog

要么

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

int @integer= 1;

var @enum = (Crustaceans)@integer; // @enum = Crustaceans.Frog

Tigrin 的答案会将枚举的字符串名称转换为枚举 - 这可能是所需的,而 Hazzik 则不会,这也可能是所需的。 但是,如果您想要 Tigrin 答案的功能,以及 Hazzik 答案的效率(Tigrin 的答案采用枚举,将其转换为字符串,然后再返回...),此代码将执行此操作:

    public static bool TryParseEnum<EnumType>(object obj, ref EnumType enumType) where EnumType : struct, System.IConvertible
    {
        if (obj != null)
        {
            try
            {
                string str = obj as string;
                if (str == null)
                {
                    enumType = (EnumType)Enum.ToObject(typeof(EnumType), obj);
                    return true;
                }
                else
                {
                    str = str.Trim();
                    if (str.Length > 0)//optimization to avoid throwing and catching in frequently occurring case
                    {
                        //if (!int.TryParse(str, out int unused))//ARRRRGGGG!!! Microsoft allows the string "2" to be parsed to the enum, which we never want.  Why would anyone want this???
                        {
                            enumType = (EnumType)Enum.Parse(typeof(EnumType), str, true);
                            return true;
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
        }
        return false;
    }

请注意注释掉的代码中的代码:Tigrin 的答案和上面的代码允许将整数的“字符串”表示(例如“1”)转换为枚举。 实现者必须决定是否允许这样做。

这个问题与泛型方法中的枚举转换有关

给定一个枚举

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

我可以很简单地创建我的枚举的实例

short val = 4;
Crustaceans crusty = (Crustaceans) val;

但是,如果

short val = 4;
object obj = (object) val;
Crustaceans crusty = (Crustaceans)obj;

引发运行时异常,尝试执行硬壳初始化。

谁能解释这是为什么发生的,为什么这样做是不合法的。

并不是我真的想这样做,而是在尝试使泛型发生类似的事情时有效地解决了一个问题,而这实际上是在幕后进行的事情。 IE

public T dosomething<T>(short val) where T : new()
{
    T result = (T)(object) val;
    return result;
}

因此,我试图做的是有一个通用函数,可与枚举和非枚举一起使用(不是很关键,但会很好),可以将其设置为短值而不会引发异常并实际初始化正确的枚举值。

你可以使用这个扩展:

public static T ToEnum<T>(this object obj)
    {
        var objType = obj.GetType();
        if (typeof(T).IsEnum)
        {
            if (objType == typeof(string))
                return (T)Enum.Parse(typeof(T), obj.ToString());
            return (T)Enum.ToObject(typeof(T), obj);
        }
        if (objType == typeof(string))
            return (T)Enum.Parse(Nullable.GetUnderlyingType(typeof(T)), obj.ToString());
        return (T)Enum.ToObject(Nullable.GetUnderlyingType(typeof(T)), obj);
    }

枚举

public enum Crustaceans { Frog = 1, Toad = 4 }

用法

Crustaceans x = "Toad".ToEnum<Crustaceans>();
Crustaceans y = 4.ToEnum<Crustaceans>();
if (x == y) 
{
    System.Console.WriteLine("Equale");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM