2

クライアントから、各 int 値が Enum DayOfWeek の enum int 値である List を取得します。

リストには、タイム プランナーに表示される int 値 (日) のみが含まれます。

0,1,2 (日曜、月曜、火曜) などの int 値のリストを取得すると、これらの値を DayOfWeek 列挙型にどのように書き込めば、7 日間すべてまたは 1 日も機能しない一般的な方法になりますか?

土曜日のインデックスは 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; }

上記のコードは、1 週間のすべての曜日を VisibleDayOfWeek 列挙型に書き込み、データベース フィールドに簡単に保存できるようになりました。

Microsoft MSDN によると、フラグ列挙型の None 値が再び 0 に設定され、残りの値は 2 の累乗になります。

4

5 に答える 5

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();
于 2013-03-22T22:33:21.470 に答える
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,
}

(編集された質問に一致するように編集されました)

于 2013-03-22T22:29:45.383 に答える
0

(1)Undefinedの名前をNoneに変更します。これはセマンティクスによりよく適合します。

(2)DayValueごとに、

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

DayValueは、0、1、...、6の入力値です。

于 2013-03-22T22:28:08.473 に答える
0

あなたはこのようなことをすることができます:

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

編集:私はあなたの質問を間違えたかもしれません、私はあなたが整数のリストを手に入れ、それらをDayOfWeekに変換したいと思ったのです。すべての日が必要な場合は、列挙型に追加する(DayOfWeek)127か、追加することができます。AllDays = 127

于 2013-03-22T22:28:41.537 に答える
0

この質問に対する答えを理解するには、列挙型クラスの[Flags]属性をより深く理解する必要があります。この属性については、MSDNで読むことができます(または使用方法に関するガイドラインを読むことができます)。

「フラグ」属性は、C#とCLRが提供するすべての派手なタイプを持っていなかったCの世界からの残骸のようなものです。

たとえば、さまざまな直交条件(Condition0、Condition1、Condition2などと呼びます。..)を追跡する必要があるが、スペースを節約したり、これらの条件を簡単に渡したりできるCプログラムを作成できます。単一のユニットとして、それらすべてを1つの8ビット(またはそれ以上)の値に詰め込みたいと考えています。次に、次のような条件を定義します。

  • ビット0はCondition0の状態を追跡します
  • ビット1はCondition1の状態を追跡します
  • ビット2はCondition2の状態を追跡します

2進数から10進数への変換を覚えている場合は、次のことがわかります。-ビット0は1の10進値を表します-ビット1は2の10進値を表します-ビット2は4の10進値を表します-ビット4は10進値を表しますof8-ビットnは2のn乗の10進値を表します

したがって、これら2つのリストを組み合わせて、次のことを確認できます。

  • Condition0の値は1です(4ビットバイナリでは0b0001)
  • Condition1の値は2です(4ビットバイナリでは0b0010)
  • Condition2の値は4です(4ビットバイナリでは0b0100)
  • など。。

Condition1とCondition2が発生したことを表す必要がある場合、それはビット1とビット2が設定されていることを意味します。2進数では0b0110、10進数では「6」です。Condition1とCondition2を表す値は、単にCondition1とCondition2の論理ORです。0b0010または0b0110は0b0110です。2または4は6です。

ここで、論理ORと、Condition1とCondition2の合計が上記の例で同じ値(2 + 4 = 2 OR 4)になることに気付いたかもしれません。「わかっている、すべての条件を合計するだけだ!」あなたが言うでしょう。ORとアキュムレータを使用したforループよりも、List.Sum()を作成する方がはるかに簡単です。残念ながら、それは常に機能するとは限りません。

  • 上からの「6」または0b0110の値をもう一度考えてみます。これは、「Condition1およびCondition2」が真であることを意味します。

  • 次に、それを「Condition0とCondition1」が設定されていることを意味する値と組み合わせます。0b0011または10進数の「3」

  • 論理OR-(0b0110 OR 0b0011)を実行すると、0b0111または10進数の7が得られます。これは「Condition0、Condition1、およびCondition2」がすべてtrueのように見えます。それは正しいようです!

ただし、値を合計すると、10進数の9(6 + 3、または0b0110 + 0b0011)が得られ、0b1001になります。0b1001は「Condition3がtrueでCondition0がtrue」のように見えます。これは正しくありません。ここでCondition3はどのように関与し、Condition1とCondition2はどうなりましたか?私たちが始めたとき、それらは両方とも設定されていました!

ここで、C#の世界に戻ります。「フラグ」属性は、「この列挙型は、独立して存在することも存在しないこともできる1つ以上の直交条件で構成できる」ことを意味します。列挙型のさまざまな要素に値が重ならないように割り当てるのは、プログラマーの責任です(Cの場合と同様)。それが完了したら、論理OR演算を実行することにより、これらの直交条件の1つ以上をうまく組み合わせることができます。以前に定義された要素の組み合わせである列挙型の要素を定義することもできます。要素を検討する

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

結論: フラグの合計は、特定のシナリオでのみ機能します(主に、合計される各値が単一の条件を表す場合)。すべての場合に正しく機能する堅牢なコードを作成するには、フラグの論理ORを使用する必要があります。書くのに数行余分にかかるかもしれませんが、それはあなたの意図をより正確に捉え、維持しやすく、誰かがあなたが予期していなかったものをあなたのメソッドに渡した場合により堅牢になります。したがって、リスト内のすべての要素を組み合わせるには、それらすべてを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ガイドラインで推奨されていることを追加して、読者の練習問題として修正しておきます。

于 2013-03-22T23:04:02.987 に答える