2013-03-22 132 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

相關問題