Enum “herança”

391

Eu tenho um enum em um espaço para nome de baixo nível. Eu gostaria de fornecer uma classe ou enum em um espaço para nome de nível médio que "herda" a enum de baixo nível.

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

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

Espero que isso seja possível, ou talvez algum tipo de classe que substitua o consumo de enum, o que fornecerá uma camada de abstração para o enum, mas ainda permita que uma instância dessa classe acesse o enum.

Pensamentos?

EDIT: Uma das razões pelas quais eu não mudei isso para consts nas aulas é que o enum de baixo nível é necessário para um serviço que devo consumir. Recebi os WSDLs e os XSDs, que definem a estrutura como uma enumeração. O serviço não pode ser alterado.

CodeMonkey1313
fonte
11
Uma opção é codeproject.com/Articles/20805/Enhancing-C-Enums
Walter Vehoeven

Respostas:

462

Isso não é possível. Enums não podem herdar de outros enums. De fato, todas as enums devem realmente herdar System.Enum. O C # permite que a sintaxe altere a representação subjacente dos valores de enum que se parece com herança, mas na realidade eles ainda herdam do System.enum.

Consulte a seção 8.5.2 da especificação da CLI para obter detalhes completos. Informações relevantes da especificação

  • Todas as enums devem derivar de System.Enum
  • Por causa do exposto, todas as enumerações são tipos de valor e, portanto, seladas
JaredPar
fonte
2
E todos os tipos de valores derivam de System.ValueType
Raz Megrelidze
4
Tenho que mencionar que a resposta de @Seven é uma solução legítima: stackoverflow.com/a/4042826/538387
Tohid:
mas a resposta de @ Steven não pode ser usada em switchsituações.
Zionpi 11/04/19
@ zionpi sim, mas observe que (acredito) o switch padrão é compilado no mesmo código IL como um bloco completo if, else if, else: o que eu acho que tem uma sintaxe melhor e melhor de qualquer maneira. Você perde a capacidade de o recarregador / VS completar automaticamente todas as declarações de caso, mas acho que esse não é o fim do mundo. É uma preferência pessoal, mas não sou fã da declaração do switch.
MemeDeveloper 04/07/19
165

Você pode conseguir o que deseja com as classes:

public class Base
{
    public const int A = 1;
    public const int B = 2;
    public const int C = 3;
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

Agora você pode usar essas classes semelhantes como quando eram enumerações:

int i = Consume.B;

Atualização (após a atualização da pergunta):

Se você atribuir os mesmos valores int às constantes, conforme definido na enum existente, poderá converter entre a enum e as constantes, por exemplo:

public enum SomeEnum // this is the existing enum (from WSDL)
{
    A = 1,
    B = 2,
    ...
}
public class Base
{
    public const int A = (int)SomeEnum.A;
    //...
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;
M4N
fonte
8
Como você enumera os campos nessa classe então? Para mim, esse é um comportamento importante de uma enumeração:Enum.GetValues(typeof(MyEnum)
Mike de Klerk 3/15
11
Você pode usar a reflexão: void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
mnieto
2
Você precisaria garantir que a reunião de propriedades com reflexão ignore as propriedades herdadas de Object.
Robert
A reflexão é super feia para essa tarefa.
dylanh724
11
Não há necessidade de usar o Reflection, a implementação em codeproject.com/Articles/20805/Enhancing-C-Enums é uma boa maneira de fazê-lo, já que os objetos estão sendo criados, eles são adicionados a uma lista e essa lista pode ser usada para retornar uma lista de tipos de objetos. Ao misturá-lo com herança, você terá que verificar se está usando a lista correta para as classes herdadas.
PBo 3/09/18
112

A resposta curta é não. Você pode jogar um pouco, se quiser:

Você sempre pode fazer algo assim:

private enum Base
{
    A,
    B,
    C
}

private enum Consume
{
    A = Base.A,
    B = Base.B,
    C = Base.C,
    D,
    E
}

Mas, não funciona tão bem porque Base.A! = Consume.A

Você sempre pode fazer algo assim:

public static class Extensions
{
    public static T As<T>(this Consume c) where T : struct
    {
        return (T)System.Enum.Parse(typeof(T), c.ToString(), false);
    }
}

Para cruzar entre Base e Consumir ...

Você também pode converter os valores das enumerações em ints e compará-los como ints em vez de enum, mas esse tipo de coisa também é péssimo.

O método de extensão return deve digitar cast e digitar T.

Brian Genisio
fonte
4
Eu gosto disso, cara. Usei esse conceito para fazer bolhas de algumas enumerações do meu ORM para minha interface pública (para aqueles sem a referência do ORM).
ObjectType
5
Pode-se lançar enums para comparação com o trabalho:Base.A == (Base)Consume.A
Kresimir 29/08
11
Use (decimal) Base.A == (decimal) Consume.A. Motivo: é assim que a combinação de sinalizador / máscara de bits funciona (por exemplo, em Enum.IsDefined msdn.microsoft.com/en-us/library/… ). Portanto, uma enumeração pode ser definida como um número inteiro não definido na enumeração. Teste de consumo = 123456;
TamusJRoyce 13/04
3
@TamusJRoyce decimal? intfaria muito mais sentido. Quando um enum teria uma parte fracionária!?!?!
ErikE
Pelo menos, isso garante que as constantes de enum correspondentes tenham o mesmo valor inteiro. Afinal, enums são apenas um conjunto de constantes inteiras. O C # não impõe que os valores atribuídos sejam constantes de enumeração vaild, ou seja, enumerações não são do tipo seguro no sentido estrito.
Olivier Jacot-Descombes 02/02
98

As soluções acima, usando classes com constantes int, não possuem segurança de tipo. Ou seja, você pode inventar novos valores realmente não definidos na classe. Além disso, não é possível, por exemplo, escrever um método usando uma dessas classes como entrada.

Você precisaria escrever

public void DoSomethingMeaningFull(int consumeValue) ...

No entanto, existe uma solução baseada em classe dos velhos tempos de Java, quando não havia enumerações disponíveis. Isso fornece um comportamento quase enum. A única ressalva é que essas constantes não podem ser usadas em uma instrução switch.

public class MyBaseEnum
{
    public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
    public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
    public static readonly MyBaseEnum C = new MyBaseEnum( 3 );

    public int InternalValue { get; protected set; }

    protected MyBaseEnum( int internalValue )
    {
        this.InternalValue = internalValue;
    }
}

public class MyEnum : MyBaseEnum
{
    public static readonly MyEnum D = new MyEnum( 4 );
    public static readonly MyEnum E = new MyEnum( 5 );

    protected MyEnum( int internalValue ) : base( internalValue )
    {
        // Nothing
    }
}

[TestMethod]
public void EnumTest()
{
    this.DoSomethingMeaningful( MyEnum.A );
}

private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
    // ...
    if( enumValue == MyEnum.A ) { /* ... */ }
    else if (enumValue == MyEnum.B) { /* ... */ }
    // ...
}
Sete
fonte
7
Eu acho que esta é a resposta certa. Você não pode ter herança para o Enum, mas isso pode permitir que você gerencie-o!
robob
11
Legal e Limpo. +1. Apenas uma dica, você realmente não precisa do valor int.
Ignacio Soler Garcia
11
Eu nunca pensei em enumerações como se você pudesse dizer FileOpenMode.Read> FileOpenMode.Write. Se for esse o caso, você precisará de um IEqualityComparer int ou ainda melhor para essa enumeração. Saudações.
Ignacio Soler Garcia
3
@binki usando random object's faria os valores diferentes para cada instanciação da montagem, para que eles não possam ser serializados.
Ivan_pozdeev
2
Mas isso não permite que você "ligue" o MyEnum, pois não? Quero dizer que é principalmente porque eu uso enums ...
MemphiZ
13

Ignorando o fato de que base é uma palavra reservada, você não pode herdar enum.

A melhor coisa que você pode fazer é algo assim:

public enum Baseenum
{
   x, y, z
}

public enum Consume
{
   x = Baseenum.x,
   y = Baseenum.y,
   z = Baseenum.z
}

public void Test()
{
   Baseenum a = Baseenum.x;
   Consume newA = (Consume) a;

   if ((Int32) a == (Int32) newA)
   {
   MessageBox.Show(newA.ToString());
   }
}

Como todos são do mesmo tipo base (ou seja: int), você pode atribuir o valor de uma instância de um tipo à outra que é convertida. Não é o ideal, mas funciona.

Pascal
fonte
2
base é reservado, mas de base não é
erikkallen
2
Ele está se referindo ao uso do OP de base como o nome enum, é apenas um exemplo de nome Tenho certeza
John Rasch
O mesmo que a resposta de Genisio.
Nawfal #
6

Eu sei que essa resposta está meio atrasada, mas foi o que acabei fazendo:

public class BaseAnimal : IEquatable<BaseAnimal>
{
    public string Name { private set; get; }
    public int Value { private set; get; }

    public BaseAnimal(int value, String name)
    {
        this.Name = name;
        this.Value = value;
    }

    public override String ToString()
    {
        return Name;
    }

    public bool Equals(BaseAnimal other)
    {
        return other.Name == this.Name && other.Value == this.Value;
    }
}

public class AnimalType : BaseAnimal
{
    public static readonly BaseAnimal Invertebrate = new BaseAnimal(1, "Invertebrate");

    public static readonly BaseAnimal Amphibians = new BaseAnimal(2, "Amphibians");

    // etc        
}

public class DogType : AnimalType
{
    public static readonly BaseAnimal Golden_Retriever = new BaseAnimal(3, "Golden_Retriever");

    public static readonly BaseAnimal Great_Dane = new BaseAnimal(4, "Great_Dane");

    // etc        
}

Então eu sou capaz de fazer coisas como:

public void SomeMethod()
{
    var a = AnimalType.Amphibians;
    var b = AnimalType.Amphibians;

    if (a == b)
    {
        // should be equal
    }

    // call method as
    Foo(a);

    // using ifs
    if (a == AnimalType.Amphibians)
    {
    }
    else if (a == AnimalType.Invertebrate)
    {
    }
    else if (a == DogType.Golden_Retriever)
    {
    }
    // etc          
}

public void Foo(BaseAnimal typeOfAnimal)
{
}
Tono Nam
fonte
2
Os números mágicos podem ser substituídos por objetos conforme stackoverflow.com/questions/757684/… . Mas, nesse caso em particular, você pode obter o melhor dos dois mundos usando os recursos da nomenclatura biológica existente para garantir a exclusividade.
ivan_pozdeev
4

Foi o que eu fiz. O que eu fiz de diferente é usar o mesmo nome e a newpalavra-chave no "consumir" enum. Como o nome do enumé o mesmo, você pode usá-lo sem pensar e estará correto. Além disso, você obtém intellisense. Você só precisa tomar cuidado ao configurar que os valores são copiados da base e mantê-los sincronizados. Você pode ajudar isso junto com os comentários do código. Essa é outra razão pela qual, no banco de dados, ao armazenar enumvalores, eu sempre guardo a string, não o valor. Porque se você estiver usando valores inteiros crescentes atribuídos automaticamente, eles poderão mudar com o tempo.

// Base Class for balls 
public class BaseBall
{
    // keep synced with subclasses!
    public enum Sizes
    {
        Small,
        Medium,
        Large
    }
}

public class VolleyBall : BaseBall
{
    // keep synced with base class!
    public new enum Sizes
    {
        Small = BaseBall.Sizes.Small,
        Medium = BaseBall.Sizes.Medium,
        Large = BaseBall.Sizes.Large,
        SmallMedium,
        MediumLarge,
        Ginormous
    }
}
toddmo
fonte
2
Considere definir um intervalo diferente para os novos valores na classe derivada (por exemplo SmallMedium = 100,), para manter a compatibilidade com versões mais antigas do seu software ao adicionar novos valores à classe base. Por exemplo, adicionar um Hugetamanho à sua enum base seria atribuído 4ao seu valor, mas 4já é usado SmallMediumna classe derivada.
Roberto
11
@ Roberto, Para resolver isso, eu nunca persisto valores enum, mas apenas os nomes. E mantê-los sincronizados é um requisito aqui. Assim, adicionando Hugena classe base seria necessário um Hugena subclasse antesSmallMedium
toddmo
2
BaseBallpode não ser o nome mais inteligente aqui. Isto é confuso. Desde que uma bola de beisebol é realmente uma coisa. Se você sente falta de que essa é apenas uma classe básica para a bola, parece muito estranho que um voleibol herda de um beisebol fisicamente menor :). Minha sugestão é usar apenasBall
Nick N.
3

Solução alternativa

Na minha empresa, evitamos "pular projetos" para chegar a projetos de nível inferior não comuns. Por exemplo, nossa camada de apresentação / API só pode fazer referência a nossa camada de domínio e a camada de domínio pode fazer referência apenas à camada de dados.

No entanto, esse é um problema quando há enumerações que precisam ser referenciadas pelas camadas de apresentação e domínio.

Aqui está a solução que implementamos (até agora). É uma solução muito boa e funciona bem para nós. As outras respostas estavam acertando tudo isso.

A premissa básica é que enums não podem ser herdadas - mas classes podem. Assim...

// In the lower level project (or DLL)...
public abstract class BaseEnums
{
    public enum ImportanceType
    {
        None = 0,
        Success = 1,
        Warning = 2,
        Information = 3,
        Exclamation = 4
    }

    [Flags]
    public enum StatusType : Int32
    {
        None = 0,
        Pending = 1,
        Approved = 2,
        Canceled = 4,
        Accepted = (8 | Approved),
        Rejected = 16,
        Shipped = (32 | Accepted),
        Reconciled = (64 | Shipped)
    }

    public enum Conveyance
    {
        None = 0,
        Feet = 1,
        Automobile = 2,
        Bicycle = 3,
        Motorcycle = 4,
        TukTuk = 5,
        Horse = 6,
        Yak = 7,
        Segue = 8
    }

Então, para "herdar" as enumerações em outro projeto de nível superior ...

// Class in another project
public sealed class SubEnums: BaseEnums
{
   private SubEnums()
   {}
}

Isso tem três vantagens reais ...

  1. As definições de enumeração são automaticamente as mesmas nos dois projetos - por definição.
  2. Quaisquer alterações nas definições de enumeração são ecoadas automaticamente na segunda sem precisar fazer modificações na segunda classe.
  3. As enumerações são baseadas no mesmo código - para que os valores possam ser facilmente comparados (com algumas ressalvas).

Para referenciar as enumerações no primeiro projeto , você pode usar o prefixo da classe: BaseEnums.StatusType.Pending ou adicionar um "using static BaseEnums;" declaração para seus usos.

No segundo projeto, ao lidar com a classe herdada, no entanto, não consegui trabalhar com a abordagem "using static ..." , portanto todas as referências às "enumerações herdadas" seriam prefixadas com a classe, por exemplo, SubEnums.StatusType.Pending . Se alguém tiver uma maneira de permitir que a abordagem "usando estática" seja usada no segundo projeto, informe-me.

Estou certo de que isso pode ser aprimorado para torná-lo ainda melhor - mas isso realmente funciona e eu usei essa abordagem em projetos de trabalho.

Faça um voto positivo se achar útil.

Thomas Phaneuf
fonte
2

Eu também queria sobrecarregar a Enums e criei uma mistura da resposta de 'Seven' nesta página e da resposta de 'Merlyn Morgan-Graham' em um post duplicado , além de algumas melhorias.
Principais vantagens da minha solução sobre as demais:

  • incremento automático do valor int subjacente
  • nomeação automática

Esta é uma solução pronta para uso e pode ser inserida diretamente no seu projeto. Ele foi projetado de acordo com minhas necessidades; portanto, se você não gostar de algumas partes, substitua-as por seu próprio código.

Primeiro, há a classe base da CEnumqual todas as enumerações personalizadas devem herdar. Possui a funcionalidade básica, semelhante ao Enumtipo .net :

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

Em segundo lugar, aqui estão duas classes Enum derivadas. Todas as classes derivadas precisam de alguns métodos básicos para funcionar como esperado. É sempre o mesmo código padrão; Ainda não encontrei uma maneira de terceirizá-lo para a classe base. O código do primeiro nível de herança difere um pouco de todos os níveis subsequentes.

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 ();
  }
}

As classes foram testadas com sucesso com o seguinte código:

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
}
Tobias Knauss
fonte
1

Enums não são classes reais, mesmo que pareçam. Internamente, eles são tratados como seu tipo subjacente (por padrão, Int32). Portanto, você só pode fazer isso "copiando" valores únicos de uma enumeração para outra e convertendo-os em seu número inteiro para compará-los quanto à igualdade.

Lucero
fonte
1

As enumerações não podem ser derivadas de outras enumerações, mas apenas de int, uint, short, ushort, long, ulong, byte e sbyte.

Como Pascal disse, você pode usar os valores ou constantes de outros enum para inicializar um valor de enum, mas é isso.

Jeroen Landheer
fonte
8
É um pouco inadequado devido à sintaxe do c #, mas os enum não podem herdar int, uint, etc ... Sob o capô, eles ainda herdam do System.Enum. É que o membro que representa o enum é digitado ao int, uint, etc ...
JaredPar
@JaredPar. Quando um enum é derivado de um uint, significa que seus valores são todos uint etc. Por padrão, um enum herda int. (Dê uma olhada na especificação C #, enum SomeEnum: uint {...} realmente funciona.)
Jeroen Landheer
4
Na verdade não. Ele herda System.enum. Como foi publicado antes e com mais frequência aqui, o que você acha que é herança é apenas uma dusambigüidade linguística no csharp.
TomTom
1

outra solução possível:

public enum @base
{
    x,
    y,
    z
}

public enum consume
{
    x = @base.x,
    y = @base.y,
    z = @base.z,

    a,b,c
}

// TODO: Add a unit-test to check that if @base and consume are aligned

HTH

ShloEmi
fonte
1

Isso não é possível (como @JaredPar já mencionado). Tentar colocar a lógica para solucionar isso é uma prática ruim. Caso você tenha um base classque tenha um enum, deve listar tudo o que é possível enum-valueslá e a implementação da classe deve funcionar com os valores que ele conhece.

Por exemplo, suponha que você tenha uma classe base BaseCataloge ela tenha um enum ProductFormats( Digital, Physical). Então você pode ter um MusicCatalogou BookCatalogque poderia conter ambos Digitale Physicalprodutos, mas se a classe for ClothingCatalog, ela deverá conter apenas Physicalprodutos.

Jaider
fonte
1

Sei que estou um pouco atrasado para esta festa, mas aqui estão meus dois centavos.

Estamos todos claros de que a herança do Enum não é suportada pela estrutura. Algumas soluções muito interessantes foram sugeridas neste tópico, mas nenhuma delas parecia muito com o que eu estava procurando, então eu mesmo tentei.

Apresentando: ObjectEnum

Você pode verificar o código e a documentação aqui: https://github.com/dimi3tron/ObjectEnum .

E o pacote aqui: https://www.nuget.org/packages/ObjectEnum

Ou apenas instale: Install-Package ObjectEnum

Em resumo, ObjectEnum<TEnum>atua como um invólucro para qualquer enumeração. Substituindo GetDefinedValues ​​() nas subclasses, é possível especificar quais valores de enumeração são válidos para essa classe específica.

Foram adicionadas várias sobrecargas de operador para fazer com que uma ObjectEnum<TEnum>instância se comporte como se fosse uma instância da enum subjacente, tendo em mente as restrições de valor definidas. Isso significa que você pode comparar facilmente a instância com um valor int ou enum e, portanto, usá-la em um caso de opção ou em qualquer outra condição.

Gostaria de consultar a referência acima do repositório do github para exemplos e mais informações.

Espero que você ache isso útil. Sinta-se à vontade para comentar ou abrir um problema no github para mais pensamentos ou comentários.

Aqui estão alguns breves exemplos do que você pode fazer com ObjectEnum<TEnum>:

var sunday = new WorkDay(DayOfWeek.Sunday); //throws exception
var monday = new WorkDay(DayOfWeek.Monday); //works fine
var label = $"{monday} is day {(int)monday}." //produces: "Monday is day 1."
var mondayIsAlwaysMonday = monday == DayOfWeek.Monday; //true, sorry...

var friday = new WorkDay(DayOfWeek.Friday);

switch((DayOfWeek)friday){
    case DayOfWeek.Monday:
        //do something monday related
        break;
        /*...*/
    case DayOfWeek.Friday:
        //do something friday related
        break;
}
Dimitri Troncquo
fonte
-8

Você pode executar herança em enum, no entanto, é limitado apenas aos seguintes tipos. int, uint, byte, sbyte, curto, ushort, longo, ulong

Por exemplo

public enum Car:int{
Toyota,
Benz,
}
Sriwantha Attanayake
fonte
2
Eu acho que o OP estava pedindo para herdar uma enumeração de outro, não apenas de um tipo numérico de base (que todos os enums fazer em C #, implícita ou explicitamente.)
reirab