A developer at work recently started using a class pattern instead of enums in places where enums would usually fit. Instead, he uses something similar to that below:
internal class Suit
{
public static readonly Suit Hearts = new Suit();
public static readonly Suit Diamonds = new Suit();
public static readonly Suit Spades = new Suit();
public static readonly Suit Clubs = new Suit();
public static readonly Suit Joker = new Suit();
private static Suit()
{
}
public static bool IsMatch(Suit lhs, Suit rhs)
{
return lhs.Equals(rhs) || (lhs.Equals(Joker) || rhs.Equals(Joker));
}
}
His reasoning is that it invisibly looks like an enumeration, but allows him to contain the methods relating to the numeration (like the IsMatch above) to be contained within the enumeration itself.
He called this an Enumeration class, but it's not something I've ever seen before. I wondered what the advantages and disadvantages were and where I could find out more information?
Thanks
Edit: Another advantage he described was being able to add a specific ToString() implementation for the enumeration.
The main advantage of enums is that they are basically integers with some named values, as such they are inherently portable and serializable. Arithmetic and logical operations are also faster on enums.
Enumeration classes are used when you need an opaque value which has extra state information. For instance a generic Data Access Layer could have as an interface like:
public static class Dal { public static Record Query(Operation operation, Parameters parameters); } var result = Dal.Query(Operation.DoSomething, new DoSomethingParameters {...});
To the users of the Dal Operation is just an enumeration of the operations available, but it could contain the connection string, the SQL statement or stored procedure and any other data needed by the generic Dal.
Another "common" use is for public modes in a system (a state or a strategy). From a user perspective the mode is an opaque value, but it may contain information or internal functionality crucial to the implementation of the system. A contrived example:
public class TheSystem { public SystemMode Mode; public void Save() { Mode.Save(); } public SystemDocument Read() { return Mode.Read(); } } public abstract class SystemMode { public static SystemMode ReadOnly = new ReadOnlyMode(); public static SystemMode ReadWrite = new ReadWriteMode(); internal abstract void Save(); internal abstract SystemDocument Read(); private class ReadOnlyMode : SystemMode { internal override void Save() {...} internal override SystemDocument Read() {...} } private class ReadWriteMode : SystemMode { internal override void Save() {...} internal override SystemDocument Read() {...} } } TheSystem.Mode = SystemMode.ReadOnly;
I don't think just having an IsMatch static method warrants not using simple enums. Something very similar could be achieved with extension methods in this case.