Anyone know a good workaround for the lack of an enum generic constraint?

后端 未结 12 1301
情书的邮戳
情书的邮戳 2020-11-22 15:37

What I want to do is something like this: I have enums with combined flagged values.

public static class EnumExtension
{
    public static bool IsSet

        
12条回答
  •  遇见更好的自我
    2020-11-22 15:50

    if someone needs generic IsSet (created out of box on fly could be improved on), and or string to Enum onfly conversion (which uses EnumConstraint presented below):

      public class TestClass
      { }
    
      public struct TestStruct
      { }
    
      public enum TestEnum
      {
        e1,    
        e2,
        e3
      }
    
      public static class TestEnumConstraintExtenssion
      {
    
        public static bool IsSet(this TEnum _this, TEnum flag)
          where TEnum : struct
        {
          return (((uint)Convert.ChangeType(_this, typeof(uint))) & ((uint)Convert.ChangeType(flag, typeof(uint)))) == ((uint)Convert.ChangeType(flag, typeof(uint)));
        }
    
        //public static TestClass ToTestClass(this string _this)
        //{
        //  // #generates compile error  (so no missuse)
        //  return EnumConstraint.TryParse(_this);
        //}
    
        //public static TestStruct ToTestStruct(this string _this)
        //{
        //  // #generates compile error  (so no missuse)
        //  return EnumConstraint.TryParse(_this);
        //}
    
        public static TestEnum ToTestEnum(this string _this)
        {
          // #enum type works just fine (coding constraint to Enum type)
          return EnumConstraint.TryParse(_this);
        }
    
        public static void TestAll()
        {
          TestEnum t1 = "e3".ToTestEnum();
          TestEnum t2 = "e2".ToTestEnum();
          TestEnum t3 = "non existing".ToTestEnum(); // default(TestEnum) for non existing 
    
          bool b1 = t3.IsSet(TestEnum.e1); // you can ommit type
          bool b2 = t3.IsSet(TestEnum.e2); // you can specify explicite type
    
          TestStruct t;
          // #generates compile error (so no missuse)
          //bool b3 = t.IsSet(TestEnum.e1);
    
        }
    
      }
    

    If someone still needs example hot to create Enum coding constraint:

    using System;
    
    /// 
    /// would be same as EnumConstraint_T<Enum>Parse<EnumType>("Normal"),
    /// but writen like this it abuses constrain inheritence on System.Enum.
    /// 
    public class EnumConstraint : EnumConstraint_T
    {
    
    }
    
    /// 
    /// provides ability to constrain TEnum to System.Enum abusing constrain inheritence
    /// 
    /// should be System.Enum
    public abstract class EnumConstraint_T
      where TClass : class
    {
    
      public static TEnum Parse(string value)
        where TEnum : TClass
      {
        return (TEnum)Enum.Parse(typeof(TEnum), value);
      }
    
      public static bool TryParse(string value, out TEnum evalue)
        where TEnum : struct, TClass // struct is required to ignore non nullable type error
      {
        evalue = default(TEnum);
        return Enum.TryParse(value, out evalue);
      }
    
      public static TEnum TryParse(string value, TEnum defaultValue = default(TEnum))
        where TEnum : struct, TClass // struct is required to ignore non nullable type error
      {    
        Enum.TryParse(value, out defaultValue);
        return defaultValue;
      }
    
      public static TEnum Parse(string value, TEnum defaultValue = default(TEnum))
        where TEnum : struct, TClass // struct is required to ignore non nullable type error
      {
        TEnum result;
        if (Enum.TryParse(value, out result))
          return result;
        return defaultValue;
      }
    
      public static TEnum Parse(ushort value)
      {
        return (TEnum)(object)value;
      }
    
      public static sbyte to_i1(TEnum value)
      {
        return (sbyte)(object)Convert.ChangeType(value, typeof(sbyte));
      }
    
      public static byte to_u1(TEnum value)
      {
        return (byte)(object)Convert.ChangeType(value, typeof(byte));
      }
    
      public static short to_i2(TEnum value)
      {
        return (short)(object)Convert.ChangeType(value, typeof(short));
      }
    
      public static ushort to_u2(TEnum value)
      {
        return (ushort)(object)Convert.ChangeType(value, typeof(ushort));
      }
    
      public static int to_i4(TEnum value)
      {
        return (int)(object)Convert.ChangeType(value, typeof(int));
      }
    
      public static uint to_u4(TEnum value)
      {
        return (uint)(object)Convert.ChangeType(value, typeof(uint));
      }
    
    }
    

    hope this helps someone.

提交回复
热议问题