代码之家  ›  专栏  ›  技术社区  ›  Moe Sisko

当枚举是泛型时,是否可以强制转换为枚举?

  •  2
  • Moe Sisko  · 技术社区  · 4 年前

    试图编译这样的泛型函数。传递的T应为枚举。示例高度简化:

        public T? GetEnumValue<T>(int id) where T: struct
        {
            // do some work to get the numerical value of the enum.
            // e.g. read number from a database, looking up by passed id. Fetched value could be null. 
    
            int? rawVal = 1;  
    
            // after work is done, return result as enum. 
    
            if (rawVal == null)
                return null; 
            
            return (T)rawVal.Value;  // Line XYZ : won't compile, as T is not an Enum at compile time.
        }
    

    使用示例:

            SomeEnum? val = GetEnumValue<SomeEnum>(5);
            AnotherEnum? val2 = GetEnumValue<AnotherEnum>(3);
    

    哪里

    public enum SomeEnum 
    {
        A,
        B,        
    }
    
    public enum AnotherEnum
    {
        C,
        D,
    }
    

    有没有变通办法让XYZ的这条线正常工作?
    此行试图将枚举的整数值转换为枚举。 在这种情况下,假设只有当T是Enum时才会调用GetEnumValue,它具有基本的整数值。

    编辑:一个可能的解决方法可能是:

     return (T)Enum.ToObject(typeof(T), rawVal.Value);
    

    ,这似乎有效。

    2 回复  |  直到 4 年前
        1
  •  2
  •   jmcilhinney    4 年前

    这将编译:

    return (T)(object)rawVal.Value;
    

    不过,您也应该添加额外的约束:

    where T : struct, Enum
    

    编辑:

    为了完整起见,我将在下面留下我的原始答案,但经过测试,我发现我所期望的工作不起作用 T? ,尽管我预计会这样。这是一个可行的选择,但它是否是对原来的改进还是有争议的:

    return rawVal.HasValue
               ? (T)(object)rawVal.Value
               : (T?)null;
    

    原件(错误建议):

    您还应该能够摆脱现有的空检查,并执行以下操作:

    return (T?)((object)rawVal ?? null);
    

    或者这样:

    return (T?)(object)(rawVal ?? null);
    

    这将编译:

    return (T?)(object)rawVal;
    

    但它确实会产生警告。我还没有测试过它是否真的会抛出警告 InvalidCastException 。我认为不会,但是,如果您不喜欢代码中的警告,前面的选项将避免这种情况。

        2
  •  2
  •   Muhammad Sulaiman    4 年前
    return (T?)Enum.Parse(typeof(T), rawVal.Value.ToString());
    

    顺便说一句,您可以将T指定为Enum

    public T? GetEnumValue<T>(int id) where T : Enum
    {
       // ..
    }