Also see the updates at the end of the question...
Given the following situation:
[Flags]
enum SourceEnum
{
SNone = 0x00,
SA = 0x01,
SB = 0x02,
SC = 0x04,
SD = 0x08,
SAB = SA | SB,
SALL = -1,
}
[Flags]
enum DestEnum
{
DNone = 0x00,
DA = 0x01,
DB = 0x02,
DC = 0x04,
DALL = 0xFF,
}
I would like to convert one enum type to the other and vice-versa based on mapping function using the names like a big switch() but since this a flags enum I am having a difficult time designing such a routine to be generic.
Basically, what I want is something like the following:
Example #1
SourceEnum source = SourceEnum.SA;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DA));
Example #2
SourceEnum source = SourceEnum.SA | SourceEnum.SB;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DA | DestEnum.DB));
Example #3
SourceEnum source = SourceEnum.SAB;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DA | DestEnum.DB));
Example #4
SourceEnum source = SourceEnum.SALL;
DestEnum dest = Map<Source, Dest> (source);
Assert.That (dest, Is.EqualTo (DestEnum.DALL));
Example #5
SourceEnum source = SourceEnum.SD;
var ex = Assert.Throws<Exception> (() => Map<Source, Dest> (source));
Assert.That (ex.Message, Is.EqualTo ("Cannot map SourceEnum.SD to DestEnum!"));
The Map() function could accept a delegate for providing the actual mapping but I still need to have several functions for helping such a delegate with the bits...
DestEnum SourceToDestMapper (SourceEnum source)
{
// Switch cannot work with bit fields enumeration...
// This is to give the general idea...
switch (source)
{
case SourceEnum.SNone:
return DestEnum.DNone;
case SourceEnum.SA:
return DestEnum.DA;
case SourceEnum.SAB:
return DestEnum.DA | DestEnum.DB;
...
default:
throw new Exception ("Cannot map " + source.ToString() + " to DestEnum!");
}
}
EDIT: CLARIFICATION
The values of the enum definitions might seem to fit between each others but that is not necessarily the case.
For example, it could be:
enum SourceEnum
{
SA = 0x08,
SB = 0x20,
SC = 0x10,
SAB = SA | SB,
SABC = SA | SB | SC,
}
enum DestEnum
{
DA = 0x04,
DB = 0x80,
DC = 0x01,
DAB = DA | DB,
}
EDIT: More info
I am looking at a way of doing a custom mapping of enum flags, not based on patterns on the names. However, the names are used in the custom mapping function.
I would be perfectly possible to have a SourceToDestMapper function trying to map SA to DC for example...
The main problem is feeding the SourceToDestMapper function with each flag of the source AND taking care of flag values having multiple bit sets...
For example: Having a flag SourceEnum.SABC would call the SourceToDestMapper function three times resulting in the following:
- SourceEnum.SA mapped to DestEnum.DA
- SourceEnum.SB mapped to DestEnum.DB
- SourceEnum.SC mapped to DestEnum.DC
And the resulting DestEnum would be: DestEnum.DA | DestEnum.DB | DestEnum.DC