1

假设我有这样的课程:

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     |
+---------+---------+-----------+

我想制作一个看起来像这样的用户界面:

+-------------------------------------+
| Lorem blahdiblah FlagTwo, FlagThree |
+-------------------------------------+
| Lorem blahdiblah FlagOne, FlagThree |
+-------------------------------------+

我不必这样;我只是认为这是一个用 LINQ 解决的有趣问题,但找不到任何答案。

4

4 回答 4

3

解决这个问题的一种方法是Flag在集合中使用可为空的 s,然后过滤掉nulls,如下所示:

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?- 每个标志一个。对应于未设置属性的标志变为nulls;与 set 属性对应的标志变为可以为空的Flag.XYZ

剩下的很简单:Where()过滤掉nulls,Select()删除可空性,最后ToList()使结果成为一个列表。

于 2013-09-10T02:41:45.150 回答
1

为什么要转换它?

您也可以在 Enums 中实现标志:

[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
}

使用这种结构的优点是位表示得更紧凑,操作(如按位或)可以更快地处理,并且您不必担心位的语义(枚举隐藏位的实际值)。

如果您真的想枚举可能的值,可以使用通用构造:

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;
      }
    }
  }

}
于 2013-09-10T02:38:48.953 回答
0
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();
于 2013-09-10T02:38:23.023 回答
0

目前尚不清楚您打算如何将标志 bools 映射到枚举值,但您可能希望使用如下内容:

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.Three 代表什么。

于 2013-09-10T02:39:15.533 回答