Enum "Наследование" - PullRequest
       40

Enum "Наследование"

357 голосов
/ 16 апреля 2009

У меня есть перечисление в низкоуровневом пространстве имен. Я хотел бы предоставить класс или перечисление в пространстве имен среднего уровня, которое «наследует» перечисление низкого уровня.

namespace low
{
   public enum base
   {
      x, y, z
   }
}

namespace mid
{
   public enum consume : low.base
   {
   }
}

Я надеюсь, что это возможно, или, возможно, какой-то класс, который может заменить потребление перечисления, который обеспечит уровень абстракции для перечисления, но все же позволит экземпляру этого класса получить доступ к перечислению.

Мысли

EDIT: Одна из причин, по которой я не просто переключил это на consts в классах, состоит в том, что перечисление низкого уровня необходимо для службы, которую я должен потреблять. Мне дали WSDL и XSD, которые определяют структуру как перечисление. Услуга не может быть изменена.

Ответы [ 13 ]

1 голос
/ 16 апреля 2009

Перечисления не являются реальными классами, даже если они выглядят так. Внутренне они обрабатываются так же, как и их базовый тип (по умолчанию Int32). Следовательно, вы можете сделать это только путем «копирования» отдельных значений из одного перечисления в другое и приведения их к целому числу, чтобы сравнить их на равенство.

0 голосов
/ 02 июля 2017

Я также хотел перегрузить Enums и создал смесь ответа 'Семь' на этой странице и ответа 'Merlyn Morgan-Graham' на дублирующем посте этого плюс пара улучшений.
Основные преимущества моего решения перед другими:

  • автоматическое увеличение базового значения int
  • автоматическое именование

Это готовое решение, которое может быть непосредственно вставлено в ваш проект. Он предназначен для моих нужд, поэтому, если вам не нравятся некоторые его части, просто замените их собственным кодом.

Во-первых, существует базовый класс CEnum, от которого должны наследоваться все пользовательские перечисления. Он имеет базовую функциональность, аналогичную типу .net Enum:

public class CEnum
{
  protected static readonly int msc_iUpdateNames  = int.MinValue;
  protected static int          ms_iAutoValue     = -1;
  protected static List<int>    ms_listiValue     = new List<int>();

  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<CEnum> 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;
    }
  }
}

Во-вторых, здесь есть 2 производных класса Enum. Все производные классы нуждаются в некоторых основных методах, чтобы работать как положено. Это всегда один и тот же стандартный код; Я еще не нашел способ передать его в базовый класс. Код первого уровня наследования незначительно отличается от всех последующих уровней.

public class CEnumResult : CEnum
{
  private   static List<CEnumResult>  ms_listoValue = new List<CEnumResult>();

  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<CEnumResult> listoValue = new List<CEnumResult> ();
    listoValue.AddRange (ms_listoValue);
    return listoValue.ToArray ();
  }
}

public class CEnumResultClassCommon : CEnumResult
{
  private   static List<CEnumResultClassCommon> ms_listoValue = new List<CEnumResultClassCommon>();

  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<CEnumResult> listoValue = new List<CEnumResult> (CEnumResult.GetValues ());
    listoValue.AddRange (ms_listoValue);
    return listoValue.ToArray ();
  }
}

Классы были успешно протестированы с использованием следующего кода:

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
}
0 голосов
/ 14 декабря 2011

Вы можете выполнять наследование в enum, однако оно ограничено только следующими типами. int, uint, byte, sbyte, short, ushort, long, ulong

* 1003 Е.Г. *

public enum Car:int{
Toyota,
Benz,
}
...