问题
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?
回答1:
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;
}
}
}
回答2:
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.
回答3:
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);
}
回答4:
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