从客户端我得到一个List,其中每个int值是Enum DayOfWeek的enum int值。
该列表仅包含在时间规划器中可见的int值(天)。
获取int值列表,例如0,1,2(星期日,星期一,星期二)你会如何以一般方式将这些价值观写入DayOfWeek枚举7天或没有一天工作?
只知道星期六的索引为6,而我的DayOfWeek枚举值为32。
[Flags]
public enum DayOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
NotSet = 64,
}
更新
这是来自MarcinJuraszek的工作解决方案代码,它只是改变了我的需求:
var visibleWeekDays = new List<int>();
for (int i = 0; i <= 6; i++)
{
visibleWeekDays.Add(i);
}
int allBitValues = visibleWeekDays.Select(i => (int)Math.Pow(2, ((i + 6) % 7))).Aggregate((e, i) => e | i);
AllVisibleDays = (VisibleDayOfWeek) allBitValues;
[Flags]
public enum VisibleDayOfWeek
{
None = 0,
Mon = 1,
Tue = 2,
Wed = 4,
Thu = 8,
Fri = 16,
Sat = 32,
Sun = 64
}
public VisibleDayOfWeek AllVisibleDays { get; set; }
上面的代码将一周中的所有日子写入VisibleDayOfWeek枚举,现在可以轻松保存在数据库字段中。
根据Microsoft MSDN,标志枚举的None值现在再次设置为0,其余值为2的幂。
答案 0 :(得分:3)
var input = new List<int>() { 0, 1, 2 };
var output = input.Select(i => (DayOfWeek)Math.Pow(2, ((i + 6) % 7))).ToList();
奇怪的((i + 6) % 7)
是必要的,因为标准DayOfWeek
从星期日开始,而你的64
作为星期日的值。
您也可以使用LINQ将标志聚合为单个int
值:
var x = output.Select(i => (int)i).Aggregate((e, i) => e | i);
<强>更新强>
对于已更改的标记,您必须更改翻译查询:
var output = input.Select(i => (DayOfWeek)Math.Pow(2, (i - 1) % 7)).ToList();
答案 1 :(得分:1)
像这样:
private void button1_Click(object sender, EventArgs e)
{
var mylist = new List<int>() { 0, 1, 2 }; // Sunday, Monday, Tuesday
DayOfWeek days = (DayOfWeek)0;
foreach (var item in mylist)
days |= (DayOfWeek)Math.Pow(2, item);
Debug.WriteLine(days);
// Displays "Sunday, Monday, Tuesday"
}
[Flags]
public enum DayOfWeek
{
None = 0,
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
}
(编辑以匹配编辑过的问题)
答案 2 :(得分:0)
(1)将Undefined的名称更改为None;这更符合语义。
(2)对于每个DayValue,设置
dayOfWeek |= (DayOfWeek) Math.Pow(2,DayValue);
DayValue是输入值:0,1,...,6
答案 3 :(得分:0)
你可以这样做:
var days = (DayOfWeek)listOfValues.Sum();
编辑:我可能错了你的问题,我认为你得到一个整数列表,并希望将它们转换为DayOfWeek。如果您只需要所有日期,则可以执行(DayOfWeek)127
或仅将AllDays = 127
添加到枚举。
答案 4 :(得分:0)
理解这个问题的答案需要更深入地了解枚举类的[Flags]属性。您可以阅读有关此属性的信息(或阅读有关如何使用它的一些指导原则)here at MSDN
“Flags”属性是C世界的遗留物,你没有C#和CLR给你的所有花哨类型。
例如,你可能有一个C程序需要跟踪一堆不同的正交条件(我们称之为Condition0,Condition1,Condition2等......)但是为了节省空间,或者让它更容易通过这些条件作为一个单元,我们希望将它们全部塞入一个8位(或更大)值。那么你要做的是定义条件:
如果你还记得二进制到十进制的转换,你就会知道 - 位0表示十进制值1 - 位1表示小数值2 - 位2表示小数值4 - 位4表示小数值8 - 位n代表n的幂的小数值2
因此,我们可以将这两个列表结合起来,看看:
如果我们需要表示发生了Condition1和Condition2,则表示设置了位1和位2。在二进制中,它是0b0110,在十进制中是“6”。表示Condition1和Condition2的值只是Condition1和Condition2的逻辑OR。 0b0010或0b0110是0b0110。 2或4是6。
现在,你可能已经注意到逻辑OR和Condition1和Condition2的总和在上面的例子中出现了相同的值(2 + 4 = 2 OR 4)。 “我知道,我只是将所有条件加在一起!”你会说。编写List.Sum()比使用OR和累加器的for循环更容易。不幸的是,这不会一直有效。
再次考虑上面的“6”或0b0110的值,这意味着“Condition1和Condition2”为真。
然后将其与设置为“Condition0和Condition1”的值组合。 0b0011或十进制“3”
如果您执行逻辑OR - (0b0110 OR 0b0011),则会得到0b0111或小数7.这看起来像“Condition0,Condition1和Condition2”都是真的。这似乎是正确的!
如果你将这些值加在一起,你会得到十进制9(6 + 3,或0b0110 + 0b0011),它出现在0b1001。 0b1001看起来像“条件3是真的,条件0是真的”这不可能是正确的。 Condition3如何参与此处以及Condition1和Condition2发生了什么?当我们开始时它们都被设定了!
现在,回到C#世界 - “Flags”属性意味着“此枚举可以由一个或多个可以存在或不存在的正交条件组成”。程序员可以自己为枚举的不同元素赋值,使它们不重叠(就像在C中一样)。一旦完成,您可以通过对它们执行逻辑OR运算来愉快地组合这些正交条件中的一个或多个。您甚至可以在枚举中定义元素,这些元素是先前定义的元素的组合。考虑元素
Weekends = Saturday | Sunday,
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday,
结论: 对标志求和仅适用于某些情况(主要是当每个被求和的值表示单个条件时)。为了编写在所有情况下都能正常工作的健壮代码,您应该坚持使用标志的逻辑OR。可能需要额外的几行来编写,但它更准确地捕获您的意图,更容易维护,并且如果有人将您不期望的内容传递到您的方法中,则会更加强大。因此,要组合列表中的所有元素,您应该将它们全部组合在一起。像
这样的东西FlagsEnum accumulator = 0; //Or better yet, FlagsEnum accumulator = FlagsEnum.None if you've followed the design guidelines
foreach(FlagsEnum flag in ListOfflags)
{
accumulator |= flag;
}
return accumulator;
现在,你已经因为没有“无”0而在作品中引起了额外的皱纹,但是我会把这个作为练习留给读者,附加说明MSDN guidelines建议不要做这一点。