なぜ人々は常に0, 1, 2, 4, 8
ではなく0, 1, 2, 3, 4
のような列挙値を使用するのですか?
これはビット演算などと関係がありますか?
私はこれがどのように正しく使用されるかについての小さなサンプルスニペットを本当に感謝します:)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
それらは2のべき乗であり、私はこれを行うことができるからです。
var permissions = Permissions.Read | Permissions.Write;
そしておそらく後で...
if( (permissions & Permissions.Write) == Permissions.Write )
{
// we have write access
}
これはビットフィールドであり、各セットビットは許可(または列挙値が論理的に対応するもの)に対応します。これらが1, 2, 3, ...
として定義されている場合、この方法でビットごとの演算子を使用して意味のある結果を取得することはできません。深く掘り下げるには...
Permissions.Read == 1 == 00000001
Permissions.Write == 2 == 00000010
Permissions.Delete == 4 == 00000100
ここにパターンがありますか?私の元の例、つまり
var permissions = Permissions.Read | Permissions.Write;
その後...
permissions == 00000011
見る? Read
ビットとWrite
ビットの両方が設定されており、それを個別に確認できます(Delete
ビットがnotであるため、これが設定されているため、値は削除の許可を伝えません)。
単一のビットフィールドに複数のフラグを格納できます。
それでも他の回答から明らかでない場合は、次のように考えてください。
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
書くための短い方法です:
public enum Permissions
{
DeleteNoWriteNoReadNo = 0, // None
DeleteNoWriteNoReadYes = 1, // Read
DeleteNoWriteYesReadNo = 2, // Write
DeleteNoWriteYesReadYes = 3, // Read + Write
DeleteYesWriteNoReadNo = 4, // Delete
DeleteYesWriteNoReadYes = 5, // Read + Delete
DeleteYesWriteYesReadNo = 6, // Write + Delete
DeleteYesWriteYesReadYes = 7, // Read + Write + Delete
}
8つの可能性がありますが、それらを4つのメンバーのみの組み合わせとして表すことができます。 16の可能性がある場合、それらを5つのメンバーのみの組み合わせとして表すことができます。 40億の可能性がある場合、それらを33のメンバーの組み合わせとして表すことができます!列挙で40億個のアイテムに名前を付けようとするよりも、33個のメンバー(それぞれゼロ(ゼロを除く)の2のべき乗)のみを使用する方が明らかにはるかに優れています。
これらの値はバイナリで一意のビット位置を表すため:
1 == binary 00000001
2 == binary 00000010
4 == binary 00000100
など
1 | 2 == binary 00000011
編集:
3 == binary 00000011
2進数の3は、1の場所と2の場所の両方で1の値で表されます。実際には、値1 | 2
と同じです。したがって、バイナリの場所をフラグとして使用して何らかの状態を表す場合、3は通常意味がありません(実際には2つの組み合わせである論理値がない限り)
さらに明確にするために、次のように列挙型の例を拡張できます。
[Flags]
public Enum Permissions
{
None = 0, // Binary 0000000
Read = 1, // Binary 0000001
Write = 2, // Binary 0000010
Delete = 4, // Binary 0000100
All = 7, // Binary 0000111
}
したがって、私はPermissions.All
を持っていますが、Permissions.Read
、Permissions.Write
、およびPermissions.Delete
も暗黙的に持っています
[Flags]
public Enum Permissions
{
None = 0; //0000000
Read = 1; //0000001
Write = 1<<1; //0000010
Delete = 1<<2; //0000100
Blah1 = 1<<3; //0001000
Blah2 = 1<<4; //0010000
}
このように書く方が理解しやすく、読みやすく、計算する必要はないと思います。
これらは、列挙値の組み合わせを許可するビットフラグを表すために使用されます。 16進表記で値を記述するとより明確になると思います
[Flags]
public Enum Permissions
{
None = 0x00,
Read = 0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}
これは本当にコメントですが、書式設定をサポートしていないため、フラグ列挙の設定に使用したメソッドを含めたいだけです。
[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}
このアプローチは、フラグをアルファベット順に維持したい場合に開発中に特に役立ちます。新しいフラグ値を追加する必要があると判断した場合は、アルファベット順にそれを挿入するだけで、変更する必要がある値はその前にある値のみです。
ただし、ソリューションが実稼働システムに公開されると(特に、Webサービスなどで密結合なしで列挙が公開される場合)、列挙内の既存の値を変更しないことを強くお勧めします。
これに対する多くの良い答えがあります…私はただ..あなたが気に入らない場合、または簡単に把握できない what the <<
構文は表現しようとしています。私は個人的に代替手段を好みます(そして、あえて言うと、straightforward enum宣言スタイル)…
typedef NS_OPTIONS(NSUInteger, Align) {
AlignLeft = 00000001,
AlignRight = 00000010,
AlignTop = 00000100,
AlignBottom = 00001000,
AlignTopLeft = 00000101,
AlignTopRight = 00000110,
AlignBottomLeft = 00001001,
AlignBottomRight = 00001010
};
NSLog(@"%ld == %ld", AlignLeft | AlignBottom, AlignBottomLeft);
LOG 513 == 513
理解するのが非常に簡単です(少なくとも、私にとっては)。必要な結果を記述し、希望する結果を取得します。「計算」は必要ありません。