将已知为枚举可为空类型的通用类型转换为可为空的整数。

3
我知道这听起来有点奇怪,但我想将一个T?对象转换为int?。我之所以这样做是因为T总是枚举类型,并且我知道此枚举类型可以转换为int。我正在创建一个通用的枚举包装类,并找到这个“解决方案”将通用类型限制为枚举类型。

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

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)可以欺骗编译器,但这种方法对这里是否有效我还有疑问,我怀疑可空类型会干扰它。
因此,我的问题是:实现这种通用行为的最佳方法是什么?

好的,我会试一下。不过,这似乎并不是最好的解决方案... - Florian Koch
2
使用C# 6的更优雅的解决方案:public int? EnumValue => this.Enum?.ToInt32(CultureInfo.CurrentCulture.NumberFormat); - haim770
3
仅仅因为它是枚举类型,并不保证可以转换为“int”。值得注意的是,枚举类型可以基于“uint”或“long/ulong”。 - Damien_The_Unbeliever
@Damien_The_Unbeliever 是的,你说得对,但在我的情况下,这不会发生 - 我甚至在实际代码中使用Int16(short),因为它永远不会那么高。 - Florian Koch
前几天,我在CodeProject上发布了一条名为“使用泛型枚举约束的乐趣”的消息(请参见www.codeproject.com/Feature/WeirdAndWonderful.aspx?msg=5071953)。嗯,你也遇到了这些问题。 - Bernhard Hiller
显示剩余5条评论
1个回答

2

由于 T 实现了 IConvertible 接口,因此您可以使用 ToInt32() 方法避免强制转换和装箱:

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

this.Enum? 将确保在实际值缺失的情况下返回 null

另外,由于我们试图保留包装的 Enum 的值类型语义,您需要将 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

最好的部分是,您可以确信可空已正确处理 - 谢谢! - Florian Koch
我很喜欢使用扩展方法的建议,再次点赞 - 谢谢,我想我会使用这个。 - Florian Koch
唯一的缺点是我无法使用构造函数来检查 T 是否真的是一个枚举。 - Florian Koch
1
@FlorianKoch,我把那个检查移到了扩展方法中。 - haim770

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接