Click here to Skip to main content
13,259,976 members (49,362 online)
Click here to Skip to main content
Add your own
alternative version

Stats

11.1K views
88 downloads
20 bookmarked
Posted 30 Jul 2017

Smart enums in C#

, 6 Aug 2017
Rate this:
Please Sign up or sign in to vote.
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:

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)

Share

About the Author

robsosno
Web Developer
Poland Poland
No Biography provided

You may also be interested in...

Comments and Discussions

 
Questioncode availability? Pin
Member 85555501-Sep-17 6:43
memberMember 85555501-Sep-17 6:43 
QuestionWhere is the download link? Pin
James Curran1-Aug-17 8:51
memberJames Curran1-Aug-17 8:51 
AnswerRe: Where is the download link? Pin
robsosno6-Aug-17 9:10
memberrobsosno6-Aug-17 9:10 
AnswerRe: Where is the download link? Pin
robsosno6-Aug-17 9:43
memberrobsosno6-Aug-17 9:43 
QuestionThe serialization is quite odd. Pin
Paulo Zemek31-Jul-17 12:23
professionalPaulo Zemek31-Jul-17 12:23 
AnswerRe: The serialization is quite odd. Pin
robsosno6-Aug-17 10:07
memberrobsosno6-Aug-17 10: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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171114.1 | Last Updated 6 Aug 2017
Article Copyright 2017 by robsosno
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid