使用 LINQ 将一堆布尔值转换为枚举列表
本文关键字:转换 布尔值 枚举 列表 一堆 LINQ 使用 | 更新日期: 2023-09-27 18:30:41
假设我有这样的类:
class From
{
public bool FlagOne { get; set; }
public bool FlagTwo { get; set; }
public bool FlagThree { get; set; }
}
。我想将这些列表转换为这些列表:
class To
{
public List<Flag> Flags { get; set; }
}
。Flag
如下所示:
public enum Flag
{
One,Two,Three
}
我写了一些代码:
var froms = new List<From>
{
new From {
FlagOne = false,
FlagTwo = true,
FlagThree = true
},
new From {
FlagOne = true,
FlagTwo = false,
FlagThree = true
}
};
var tos = froms.Select(from => new To {
Flags = // ....... what? what goes here?
}).ToList();
枚举值和布尔标志的名称无关紧要。 没有必要进行反思。
上下文
我有一个这样的数据库表:
+---------+---------+-----------+
| FlagOne | FlagTwo | FlagThree |
+=========+=========+===========|
| 0 | 1 | 1 |
+---------+---------+-----------+
| 1 | 0 | 1 |
+---------+---------+-----------+
我想制作一个看起来像这样的 UI:
+-------------------------------------+
| Lorem blahdiblah FlagTwo, FlagThree |
+-------------------------------------+
| Lorem blahdiblah FlagOne, FlagThree |
+-------------------------------------+
我不必这样做;我只是认为这是一个用 LINQ 解决的有趣问题,找不到任何答案。
解决此问题的一种方法是在集合中使用可为空的 Flag
,然后过滤掉null
s,如下所示:
var tos = froms
.Select(f => new To {
Flags = new[] {
f.FlagOne ? (Flag?)Flag.One : null,
f.FlagTwo ? (Flag?)Flag.Two : null,
f.FlagThree ? (Flag?)Flag.Three : null
}
.Where(f => f.HasValue)
.Select(f => f.Value)
.ToList()
}).ToList();
在分配 Flags
中创建的数组有三个类型 Flag?
的项目 - 每个标志一个。对应于未设置属性的标志变为 null
s;与设置属性对应的标志变为可为空Flag.XYZ
。
其余的很简单:Where()
过滤掉null
,Select()
删除可空性,最后ToList()
使结果成为列表。
为什么要
转换它?
您也可以在枚举中实现标志:
[Flags]
public enum Foo : int {
Bit1 = 0x01,
Bit2 = 0x02,
Bit3 = 0x04
}
然后,只需按位 AND 操作即可检查标志是否处于活动状态。例如:
Foo aVariable = Foo.Bit1|Foo.Bit3;//both bit1 and bit3 are enabled
检查是否启用了 bit3:
if((aVariable&Foo.Bit3) != 0x00) {
//flag is enabled, now do something
}
else {
//flag is disabled, do something else
}
使用这种结构的优点是位表示得更紧凑,操作(如按位 OR)可以更快地处理,并且您不必担心位的语义(枚举隐藏了位的实际值)。
如果确实要枚举可能的值,可以使用泛型构造:
public static class Bar {
public static IEnumerable<T> EnumerateAtoms<T> (this T input) where T : enum {
foreach(T value in Enum.GetValues(typeof(T))) {
if((input&val) != 0x00) {
yield return value;
}
}
}
}
To ConvertFromFromToTo(From from)
{
List<Flag> flags = new List<Flag>();
if (from.FlagOne) flags.Add(Flag.One);
if (from.FlagTwo) flags.Add(Flag.Two);
if (from.FlagThree) flags.Add(Flag.Three);
return new To { Flags = flags };
}
var tos = froms.Select(ConvertFromFromToTo).ToList();
目前尚不清楚您打算如何将标志布尔映射到枚举值中,但您可能希望使用这样的东西:
Flags = new List<Flag> {
from.FlagOne ? Flag.One : Flag.Two,
from.FlagTwo ? Flag.One : Flag.Two,
from.FlagThree ? Flag.One : Flag.Two }
主要问题是您希望Flag.One,Flag.Two和Flag.III代表什么。