Introduction
This tip describes a generic EnumWrapper
class that exposes modular increment methods such as NextEnum
, PrevEnum
, and IncrementEnum
. The intention is to make working with enum
s more convenient, especially when representing the state of a system.
Using the Code
Given an arbitrary
enum
of the form...
public enum PlayState
{
Play,
Stop,
Pause,
Options,
HUD
}
...wrap it up by creating the instance:
var playStateWrapper = new EnumWrapper<PlayState>();
By default, the CurrentEnum
property of playStateWrapper
is set to PlayState(0) = Play
. The methods in the EnumWrapper
class are designed to modify this value in a modular fashion - in the sense of modular arithmetic, where in this case the modulus is the size of PlayState
. The value of CurrentEnum
is affected by the public
methods NextEnum
, PrevEnum
, IncrementEnum
, and SetEnum
in the obvious ways. Moreover, the methods NextEnum
, PrevEnum
, IncrementEnum
each have a boolean parameter that determines whether the CurrentEnum
should be set to that value. Otherwise, they just return the enum
's value. Since the EnumWrapper
class is full of comments and I've included the entire class, you can see how it works.
using System;
namespace YourNameSpace
{
public class EnumWrapper<T>
{
private int _CurrentEnumIndex;
private readonly Lazy<T[]> _Enums;
public T[] Enums
{
get
{
return _Enums.Value;
}
}
public T CurrentEnum { get; private set; }
public EnumWrapper()
{
_Enums = new Lazy<T[]>(() => { return (T[])Enum.GetValues(typeof(T)); });
}
public T NextEnum(bool setToCurrent)
{
return IncrementedEnum(setToCurrent, 1);
}
public T PrevEnum(bool setToCurrent)
{
return IncrementedEnum(setToCurrent, -1);
}
public T IncrementedEnum(bool setToCurrent, int increment)
{
var incrementedIndex =
((_CurrentEnumIndex + increment % Enums.Length) + Enums.Length)
% Enums.Length;
var incrementedEnum = Enums[incrementedIndex];
if (setToCurrent)
SetCurrentEnum(incrementedEnum, incrementedIndex);
return incrementedEnum;
}
public void SetCurrentEnum(T newEnum)
{
var newEnumIndex = Array.IndexOf(Enums, newEnum);
SetCurrentEnum(newEnum, newEnumIndex);
}
private void SetCurrentEnum(T newEnum, int newEnumIndex)
{
CurrentEnum = newEnum;
_CurrentEnumIndex = newEnumIndex;
}
}
}
As an example of how to use this code, the output of the wrapper's methods are listed as follows:
var playStates = new EnumWrapper<PlayState>();
playStates.CurrentEnum = PlayState.Play
playStates.NextEnum(false) = PlayState.Stop
playStates.PrevEnum(true) = PlayState.HUD
playStates.CurrentEnum = PlayState.HUD
playStates.SetCurrentEnum(PlayState.Play)
CurrentEnum = PlayState.Play
playStates.IncrementedEnum(false, 3003) = PlayState.Options
playStates.IncrementedEnum(false, -3001) = PlayState.HUD
The EnumWrapper
class is useful when you want to set the CurrentEnum
given the result of an "action". For example, if you want to turn on and off the functionality of a component dependant on the value of CurrentEnum
, then you can do something like:
PlayCommand = new RelayCommand(() =>
{
PlayStates.NextEnum(true);
});