C# 在C中将Int强制转换为泛型可为null的枚举#

C# 在C中将Int强制转换为泛型可为null的枚举#,c#,generics,casting,enums,nullable,C#,Generics,Casting,Enums,Nullable,我想将int值强制转换为使用泛型函数的可空枚举。我认为这会很容易,特别是对于enum/int转换的所有SO。我发现的最接近的问题是,但不幸的是,它不能处理可为空的枚举。解决可空枚举强制转换问题,但不能使用泛型 下面是一个我正在尝试做的简化示例: public enum SouthParkCharacters { Stan = 0, Kyle = 1, Eric = 2, Kenny = 3 } public static T CastNullableEnum&l

我想将int值强制转换为使用泛型函数的可空枚举。我认为这会很容易,特别是对于enum/int转换的所有SO。我发现的最接近的问题是,但不幸的是,它不能处理可为空的枚举。解决可空枚举强制转换问题,但不能使用泛型

下面是一个我正在尝试做的简化示例:

public enum SouthParkCharacters
{
    Stan = 0,
    Kyle = 1,
    Eric = 2,
    Kenny = 3
}

public static T CastNullableEnum<T>(int value)
{
    return (T)(object)((int?)value).Value;
}


public static T SomeFunction<T>(this int anyEnumValue)
{
        SouthParkCharacters? spc = SouthParkCharacters.Kenny;

        spc = CastNullableEnum<SouthParkCharacters>(3); //I am working!
        spc = CastNullableEnum<SouthParkCharacters?>(3); //Raise error Specified cast is not valid.

        //This function will be public so I won't have control over the T
        T finalValue = CastNullableEnum<T>(anyEnumValue); //Raise error Specified cast is not valid.

        return finalValue;

}
公共枚举字符
{
斯坦=0,
凯尔=1,
Eric=2,
肯尼=3
}
公共静态T CastNullableEnum(int值)
{
返回(T)(对象)((int?)值);
}
公共静态T SomeFunction(此int anyEnumValue)
{
SouthParkCharacters?spc=SouthParkCharacters.Kenny;
spc=CastNullableEnum(3);//我正在工作!
spc=CastNullableEnum(3);//引发错误指定的强制转换无效。
//此函数将是公共的,因此我无法控制t
T finalValue=CastNullableEnum(anyEnumValue);//引发错误指定的强制转换无效。
返回最终值;
}
正如您在上一个函数中所看到的,不可为null的枚举的强制转换正在工作。问题是,我希望能够从另一个泛型函数调用CastNullableEnum,该函数可以使用可为null的枚举作为泛型类型

我知道您可以将泛型类型作为可空的泛型
CastNullableEnum
传递,但是我们可以做相反的事情吗(即将可空的基础类型传递给泛型函数)


如果不能做到这一点,那么我想解决方案应该是找到在CastNullableEnum函数中强制转换枚举值的正确方法。

有趣的问题。此代码的问题是将整数强制转换为可为null的枚举,这是不可能的

  SouthParkCharacters? enumValue = (SouthParkCharacters?)int.MaxValue;
  if (enumValue.HasValue)
     {
         Console.WriteLine("it still has value");
     }
上面的代码正在运行,结果enumValue仍然有值

但无论如何,如果你在编译后看一看C代码,它会是这样的:

public static T CastNullableEnum<T>(int value)
    {
        Type type = typeof(T);
        return (T)((object)value);
    }
    public static T SomeFunction<T>(int anyEnumValue)
    {
        Program.SouthParkCharacters? spc = new Program.SouthParkCharacters?(Program.SouthParkCharacters.Kenny);
        spc = new Program.SouthParkCharacters?(Program.CastNullableEnum<Program.SouthParkCharacters>(new int?(3)));
        spc = Program.CastNullableEnum<Program.SouthParkCharacters?>(new int?(3));
        return Program.CastNullableEnum<T>(new int?(anyEnumValue));
    }
public static T CastNullableEnum(int值)
{
类型=类型(T);
返回(T)((对象)值);
}
公共静态T SomeFunction(int anyEnumValue)
{
Program.SouthParkCharacters?spc=新程序.SouthParkCharacters?(Program.SouthParkCharacters.Kenny);
spc=新程序.SouthParkCharacters?(程序.CastNullableEnum(新int?(3));
spc=Program.CastNullableEnum(新的int?(3));
返回程序.CastNullableEnum(新int?(anyEnumValue));
}
现在,请注意

spc = new Program.SouthParkCharacters?(Program.CastNullableEnum<Program.SouthParkCharacters>(new int?(3))); 
spc=new Program.SouthParkCharacters?(Program.CastNullableEnum(new int?(3));
这就是未指定的强制转换异常的来源;因为新字符?(int值)需要一个整数


有趣的是,当您使用即时命令运行时,您不会遇到这个问题。有趣,是吗?

有趣的问题。此代码的问题是将整数强制转换为可为null的枚举,这是不可能的

  SouthParkCharacters? enumValue = (SouthParkCharacters?)int.MaxValue;
  if (enumValue.HasValue)
     {
         Console.WriteLine("it still has value");
     }
上面的代码正在运行,结果enumValue仍然有值

但无论如何,如果你在编译后看一看C代码,它会是这样的:

public static T CastNullableEnum<T>(int value)
    {
        Type type = typeof(T);
        return (T)((object)value);
    }
    public static T SomeFunction<T>(int anyEnumValue)
    {
        Program.SouthParkCharacters? spc = new Program.SouthParkCharacters?(Program.SouthParkCharacters.Kenny);
        spc = new Program.SouthParkCharacters?(Program.CastNullableEnum<Program.SouthParkCharacters>(new int?(3)));
        spc = Program.CastNullableEnum<Program.SouthParkCharacters?>(new int?(3));
        return Program.CastNullableEnum<T>(new int?(anyEnumValue));
    }
public static T CastNullableEnum(int值)
{
类型=类型(T);
返回(T)((对象)值);
}
公共静态T SomeFunction(int anyEnumValue)
{
Program.SouthParkCharacters?spc=新程序.SouthParkCharacters?(Program.SouthParkCharacters.Kenny);
spc=新程序.SouthParkCharacters?(程序.CastNullableEnum(新int?(3));
spc=Program.CastNullableEnum(新的int?(3));
返回程序.CastNullableEnum(新int?(anyEnumValue));
}
现在,请注意

spc = new Program.SouthParkCharacters?(Program.CastNullableEnum<Program.SouthParkCharacters>(new int?(3))); 
spc=new Program.SouthParkCharacters?(Program.CastNullableEnum(new int?(3));
这就是未指定的强制转换异常的来源;因为新字符?(int值)需要一个整数


有趣的是,当您使用即时命令运行时,您不会遇到这个问题。有意思,是吧?

我可能看错了问题,你可以从nullable中获取底层类型,然后使用
Enum.Parse
而不是直接强制转换

public T CastNullableEnum<T>(int value) 
{
    var enumType = Nullable.GetUnderlyingType(typeof(T));
    if (Enum.IsDefined(enumType, value)) 
    {
        return (T)(object)Enum.Parse(enumType, value.ToString());
    }
    return default(T);
}

var test1 = CastNullableEnum<SouthParkCharacters?>(3); 
//returns Kenny

var test2 = CastNullableEnum<SouthParkCharacters?>(9); 
// returns null
public T CastNullableEnum(int值)
{
var enumType=Nullable.GetUnderlyingType(typeof(T));
if(枚举已定义(枚举类型、值))
{
返回(T)(对象)Enum.Parse(enumType,value.ToString());
}
返回默认值(T);
}
var test1=CastNullableEnum(3);
//返回肯尼
var test2=CastNullableEnum(9);
//返回空值

我可能看错了这个问题,你可以从null表中获取底层类型,然后使用
Enum.Parse
而不是直接强制转换

public T CastNullableEnum<T>(int value) 
{
    var enumType = Nullable.GetUnderlyingType(typeof(T));
    if (Enum.IsDefined(enumType, value)) 
    {
        return (T)(object)Enum.Parse(enumType, value.ToString());
    }
    return default(T);
}

var test1 = CastNullableEnum<SouthParkCharacters?>(3); 
//returns Kenny

var test2 = CastNullableEnum<SouthParkCharacters?>(9); 
// returns null
public T CastNullableEnum(int值)
{
var enumType=Nullable.GetUnderlyingType(typeof(T));
if(枚举已定义(枚举类型、值))
{
返回(T)(对象)Enum.Parse(enumType,value.ToString());
}
返回默认值(T);
}
var test1=CastNullableEnum(3);
//返回肯尼
var test2=CastNullableEnum(9);
//返回空值
这将起作用:

public static T IntToEnum<T>(object value)
{
    if (value == null)
        return (T)value;

    else if (typeof(T).IsEnum)
        return (T)value;

    else if (Nullable.GetUnderlyingType(typeof(T))?.IsEnum == true)
        return (T)Enum.ToObject(Nullable.GetUnderlyingType(typeof(T)), (int)value);

    throw new Exception(string.Format("Value cannot be converted from {0} to {1}", value.GetType().Name, typeof(T).Name));
}
public static T IntToEnum(对象值)
{
如果(值==null)
返回(T)值;
else if(typeof(T).IsEnum)
返回(T)值;
else if(Nullable.getUnderlineType(typeof(T))?.IsEnum==true)
返回(T)Enum.ToObject(null.getUnderlineType(typeof(T)),(int)值);
抛出新异常(string.Format(“值不能从{0}转换为{1}”)、Value.GetType().Name、typeof(T.Name));
}
可用于可空枚举和常规枚举

public enum Codes
{
    A = 1,
    B = 2,
    C = 3
}

static void Main(string[] args)
{
    Console.WriteLine(IntToEnum<Codes?>(1));
    Console.WriteLine(IntToEnum<Codes?>(null));
    Console.WriteLine(IntToEnum<Codes>(2));
}
公共枚举代码
{
A=1,
B=2,
C=3
}
静态void Main(字符串[]参数)
{
控制台写入线(IntToEnum(1));
Console.WriteLine(IntToEnum(null));
控制台写入线(IntToEnum(2));
}
这将起作用:

public static T IntToEnum<T>(object value)
{
    if (value == null)
        return (T)value;

    else if (typeof(T).IsEnum)
        return (T)value;

    else if (Nullable.GetUnderlyingType(typeof(T))?.IsEnum == true)
        return (T)Enum.ToObject(Nullable.GetUnderlyingType(typeof(T)), (int)value);

    throw new Exception(string.Format("Value cannot be converted from {0} to {1}", value.GetType().Name, typeof(T).Name));
}
public static T IntToEnum(对象值)
{
如果(值==null)
返回(T)值;
else if(typeof(T).IsEnum)
返回(T)值;
else if(Nullable.getUnderlineType(typeof(T))?.IsEnum==true)