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.