Laden...

Snippet für JavaStyle Enums (Version 0.1)

Erstellt von dr4g0n76 vor 9 Jahren Letzter Beitrag vor 9 Jahren 6.973 Views
dr4g0n76 Themenstarter:in
2.921 Beiträge seit 2005
vor 9 Jahren
Snippet für JavaStyle Enums (Version 0.1)

Java-Style-Enums in C#

Neulich bin ich über Java-Enums gestolpert.
Etwas erstaunt war ich, dass diese nicht äquivalent zu c# oder c++ sind, sondern im Gegenteil dazu noch viel mehr können! Dann kam die Frage auf, wie können wir uns dieses Konzept in C# zunutze machen?

Hier das Ergebnis:

Mit diesem Snippet (unten) kann ein Enum im Style von Java angelegt werden.
Angeregt wurde diese Idee unter anderem durch folgenden Post:

Java Enum - Oracle

Entweder kann der untere Code in ein Snippet-Editor für C# in Visual Studio eingefügt werden
oder einfach das Snippet unten aus dem Dateianhang herunterladen und die Dateiendung in ".snippet" umändern.

Ich denke hier ist es auch legitim Extension-Methods zu verwenden, um Java möglichst nahe zu kommen. Sie sollten im Idealfall andere Objekte nie stören, da Enums so gesehen keine Funktionen haben.

Bei Oracle gab es dazu folgendes Beispiel:


public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass() { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage: java Planet <earth_weight>");
            System.exit(-1);
        }
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/EARTH.surfaceGravity();
        for (Planet p : Planet.values())
           System.out.printf("Your weight on %s is %f%n",
                             p, p.surfaceWeight(mass));
    }
}

Hier also das Snippet und unten noch ein Beispiel dazu, wie man einen Java-Style-Enum daraus erstellen kann und dieses benutzt.


public enum $Testenum$
{
}

public static class $Testenum$Extensions
{
    private static readonly IDictionary<$Testenum$, $Testenum$Data> _map;

	static $Testenum$Extensions()
    {
		_map = new Dictionary<$Testenum$, $Testenum$Data>() { 
			//Fill here like Concrete enum value: for example $Testenum$.Value1, new $Testenum$Data(constructor value1, constructor value2, constructor value3, ...)
        };
	}
	
	public static $Testenum$Data Get$Testenum$Data(this $Testenum$ _value)
    {
		if (!_map.ContainsKey(_value))
			throw new ArgumentOutOfRangeException("_map", "Unknown $Testenum$");	
		return _map[_value];
	}
		
	/*public static int GetValue(this $Testenum$ $Testenum$)
	{
		//Example function
		//just put your code here
		//return Get$Testenum$Data($Testenum$).$Testenum$DataFunctionName;
	}*/
}

public class $Testenum$Data
{
      public $Testenum$Data(/* insert your constructor parameters here */)
      {
	
      }
}

Hier also der Java-Style-Enum. Ich hab mit Absicht nicht die Planeten-Klasse genommen,
denn ich hoffe es probiert jemand mal aus. Sondern hier was gemacht, um z.B. in einem Abwasch Farben so als Int-Werte ausgeben zu können und ja ich bin mir bewusst, dass es in diesem Falle auch anders geht. 😃


  public enum Colorable
    {
        Red, 
        Green,
        Blue
    }

    public static class ColorableExtensions
    {
        private static readonly IDictionary<Colorable, ColorableData> _map;

        static ColorableExtensions()
        {
            _map = new Dictionary<Colorable, ColorableData>()
            {
                //Fill here like Concrete enum value: for example Colorable.Value1, new ColorableData(constructor value1, constructor value2, constructor value3, ...)
                {Colorable.Red, new ColorableData(Color.Red)},
                {Colorable.Blue, new ColorableData(Color.Blue)},
                {Colorable.Green, new ColorableData(Color.Green)}
            };
        }

        public static ColorableData GetColorableData(this Colorable _value)
        {
            if (!_map.ContainsKey(_value))
                throw new ArgumentOutOfRangeException("_map", "Unknown Colorable");
            return _map[_value];
        }

        public static int RGBValue(this Colorable Colorable)
        {
            //Example function
            //just put your code here
            return GetColorableData(Colorable).RGBValue;
        }
    }
    
    public class ColorableData
    {
        private readonly Color m_Color;
        public ColorableData(Color _color)
        {
            m_Color = _color;
        }

        public int RGBValue { get { return m_Color.ToArgb(); } }
    }

und zu guter letzt noch ein Beispiel für die Ausgabe:


  foreach (Colorable color in typeof(Colorable).GetEnumValues())
  {
         MessageBox.Show(color.RGBValue().ToString());
  }

Java Enum

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.

742 Beiträge seit 2005
vor 9 Jahren

Ganz nett, ich würde aber das wirklich wichtige Problem von Enums lösen:

Enumeration classes: what do you do about enumerations crossing service boundaries.