Click here to Skip to main content
15,891,033 members
Articles / Programming Languages / C#

Smart enums in C#

Rate me:
Please Sign up or sign in to vote.
4.43/5 (24 votes)
6 Aug 2017CPOL1 min read 24.8K   191   25   7
Replacement for standard enums with additional functionality.

Introduction

Long time ago I've learned from John Skeet's blog about java enums which are full-fledged classes. This approach have obvious benefits: you can add behavior to enums.

I've found on Stackoverflow solutions how to implement this in C# . Unfortunately all of them haven't worked with switch statement because case requires to be followed by constant value which can't be of reference type (string is the only exception with special support from the compiler).

Things have changed with C# 7.0 with new enhanced switch statement.

Using the code

Basic idea is to change enum to an immutable class and expose static readonly instances of that class.

Most of boilerplate code I've placed in EnumBase class. This includes serialization support, comparison operators, etc. All my enums inherit from this class.

In EnumBase class I've assumed that internally enum values are represented by int. This class also supports enum description which in standard enum is usually represented by some custom attribute.

As an example here is TransactionState class:

public class TransactionState : EnumBase
{
    public static readonly TransactionState COMPLETE = new TransactionState(1, "Transaction complete");
    public static readonly TransactionState REJECTED = new TransactionState(2, "Transaction rejected");
    public static readonly TransactionState PENDING = new TransactionState(3, "Transaction pending");
    public static readonly TransactionState AWAITING_APPROVAL = new TransactionState(4, "Transaction awaiting approval");

    private TransactionState(int value, string description)
        : base(value, description)
    {
    }

    private TransactionState(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }

    public virtual bool IsTransactionComplete()
    {
        if (value == 1)
            return true;

         return false;
    }
}

This example is based on java sample from this blog: http://blog.scottlogic.com/2016/07/28/java-enums-how-to-use-them-smarter.html

As you see there is very little boilerplate code - just one additional constructor for proper serialization and another one to initialize values.

IsTransactionComplete is a method which adds some useful logic inside enum itself: it decides about enum category. With standard enums you would have to implement this in some other helper class.

Now is the time to show usage of this class:

C#
class Program
{
    static void Main()
    {
        TransactionState value = TransactionState.PENDING;
        TransactionState secondValue = TransactionState.COMPLETE;

        // Use switch with pattern matching.
        switch (value)
        {
            case var tsValue when tsValue == TransactionState.COMPLETE && secondValue == TransactionState.AWAITING_APPROVAL:
                Console.WriteLine("Y");
                break;
            case var tsValue when tsValue == TransactionState.PENDING && secondValue == TransactionState.COMPLETE:
                Console.WriteLine("Value is PENDING, secondValue is COMPLETE");
                break;
            case var tsValue when tsValue == TransactionState.REJECTED:
                Console.WriteLine("Z");
                break;
        }

        if (value.IsTransactionComplete())
        {
            Console.WriteLine("Value is COMPLETE");
        }
        else
        {
            Console.WriteLine("Value is not COMPLETE");
        }

        Console.WriteLine("value.Tostring(): {0}", value.ToString());
    }
}
I've used new switch form with pattern matching and when keyword.

Conclusion

Since C# 7.0 you can use standard classes in place of enums which can be useful for greater flexibility and usability in more complex cases.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Poland Poland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionExtension methods Pin
Eric Lynch17-Nov-18 4:53
Eric Lynch17-Nov-18 4:53 
Questioncode availability? Pin
Member 85555501-Sep-17 5:43
Member 85555501-Sep-17 5:43 
QuestionWhere is the download link? Pin
James Curran1-Aug-17 7:51
James Curran1-Aug-17 7:51 
AnswerRe: Where is the download link? Pin
robsosno6-Aug-17 8:10
robsosno6-Aug-17 8:10 
AnswerRe: Where is the download link? Pin
robsosno6-Aug-17 8:43
robsosno6-Aug-17 8:43 
QuestionThe serialization is quite odd. Pin
Paulo Zemek31-Jul-17 11:23
mvaPaulo Zemek31-Jul-17 11:23 
AnswerRe: The serialization is quite odd. Pin
robsosno6-Aug-17 9:07
robsosno6-Aug-17 9:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.