C # enum na interface de classe / base?
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 ??+
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;
}
}