29

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

给定一个枚举

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

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

4

6 回答 6

53

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

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您的情况下返回。

于 2012-08-16T08:05:33.463 回答
6

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

public T Convert<T>(object o)
{
   T enumVal= (T)Enum.ToObject(typeof(T), o);
   return enumVal;
}
于 2018-07-18T11:11:49.367 回答
5

在某些情况下,您不能使用泛型(例如在 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;
}
于 2016-10-27T12:21:36.560 回答
0

默认情况下,枚举数字值的类型 = 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
于 2018-01-12T16:42:26.533 回答
0

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”)转换为枚举。实施者必须决定是否允许这样做。

于 2020-06-25T14:51:04.857 回答
0

你可以使用这个扩展:

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

枚举

公共枚举甲壳类动物 { 青蛙 = 1,蟾蜍 = 4 }

用法

Crustaceans x = "Toad".ToEnum<Crustaceans>();
Crustaceans y = 4.ToEnum<Crustaceans>();
if (x == y) 
{
    System.Console.WriteLine("Equale");
}
于 2020-11-14T07:33:36.287 回答