Enums in C# and Java

Java and C# are both object oriented languages, they both have quite similar concepts, simple stuff like classes and interfaces or annotations or generics. Also both have enums, but how they work differs quite a lot.

Java

Let’s start with the Java version. Here an enum is a special kind of class that can not be extended or extend another class, but can implement interfaces. Every constant of an enum is just an object of that special class and they will be created once and can not be created otherwise. Because it’s a class you can add methods and properties to it. Like a numerical value for each enum or a string with a formatted name for the toString() method. There is also the possibility to add static methods for returning an enum depending on a number, for range selection.

public enum EAdrenalineLevel {
	
	Calm(0.5, "Calm as a Buddhist"),
	Relaxed(1.0, "Relaxed on the couch"),
	Toxic(99.0, "Toxic as hell");
	
	private String description;
	private double level;	
	
	private EAdrenalineLevel(double level, String description) {
		this.level = level;
		this.description = description;
	}
	
	public double getLevel() {
		return level;
	}
	
	public String getDescription() {
		return description;
	}
	
	public static double getMinLevel() {
		double result = Double.MAX_VALUE;
		
		for (EAdrenalineLevel value : values()) {
			result = Math.min(result, value.level);
		}
		
		return result;
	}
	
	public static double getMaxLevel() {
		double result = Double.MIN_VALUE;
		
		for (EAdrenalineLevel value : values()) {
			result = Math.max(result, value.level);
		}
		
		return result;
	}
}

C#

In C# on the other hand an enum is just an int. This is probably because of backwards compatibility with C & C++. The backdrop here is, that all the fancy stuff from Java is not possible directly on the enum, no variables, no methods, nothing. But C# has a nice feature to compensate for that: extension methods. Basically you define another static class that declares extension methods for that enum, and in them using switch cases to return a different value for every enum. It’s not as clean as in Java but works too. Still you cannot override the ToString() method and for static methods you have to use your companion class, but returning a numerical value or a better name works the same as in Java.

    public enum EAdrenalineLevel
    {
        Calm,
        Relaxed,
        Toxic
    }

    public static class AdrenalineLevel
    {
        public static double GetValue(this EAdrenalineLevel adrenalineLevel)
        {
            double result = double.NaN;

            switch (adrenalineLevel)
            {
                case EAdrenalineLevel.Calm: result = 0.5; break;
                case EAdrenalineLevel.Relaxed: result = 1.0; break;
                case EAdrenalineLevel.Toxic: result = 99.0; break;
                default: throw new Exception("missing AdrenalineLevel value");
            }

            return result;
        }

        public static string GetDescription(this EAdrenalineLevel adrenalineLevel)
        {
            string result = null;

            switch (adrenalineLevel)
            {
                case EAdrenalineLevel.Calm: result = "Calm as a Buddhist"; break;
                case EAdrenalineLevel.Relaxed: result = "Relaxed on the couch"; break;
                case EAdrenalineLevel.Toxic: result = "Toxic as hell"; break;
                default: throw new Exception("missing AdrenalineLevel description");
            }

            return result;
        }

        public static EAdrenalineLevel[] GetValues() 
            => Enum.GetValues(typeof(EAdrenalineLevel)).Cast<EAdrenalineLevel>().ToArray();
        public static double GetMinLevel() 
            => GetValues().Select(al => al.GetValue()).Min();
        public static double GetMaxLevel() 
            => GetValues().Select(al => al.GetValue()).Max();
    }

Conclusion

In my opinion the Java approach has more possibilities, especially now with interfaces and default implementations. Tell me in the comments, what you think.

Leave a Reply