2013-03-22 184 views
2

从客户端我得到一个列表,其中每个int值是Enum DayOfWeek的枚举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枚举可能现在可以轻松保存在数据库字段中。

根据微软MSDN的标志枚举现在已经设置为0再次其无值,其余值是电源2.

+0

所以你从内置的星期几,你想将它们转换成你一周中的某天枚举获取值?这是你写的意思吗? – 2013-03-22 22:28:44

+0

家伙,我已经更新了我的问题,改变了枚举值,以更好地适应那里周日有int值0 – Elisabeth 2013-03-22 22:37:39

+1

我想你想扭转这种变化枚举原来DAYOFWEEK枚举值;如果只是这样,它默认为None,而不是Sunday。只有在未初始化或使用Default方法设置时。 – 2013-03-22 22:40:43

回答

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(); 
+0

+1的意图,以获得优雅和解释性答案。 – 2013-03-22 22:36:56

+0

guys我更新了我的问题,并更改了枚举值以更好地适应星期日具有int值0的原始DayOfWeek枚举值 – Elisabeth 2013-03-22 22:38:07

+0

也更新了我的答案。 – MarcinJuraszek 2013-03-22 22:42:38

0

(1)改变未定义为无名称;这更符合语义。

(2)对于每一个DayValue,设置

dayOfWeek |= (DayOfWeek) Math.Pow(2,DayValue); 

DayValue在输入淡水河谷未来:0,1,...,6

+0

家伙,我已经更新了我的问题,改变了枚举值,以更好地适应那里周日有int值0 – Elisabeth 2013-03-22 22:38:51

0

你可以做这样的事情:

var days = (DayOfWeek)listOfValues.Sum(); 

编辑:我可能得到你的问题错了,我想你得到一个整数列表,并希望将它们转换为DayOfWeek。如果你只需要所有的日子,你可以做(DayOfWeek)127或者只需将AllDays = 127添加到枚举中。

+0

原DAYOFWEEK枚举值我会从奥尔代斯坚持=周日|星期一|星期二|星期三|星期四|星期五|星期六|星期日更准确地记录 – 2013-03-22 23:33:40

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

(编辑,以匹配编辑的问题)

0

理解这个问题的答案需要一个更深入地理解你的枚举类中的[Flags]属性。你可以阅读关于这个属性的知识(或者阅读一些关于如何使用它的指导)here at MSDN

“Flags”属性是C世界的一种遗留问题,你没有所有的幻想类型C#和CLR给你。例如,你可以有一个需要跟踪一堆不同正交条件(我们称之为Condition0,Condition1,Condition2等)的C程序,但为了节省空间,或者使它更容易将这些条件作为一个单元传递,我们希望将它们全部塞入一个8位(或更大)值。你会做什么,然后就是定义的条件使得:

  • 位0磁道Condition0的状态
  • 位1个曲目条件1的状态
  • 位2米的轨道条件2的状态
  • 等。

如果你还记得你的二进制到十进制转换,你就会知道, - 位0代表1 十进制值 - 第1位代表2十进制值 - 位2表示4 十进制值 - 第4位表示8 的十进制值 - 位n表示2至n的功率的十进制值

因此,我们可以结合这两个列表,并看到:

  • Condition0具有1(0b0001在4位二进制)的值
  • 条件1具有2(0b0010在4位二进制)的值
  • 条件2具有4(0b0100中的值4位二进制)
  • 等。 。

如果我们需要表示条件1和条件2已经发生,那么这意味着位1和位2被设置。在二进制中,这是0b0110,十进制是“6”。表示Condition1和Condition2的值只是Condition1和Condition2的逻辑或。 0b0010或0b0110是0b0110。 2或4是6.

现在,您可能已经注意到逻辑OR,Condition1和Condition2的总和在上例(2 + 4 = 2或4)中出现相同的值。 “我知道,我只是把所有的条件总结在一起!”你会说。编写List.Sum()比使用ORs和累加器的for循环更容易。不幸的是,这并不是一直工作。

  • 再次考虑从上面的“6”或0b0110的值,这意味着“条件1和条件2”为真。

  • 然后结合起来,与表示“Condition0和条件1”被设置的值。 0b0011或十进制“3”

  • 如果您执行逻辑或 - (0b0110或0b0011),将得到0b0111或十进制7.这看起来像“条件0,条件1和条件2”均为真。这似乎是正确的!

如果增值在一起,不过,你会得到十进制9(6 + 3或0b0110 + 0b0011),它出来到0b1001。 0b1001看起来像“条件3是真的,条件0是真的”这不可能是正确的。 Condition3是如何涉及这里以及Condition1和Condition2发生了什么?当我们开始的时候,他们都已经定了

现在,回到C#的世界 - “标志”属性的意思是“这个枚举可以由的,可以存在或不能独立存在一个或多个正交条件”。程序员可以自己决定为枚举的不同元素赋值,使它们不重叠(就像在C中一样)。一旦完成,您可以通过对它们执行逻辑或运算来愉快地组合一个或多个这些正交条件。您甚至可以在枚举中定义以前定义的元素组合的元素。考虑的元素

Weekends = Saturday | Sunday, 
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday, 

在结论: 总结标志只能在某些情况下(主要是当每个正被求和值表示一个单一的条件)。为了编写在所有情况下都能正常工作的健壮代码,您应该坚持使用逻辑或的标志。可能需要额外写几行,但它能更准确地捕捉你的意图,更容易维护,并且如果有人将你不期望的东西传递给你的方法,它会更加健壮。因此,要将列表中的所有元素组合在一起,您应该将它们全部组合在一起。像

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推荐阅读反对这样做。

+0

我把None设置为64,这是因为我认为0代表星期日适合DayofWeek周日也是0。越来越多的我理解这一切:) – Elisabeth 2013-03-22 23:45:50

+0

设计指南建议不要这样做的原因是因为那么你最终可能会得到一组意味着“无星期天和星期一”的标志,这没有任何意义。东西是None或不是。如果你使None = 0,那么“None”和任何其他标志是互斥的。 – 2013-03-22 23:52:14