Frage

ich habe Problem mit Enum

Ich brauche eine Enum in Basisklasse oder Schnittstelle machen (aber leeren)

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

und nach diffrent Aufzählungen in einigen Elternklassen machen

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

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

, und ich habe jetzt nächste Klasse mit der Methode, wenn ich Enum müssen verwenden

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

Es ist es eine Möglichkeit, so etwas zu tun?

Wenn nicht, ich habe in jeder Klasse statische ints verwenden ...

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 sieht in Code schlecht ... in einigen Klassen ich habe ~ verwenden 20 + Variablen

War es hilfreich?

Lösung

Es gibt nicht so etwas wie eine abstrakte Enum (dass verschiedene Implementierungen in Unterklassen haben kann) - aber Generika kann eine Option sein:

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

Das einzige Problem ist, dass diese Durchsetzung nicht, dass nur Aufzählungen verwendbar sind - Sie dies zur Laufzeit tun, wenn - zum Beispiel in einem Typeninitialisierer:

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

Andere Tipps

Es ist erstaunlich, wie oft ich finde, die Leute über das Argument Warum etwas benötigt wird, anstatt die Beantwortung der Frage schtum gefragt oder halten - entweder von denen wäre hilfreicher als Zeit zu verschwenden in Frage warum eine bestimmte Anfrage in Präferenz zu einer anderen Untersuchung wurde die Befragte gemacht tatsächlich kennt die Antwort auf. Beantwortung von Fragen, die nicht gefragt haben, in keiner Weise hilfreich, OK Jungs ist ?!

zurück zum Thema an die Hand bekommen, habe ich traf genau das oben beschriebene Szenario an diesem Morgen, und kann verstehen, warum es sinnvoll wäre, in der Lage sein eine Enum in einer Schnittstelle oder Basisklasse zu definieren, dann neu definieren, die gleiche -named Enum in einer Klasse, die entweder von der Basis oder dem Interface ableitet. Eine Anwendung für eine solche Konstruktion ist in objektrelationalen Mapping und Kontrollbindung. Sie könnten eine Reihe von Aufzählungen, die beschreiben, welche Eigenschaften von abgeleiteten Klassen bindable sind, welche Arten von Kontrolle, wie zum Beispiel:

    public enum WebControlTextBoxProperties { }

    public enum WebControlLabelProperties { }

... und so weiter.

Da Sie nicht genau wissen, welche Eigenschaften für eine bestimmte abgeleitete Klasse geben wird, bis der betreffende Erbe wirksam wird, aber da man auch konsequent Methoden haben wünschen, dass die oben genannten Aufzählungen in Ihrer Basis oder Schnittstelle verbrauchen, ist es ein perfekt -Gültig Design erwarten zu können, definieren, dass die Enum existiert in der Basis / Schnittstelle, aber genau definieren, , was die Mitglieder hat es in einem bestimmten Kontext in allen abgeleiteten Klassen .

Ich wünsche, dies in C # möglich war, wie es in VB ist, weil es ein wirklich nützliches Feature sein würde.

Sie sollten in der Lage sein, eine Enum in einer Basisklasse zu deklarieren und dann die Werte pro abgeleiteten Klasse d.h ändern.

class MyClass
{
    public enum TestEnum { }

    public MyClass()
    {
    }
}

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

    public MyDerivedClass()
    {
    }
}

MyDervied Klasse hätte Zugriff auf TestEnum.value1, TestEnum.value2, TestEnum.value3, wo als MyClass nur Zugriff auf die Art haben würde.

Doch ich persönlich sehe nicht, den Vorteil, dies zu tun, ich alle Werte der Enumeration in der Basisklasse würde erklären, und nur die, die ich benutze pro Klasse benötigen.

James.

Nein, es kann nicht getan werden.

Beachten Sie, dass viele Aufzählungen oft ein Problem mit Design (viele Schalter Konstrukte, zum Beispiel) angeben. Überprüfen Sie diesen Link ein Beispiel zu sehen, wie das Refactoring: bedingte Ersetzen durch Polymorphismus .

Nein, es gibt keine Möglichkeit, etwas statisch in einer Schnittstelle zu erzwingen.

Vielleicht müssen Sie Ihr Design zu überdenken.

Warum kann man die Enum in Basisklasse definieren:

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

Und nur die relevanten Mitglieder der Enumeration in abgeleiteten Klassen verwenden?

Ich bin bei der Arbeit so nicht vollständig ausarbeiten kann, aber dies ist möglich, bis zu einem Punkt. Der Nachteil der Code unten ist, können Sie nicht Kette Aufzählungen zusammen, wie TextBoxProperties und MyCustomTextBoxProperties: TextboxProperties

Hier ist der Code.

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

CAN ABSTRACT AN ENUM!

Warum bestehen die Menschen auf die Dinge behaupten unmöglich sind, ohne etwas zu überprüfen?

Sicher, die .NET-Dokumentation ein wenig auf diese vage, aber die System.Enum Klasse ist die Abstraktion eines ENUM. Sie können System.Enum als Variable verwenden, die Enumerationswerten nur akzeptieren, und Sie können den Namen oder Wert-Typ-Wert der Aufzählung durch diese Klasse zugreifen.

Zum Beispiel:

        // 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));

Die Ausgabe des obigen Code:

9

9

Blau

Ich mag die akzeptierte Antwort von @Marc GRA. Wie ich ein Stackoverflow-Neuling bin ich bin nicht äussern dürfen. Aber ich möchte hinzufügen, dass es sinnvoll ist, auch die zugrunde liegenden Typ der Enumeration zu überprüfen - vor allem, wenn Sie die Flag Attribut und Vorform bitweise Flag-Testing-Operationen verwenden ...

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

Hier ist eine Lösung, die funktioniert für mich:

in der übergeordneten Klasse, erklärt das Feld als int, nicht als ENUM:

protected int state;

so die Elternklasse kann immer noch diesen Wert als int verwenden, um die Serialisierung und deserializion dieses Wertes auf der Festplatte zu schaffen.

Dann, der die Klasse überschreibt kann dies tun:

enum states{
  state1, state2
}

this.state = state1.toInt();

und kann den tatsächlichen Wert wie folgt zugreifen:

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

wobei toInt () in einer statischen Klasse ist folgendermaßen definiert:

public static class Utils
{

    public static int toInt(this state s)
    {
        return (int)s;
    }
 }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top