从客户端我得到一个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,
}
UPDATE
这是来自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的幂 .
5 回答
那个奇怪的
((i + 6) % 7)
是必要的,因为标准DayOfWeek
从星期日开始,而你的星期日有64
.您也可以使用LINQ将标志聚合为单个
int
值:Update
对于更改的标志,您必须更改翻译查询:
像这样:
(编辑以匹配编辑的问题)
你可以这样做:
编辑:我可能错了你的问题,我认为你得到一个整数列表,并希望将它们转换为DayOfWeek . 如果你只想要所有的日子,你可以做
(DayOfWeek)127
或只是添加AllDays = 127
枚举 .(1)将Undefined的名称更改为None;这更符合语义 .
(2)对于每个DayValue,设置
DayValue是输入值:0,1,...,6
理解这个问题的答案需要更深入地了解枚举类的[Flags]属性 . 您可以阅读有关此属性的信息(或阅读有关如何使用它的一些指导原则)here at MSDN
“Flags”属性是C世界的遗留物,你没有C#和CLR给你的所有花哨类型 .
例如,你可能有一个C程序需要跟踪一堆不同的正交条件(我们称之为Condition0,Condition1,Condition2等......)但是为了节省空间,或者为了更容易通过这些条件作为一个单元,我们希望将它们全部塞入一个8位(或更大)值 . 那么你要做的是定义以下条件:
位0跟踪Condition0的状态
位1跟踪Condition1的状态
位2跟踪Condition2的状态
等
如果你还记得你的二进制到十进制转换,你就会知道 - 位0表示十进制值1 - 位1表示十进制值2 - 位2表示十进制值4 - 位4表示十进制值8位 - n表示n的幂的小数值2
因此,我们可以将这两个列表结合起来,看看:
Condition0的值为1(4位二进制为0b0001)
Condition1的值为2(4位二进制为0b0010)
Condition2的值为4(4位二进制为0b0100)
等 . .
如果我们需要表示发生了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运算来愉快地组合这些正交条件中的一个或多个 . 您甚至可以在枚举中定义元素,这些元素是先前定义的元素的组合 . 考虑这些要素
In Conclusion: 对标志求和仅适用于某些情况(主要是当每个被求和的值表示单个条件时) . 为了编写在所有情况下都能正常工作的健壮代码,您应该坚持使用标志的逻辑OR . 可能需要额外的几行来编写,但它更准确地捕获您的意图,更容易维护,并且如果有人将您不期望的内容传递到您的方法中,则会更加强大 . 因此,要组合列表中的所有元素,您应该将它们全部组合在一起 . 就像是
现在,你将've thrown an extra wrinkle in the works by not making 2801505 0, but I' ll作为一项练习留给作为练习的读者添加了注释MSDN guidelines建议不要这样做 .