Pergunta

eu tenho problema com enum

Eu preciso fazer uma enumeração na classe base ou interface (mas vazia)

class Base 
{
   public enum Test;
   // ???
}

e depois de enums diffrent faz em algumas classes pai

class Parent1
{
   public enum Test {A, B, C};
}

class Parent2
{
   public enum Test {J, H, K};
}

E agora eu tenho próxima aula com método quando eu tenho que usar enum

class Test<T>
{
   public void Foo(Test enum)
   {
      int value = (int) enum;
      // ...
   }
}

É Existe alguma maneira de fazer algo assim?

Se não eu tenho que usar ints estáticos em todas as classes ...

class Parent1
{
   public static int A = 0;
   public static int B = 5;
   public static int C = 7;
}

class Parent2
{
   public static int J = 1;
   public static int H = 3;
   public static int K = 6;
}

class Test<T>
{
   public void Foo(int enum)
   {
      int value = enum;
      // ...
   }
}

I't parece ruim em código ... em algumas aulas eu tenho que usar ~ 20 variáveis ??+

Foi útil?

Solução

Não existe tal coisa como um enum resumo (que pode ter diferentes implementações em subclasses) - mas os genéricos pode ser uma opção:

class Base<T> where T : struct {
    private T value;
    public void Foo(T value) {
        this.value = value;
    }
}
class Parent1 : Base<Parent1.Enum1> {
    public enum Enum1 {A, B, C};
}
class Parent2 : Base<Parent2.Enum2> {
    public enum Enum2 { J, H, K };
}

O único problema é que este não impõe que apenas enums são utilizáveis ??- você pode fazer isso em tempo de execução, embora - por exemplo, em um tipo initializer:

static Base() {
    if (!typeof(T).IsEnum) throw new InvalidOperationException(
         typeof(T).Name + " is not an enum");
}

Outras dicas

É incrível como muitas vezes eu encontro pessoas discutindo sobre por algo é necessária, em vez de responder a pergunta ou manter schtum - seja de que seria mais útil do que desperdiçar questionamento tempo por um determinado inquérito foi feito em detrimento de um inquérito diferente o entrevistado realmente sabe a resposta. Respondendo a perguntas que não foram feitas não é de forma útil, caras OK ?!

Voltando ao assunto em mãos, eu bati exatamente o cenário acima, esta manhã, e posso entender por que seria útil para ser capaz de definir uma enumeração em uma interface ou classe base, em seguida, re-definir esse mesmo -named enum em uma classe que deriva a partir de qualquer base ou de interface. Uma utilização para a concepção tal é no objeto-relacional mapeamento e de controlo de ligação. Você pode ter um conjunto de enumerações que descrevem quais as propriedades das suas classes derivadas são bindable a que tipos de controle, tais como:

    public enum WebControlTextBoxProperties { }

    public enum WebControlLabelProperties { }

... e assim por diante.

Uma vez que você não sabe exatamente quais as propriedades existirá para uma determinada classe derivada até que a herança pertinente produz efeitos, mas desde que você também pode desejar ter métodos consistentes que consomem acima Enums em sua base ou interface, é um perfeitamente projeto -Válido que esperar para ser capaz de definir que o Enum existirá na base / interface, mas definir exatamente o que os membros tem em um contexto específico em quaisquer classes derivadas .

Eu realmente gostaria que isso fosse possível em C # como é em VB, porque seria um recurso muito útil.

Você deve ser capaz de declarar um enum em uma classe base e, em seguida, alterar os valores por isto classe derivada.

class MyClass
{
    public enum TestEnum { }

    public MyClass()
    {
    }
}

class MyDerivedClass
{
    public enum TestEnum { value1, value2, value3 }

    public MyDerivedClass()
    {
    }
}

classe MyDervied teria acesso a TestEnum.value1, TestEnum.value2, TestEnum.value3, onde, como MyClass só teria acesso ao tipo.

No entanto, pessoalmente, não vejo a vantagem de fazer isso eu iria declarar todos os valores da enumeração na classe base e só usar os que eu preciso por classe.

James.

Não, ele não pode ser feito.

Note que muitos enums geralmente indicam um problema com o design (muitas construções switch, por exemplo). Confira neste link para ver um exemplo de como refatorar este: Substituir condicional com polimorfismo .

Não, não há nenhuma maneira de impor qualquer coisa estática em uma interface.

Talvez você precisa repensar o seu design.

Por que não consigo definir a enumeração na classe base:

class Base 
{
   public enum Test {A, B, C, J, H, K};
}

e utilizar apenas os membros relevantes do ENUM em classes derivadas?

Eu estou no trabalho, portanto, não pode elaborar totalmente, mas isso é possível até certo ponto. A desvantagem para o código abaixo é que não consegues cadeia enums juntos, como TextBoxProperties e MyCustomTextBoxProperties: TextboxProperties

Aqui está o código.

    public enum Test
    {

    }

    public enum ThisTest
    {
        MyVal1,
        MyVal2,
        MyVal3
    }

    public abstract class MyBase
    {
        public Test MyEnum { get; set; }
    }

    public class MyDerived : MyBase
    {
        public new ThisTest MyEnum { get; set; }
    }

YOU CAN RESUMO AN ENUM!

Por que as pessoas insistem em reivindicar coisas são impossíveis sem verificar alguma coisa?

Claro, a documentação do .NET é um pouco vago sobre isso, mas a classe System.Enum, é a abstração de uma enumeração. Você pode usar System.Enum como uma variável que só aceitará valores de enumeração, e você pode acessar o nome ou o tipo de valor valor da enumeração por meio desta classe.

Por exemplo:

        // abstracted enumeration value
        Enum abstractEnum = null;

        // set to the Console-Color enumeration value "Blue";
        abstractEnum = System.ConsoleColor.Blue;

        // the defined value of "ConsoleColor.Blue" is "9":
        // you can get the value via the ToObject method:
        Console.WriteLine((int)Enum.ToObject(abstractEnum.GetType(), abstractEnum));

        // or via the GetHashCode() method:
        Console.WriteLine(abstractEnum.GetHashCode());

        // the name can also be acessed:
        Console.WriteLine(Enum.GetName(abstractEnum.GetType(), abstractEnum));

A saída do código acima:

9

9

Blue

Eu gosto a resposta aceita de @ Marc Gravell. Como eu sou um stackoverflow-novato eu não estou autorizado a comentários. Mas eu gostaria de acrescentar, que é útil para verificar também o subjacente tipo do enum - especialmente se você usar as operações sinalizador de atributo e pré-formas bit a bit flag-Testing ...

if ( !typeof(T).IsEnum || typeof(int) != Enum.GetUnderlyingType(typeof(T)) )
{
     throw new InvalidOperationException( typeof(T).Name + " is not an enum");
}

Aqui está uma solução que funciona para mim:

na classe pai, declarar o campo como int, não como enum:

protected int state;

para a classe pai ainda pode usar esse valor como um int, a fim de proporcionar a serialização e deserializion deste valor para o disco.

Então, que substitui a classe pode fazer isso:

enum states{
  state1, state2
}

this.state = state1.toInt();

e pode acessar o valor real como esta:

...
if (this.state == states.state1.toInt()){
      ...
}
else{
     ...
}

onde toInt () é definido em uma classe de estática como se segue:

public static class Utils
{

    public static int toInt(this state s)
    {
        return (int)s;
    }
 }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top