将通用但已知为枚举可空类型转换为可为空的int

时间:2016-11-02 08:55:13

标签: c# generics enums

我知道这可能听起来有点奇怪,但我想将T?的对象强制转换为int?。我想要这个的原因是T总是一个枚举,我也知道这个枚举可以转换为int。我为枚举创建了一个通用包装类,并发现this "solution"将泛型类型约束为枚举类型。

我的代码目前看起来像这样:

public class EnumWrapper<T>
    where T : struct, IConvertible
{
    public EnumWrapper()
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("T must be an enumerated type");
        }
    }

    public T? Enum { get; set; }

    public int? EnumValue => (int?)Enum;    // this won't compile

    ...
}

我知道在转换为值类型((int?)(object)Enum)之前强制转换为对象会欺骗编译器,但这也适用于此吗?我怀疑可以为空的人干扰了这一点。

所以我的问题是:实现这种通用行为的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

由于TIConvertible,您可以使用ToInt32()方法避免投射和装箱:

public int? EnumValue => this.Enum?.ToInt32(CultureInfo.CurrentCulture.NumberFormat);

如果缺少实际值,this.Enum?将确保返回null

此外,由于我们正在尝试保留已包装的枚举的值类型语义,因此您需要将EnumWrapperclass更改为struct并且使用扩展方法轻松包装值:

public struct EnumWrapper<T> where T : struct, IConvertible
{
    public T? Enum { get; set; }
    public int? EnumValue => this.Enum?.ToInt32(CultureInfo.CurrentCulture.NumberFormat);
}

public static class EnumWrapperExtension
{
    public static EnumWrapper<T> Wrap<T>(this T data) where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return new EnumWrapper<T> { Enum = data };
    }
}

用法:

public enum Color
{
    Red = 1,
    Green = 2,
}

var color = Color.Green;
var colorAsInt = color.Wrap().EnumValue;

请参阅MSDN