将一些布尔属性转换为标志枚举
本文关键字:标志 枚举 转换 属性 布尔 | 更新日期: 2023-09-27 18:37:21
我需要将具有 3 个布尔属性的遗留类转换为标志枚举。
我知道这些属性中至少有一个是正确的。
[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;
}
}
}
}
考虑到我可能会遇到需要设置更多属性和标志的情况,是否有更优雅或简洁的方法可以做到这一点?
这样的事情怎么样?
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;
}
}
}
与其在代码中使用分支,不如将按位算术与一个小函数结合使用来简化代码:
T GetFlag<T>(Boolean value, T flag) {
return value ? flag : default(T);
}
要计算枚举值,您可以使用以下表达式:
var flagEnum = GetFlag(legacyClass.PropA, FlagEnum.EnumValue1)
| GetFlag(legacyClass.PropB, FlagEnum.EnumValue2)
| GetFlag(legacyClass.PropC, FlagEnum.EnumValue3);
请注意,如果未设置任何标志,代码将引发ArgumentException
。此代码将改为计算在本例中为 0 的default(FlagEnum)
。
这个怎么样?
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);
}
是否必须为此使用按位运算?我怀疑非按位方法在这里有效:
FlagEnum = (FlagEnum)(1 * (ToInt(legacyClass.PropA))
+ 2 * (ToInt(legacyClass.PropB))
+ 4 * (ToInt(legacyClass.PropC)));
假设我们有一个函数
int ToInt(bool b) { return b ? 1 : 0; }
如果枚举 legacy 类中的布尔值,则可以更整齐地完成 - 然后我们可以使用 Math.Pow(n, 2) 应用公式。但这是一个设计选择。