Enum “Inheritance”

后端 未结 15 1440
野性不改
野性不改 2020-11-22 07:21

I have an enum in a low level namespace. I\'d like to provide a class or enum in a mid level namespace that \"inherits\" the low level enum.

namespace low
{
         


        
15条回答
  •  南笙
    南笙 (楼主)
    2020-11-22 08:14

    I also wanted to overload Enums and created a mix of the answer of 'Seven' on this page and the answer of 'Merlyn Morgan-Graham' on a duplicate post of this, plus a couple of improvements.
    Main advantages of my solution over the others:

    • automatic increment of the underlying int value
    • automatic naming

    This is an out-of-the-box solution and may be directly inserted into your project. It is designed to my needs, so if you don't like some parts of it, just replace them with your own code.

    First, there is the base class CEnum that all custom enums should inherit from. It has the basic functionality, similar to the .net Enum type:

    public class CEnum
    {
      protected static readonly int msc_iUpdateNames  = int.MinValue;
      protected static int          ms_iAutoValue     = -1;
      protected static List    ms_listiValue     = new List();
    
      public int Value
      {
        get;
        protected set;
      }
    
      public string Name
      {
        get;
        protected set;
      }
    
      protected CEnum ()
      {
        CommonConstructor (-1);
      }
    
      protected CEnum (int i_iValue)
      {
        CommonConstructor (i_iValue);
      }
    
      public static string[] GetNames (IList i_listoValue)
      {
        if (i_listoValue == null)
          return null;
        string[] asName = new string[i_listoValue.Count];
        for (int ixCnt = 0; ixCnt < asName.Length; ixCnt++)
          asName[ixCnt] = i_listoValue[ixCnt]?.Name;
        return asName;
      }
    
      public static CEnum[] GetValues ()
      {
        return new CEnum[0];
      }
    
      protected virtual void CommonConstructor (int i_iValue)
      {
        if (i_iValue == msc_iUpdateNames)
        {
          UpdateNames (this.GetType ());
          return;
        }
        else if (i_iValue > ms_iAutoValue)
          ms_iAutoValue = i_iValue;
        else
          i_iValue = ++ms_iAutoValue;
    
        if (ms_listiValue.Contains (i_iValue))
          throw new ArgumentException ("duplicate value " + i_iValue.ToString ());
        Value = i_iValue;
        ms_listiValue.Add (i_iValue);
      }
    
      private static void UpdateNames (Type i_oType)
      {
        if (i_oType == null)
          return;
        FieldInfo[] aoFieldInfo = i_oType.GetFields (BindingFlags.Public | BindingFlags.Static);
    
        foreach (FieldInfo oFieldInfo in aoFieldInfo)
        {
          CEnum oEnumResult = oFieldInfo.GetValue (null) as CEnum;
          if (oEnumResult == null)
            continue;
          oEnumResult.Name = oFieldInfo.Name;
        }
      }
    }
    

    Secondly, here are 2 derived Enum classes. All derived classes need some basic methods in order to work as expected. It's always the same boilerplate code; I haven't found a way yet to outsource it to the base class. The code of the first level of inheritance differs slightly from all subsequent levels.

    public class CEnumResult : CEnum
    {
      private   static List  ms_listoValue = new List();
    
      public    static readonly CEnumResult Nothing         = new CEnumResult (  0);
      public    static readonly CEnumResult SUCCESS         = new CEnumResult (  1);
      public    static readonly CEnumResult UserAbort       = new CEnumResult ( 11);
      public    static readonly CEnumResult InProgress      = new CEnumResult (101);
      public    static readonly CEnumResult Pausing         = new CEnumResult (201);
      private   static readonly CEnumResult Dummy           = new CEnumResult (msc_iUpdateNames);
    
      protected CEnumResult () : base ()
      {
      }
    
      protected CEnumResult (int i_iValue) : base (i_iValue)
      {
      }
    
      protected override void CommonConstructor (int i_iValue)
      {
        base.CommonConstructor (i_iValue);
    
        if (i_iValue == msc_iUpdateNames)
          return;
        if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
          ms_listoValue.Add (this);
      }
    
      public static new CEnumResult[] GetValues ()
      {
        List listoValue = new List ();
        listoValue.AddRange (ms_listoValue);
        return listoValue.ToArray ();
      }
    }
    
    public class CEnumResultClassCommon : CEnumResult
    {
      private   static List ms_listoValue = new List();
    
      public    static readonly CEnumResult Error_InternalProgramming           = new CEnumResultClassCommon (1000);
    
      public    static readonly CEnumResult Error_Initialization                = new CEnumResultClassCommon ();
      public    static readonly CEnumResult Error_ObjectNotInitialized          = new CEnumResultClassCommon ();
      public    static readonly CEnumResult Error_DLLMissing                    = new CEnumResultClassCommon ();
      // ... many more
      private   static readonly CEnumResult Dummy                               = new CEnumResultClassCommon (msc_iUpdateNames);
    
      protected CEnumResultClassCommon () : base ()
      {
      }
    
      protected CEnumResultClassCommon (int i_iValue) : base (i_iValue)
      {
      }
    
      protected override void CommonConstructor (int i_iValue)
      {
        base.CommonConstructor (i_iValue);
    
        if (i_iValue == msc_iUpdateNames)
          return;
        if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
          ms_listoValue.Add (this);
      }
    
      public static new CEnumResult[] GetValues ()
      {
        List listoValue = new List (CEnumResult.GetValues ());
        listoValue.AddRange (ms_listoValue);
        return listoValue.ToArray ();
      }
    }
    

    The classes have been successfully tested with follwing code:

    private static void Main (string[] args)
    {
      CEnumResult oEnumResult = CEnumResultClassCommon.Error_Initialization;
      string sName = oEnumResult.Name;   // sName = "Error_Initialization"
    
      CEnum[] aoEnumResult = CEnumResultClassCommon.GetValues ();   // aoEnumResult = {testCEnumResult.Program.CEnumResult[9]}
      string[] asEnumNames = CEnum.GetNames (aoEnumResult);
      int ixValue = Array.IndexOf (aoEnumResult, oEnumResult);    // ixValue = 6
    }
    

提交回复
热议问题