Skip to content

Development Notes: EquivalentEnumAttribute

Martin Evans edited this page Oct 9, 2015 · 5 revisions

Part of what SupersonicSound does is to wrap FMOD enums (with ugly, non C# names) with C# enums with much nicer names. For example:

//FMOD enum
enum OUTPUTTYPE
{
    AUTODETECT
}

//C# enum
public enum OutputType
{
    // Copy the value from the FMOD enum to ensure casting works
    AutoDetect  = OUTPUTTYPE.AUTODETECT
}

SupersonicSound includes an attribute to help do this task; EquivalentEnumAttribute. The EquivalentEnumAttribute indicates that two enums should have all the same members, when SSS is loaded (with a debug build) it will check all types decorated with this attribute and throw an exception if it detects a programmer error. This is particularly useful when upgrading FMOD - any new enum values included in FMOD will cause all tests to fail until enums are updated correctly.

Ignoring Values

Some enums will have values which you do not want to include in SupersonicSound. For example the OUTPUTTYPE enum includes some values only for consoles, since SSS does not currently support any consoles these values are pointless. You can pass in an array of names to ignore:

[EquivalentEnum(typeof(OUTPUTTYPE),
  "XBOX360",  //
  "PS3",      // We don't support consoles
  "WIIU",     //
  "AUDIOOUT", // <-- PS4+Vita

  "MAX"       // Denotes the last item in the enum, don't need this
)]

Casting Values

Naturally within the wrapper you must frequently cast back to the underlying FMOD enum. Since the enum values are exactly the same you could just cast directly:

OutputType sss = OutputType.AutoDetect;
OUTPUTTYPE fmod = (OUTPUTTYPE)sss;

However this is error prone, if you cast to the wrong enum type nothing is guaranteed to break and you will likely only get subtle errors later on. Instead you can use the equivalent enum system for casting too:

OutputType sss = OutputType.AutoDetect;
OUTPUTTYPE fmod = EquivalentEnum<OutputType, OUTPUTTYPE>.Cast(sss);
//      Type we are casting from ^           ^ Type we are casting to

In release mode this just evaluates to a simple cast. However in debug mode this performs extra checks to ensure that what you're casting to and from are valid (i.e. that one of the two types has an EquivalentEnum attribute which indicates equivalence with the other type).