I need to convert a legacy class with 3 bool properties to a flag enum.
I know that at least one of those properties is true.
[Flags]
public enum FlagEnum
{
EnumValue1 = 1,
EnumValue2 = 2,
EnumValue3 = 4
}
public class LegacyClass
{
public bool PropA { get; set; }
public bool PropB { get; set; }
public bool PropC { get; set; }
}
public class DtoClass
{
public FlagEnum FlagEnum { get; set; }
public DtoClass(LegacyClass legacyClass)
{
if (!legacyClass.PropA && !legacyClass.PropB && !legacyClass.PropC)
{
throw new ArgumentException();
}
if (legacyClass.PropA)
{
FlagEnum = FlagEnum.EnumValue1;
}
if (legacyClass.PropB)
{
if (legacyClass.PropA)
{
FlagEnum = FlagEnum.EnumValue1|FlagEnum.EnumValue2;
}
else
{
FlagEnum = FlagEnum.EnumValue2;
}
}
if (legacyClass.PropC)
{
if (legacyClass.PropA||legacyClass.PropB)
{
FlagEnum = FlagEnum | FlagEnum.EnumValue3;
}
else
{
FlagEnum = FlagEnum.EnumValue3;
}
}
}
}
Is there a more elegant or concise way to do this considering that I may run into a case with even more properties and flags to set?
how about something like this?
using System;
namespace ConsoleApplication1
{
[Flags]
public enum FlagEnum
{
EnumValue1 = 1,
EnumValue2 = 2,
EnumValue3 = 4
}
public static class LegacyClass
{
public static bool PropA { get; set; }
public static bool PropB { get; set; }
public static bool PropC { get; set; }
}
class Program
{
static void Main(string[] args)
{
LegacyClass.PropB = true;
FlagEnum result = LegacyClass.PropA ? FlagEnum.EnumValue1 : 0;
result |= LegacyClass.PropB ? FlagEnum.EnumValue2 : 0;
result |= LegacyClass.PropC ? FlagEnum.EnumValue3 : 0;
}
}
}
Instead of using branching in your code you can do bitwise arithmetic combined with a small function to simplify the code:
T GetFlag<T>(Boolean value, T flag) {
return value ? flag : default(T);
}
To compute the enum value you can use this expression:
var flagEnum = GetFlag(legacyClass.PropA, FlagEnum.EnumValue1)
| GetFlag(legacyClass.PropB, FlagEnum.EnumValue2)
| GetFlag(legacyClass.PropC, FlagEnum.EnumValue3);
Note that your code will throw an ArgumentException
if none of the flags are set. This code will instead compute default(FlagEnum)
which in this case is 0.
How about this?
public DtoClass(LegacyClass legacyClass)
{
if (!legacyClass.PropA && !legacyClass.PropB && !legacyClass.PropC)
{
throw new ArgumentException();
}
FlagEnum = ((legacyClass.PropA) ? FlagEnum.EnumValue1 : FlagEnum)
| ((legacyClass.PropB) ? FlagEnum.EnumValue2 : FlagEnum)
| ((legacyClass.PropC) ? FlagEnum.EnumValue3 : FlagEnum);
}
Do you have to use bitwise operations for this? I suspect a non-bitwise approach would work here:
FlagEnum = (FlagEnum)(1 * (ToInt(legacyClass.PropA))
+ 2 * (ToInt(legacyClass.PropB))
+ 4 * (ToInt(legacyClass.PropC)));
assuming we have a function
int ToInt(bool b) { return b ? 1 : 0; }
It could be done more neatly if the boolean values in the legacy class were enumerated - then we could apply a formula using Math.Pow(n, 2). But that's a design choice.
来源:https://stackoverflow.com/questions/19656242/convert-some-bool-properties-to-a-flags-enum