Reputation: 8444
Say I have a class like this:
class From
{
public bool FlagOne { get; set; }
public bool FlagTwo { get; set; }
public bool FlagThree { get; set; }
}
... and I want to convert a list of these into a list of these:
class To
{
public List<Flag> Flags { get; set; }
}
... where Flag
looks like this:
public enum Flag
{
One,Two,Three
}
I write some code:
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();
The names of the enum values and the boolean flags to not matter. There should be no reflection necessary.
I have a database table like this:
+---------+---------+-----------+
| FlagOne | FlagTwo | FlagThree |
+=========+=========+===========|
| 0 | 1 | 1 |
+---------+---------+-----------+
| 1 | 0 | 1 |
+---------+---------+-----------+
and I want to make a UI that looks like this:
+-------------------------------------+
| Lorem blahdiblah FlagTwo, FlagThree |
+-------------------------------------+
| Lorem blahdiblah FlagOne, FlagThree |
+-------------------------------------+
I don't have to do this; I just thought it was an interesting problem to solve with LINQ, and couldn't find any answers.
Upvotes: 1
Views: 194
Reputation: 726849
One way to deal with this is using nullable Flag
s in a collection, and then filter out the null
s, like this:
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();
The array created in the assignment of Flags
has three items of type Flag?
- one for each flag. The flags that correspond to an unset property become null
s; the flags corresponding to set properties become the nullable Flag.XYZ
.
The rest is simple: the Where()
filters out the null
s, the Select()
drops nullability, and finally ToList()
makes the results a list.
Upvotes: 3
Reputation: 721
It isn't clear exactly how you intend for the flag bools to map into enum values, but you would probably want to use something like this:
Flags = new List<Flag> {
from.FlagOne ? Flag.One : Flag.Two,
from.FlagTwo ? Flag.One : Flag.Two,
from.FlagThree ? Flag.One : Flag.Two }
The main question being what you want Flag.One, Flag.Two, and Flag.Three to represent.
Upvotes: 0
Reputation: 477230
Why do you want to convert it?
You can implement flags in Enums as well:
[Flags]
public enum Foo : int {
Bit1 = 0x01,
Bit2 = 0x02,
Bit3 = 0x04
}
You can then check if a flag is active simply by a bitwise AND operation. For instance:
Foo aVariable = Foo.Bit1|Foo.Bit3;//both bit1 and bit3 are enabled
Check if bit3 is enabled:
if((aVariable&Foo.Bit3) != 0x00) {
//flag is enabled, now do something
}
else {
//flag is disabled, do something else
}
The advantage of using such constructions is that the bits are represented more compact, operations (like a bitwise OR) can be handled more faster and you don't have to worry about semantics of the bits (the enum hides the actual value of the bits).
If you really want to enumerate over the possible values, you can use a generic construction:
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;
}
}
}
}
Upvotes: 1
Reputation: 217351
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();
Upvotes: 0