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 enums 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);
});