[英]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.