|
.NET TIPS
列挙体をビット・フィールドとして取り扱うには?[C#、VB]
デジタルアドバンテージ 一色 政彦
2010/08/26 |
 |
|
引数としてフラグ(あるいはオプション)を受け取るメソッドを作る場合がある。例えば、引数がtrueであれば「Aモード」で実行し、falseがあれば「Bモード」で実行するといったように、引数の値によって挙動を変えるようなメソッドである。
こういったフラグ・パラメータとしては、2つのモード間での切り替えであればtrue/falseのBoolean型が使えるが、フラグが複数になってくるとEnum型を使う場合が多い。ただし通常のEnum型は、1つの値しか保持できないので、1つの引数で複数のフラグを組み合わせることはできない。
Enum型では、Flags属性(=FlagsAttributeクラス)を付与することで、そのEnum型が、「ビットごとのOR演算」が行えるビット・フィールドとして使えるようになる。これにより、1つの値で複数のフラグの組み合わせを扱える。
例えば.NET Framework 2.0以降の基本クラス・ライブラリでは、ConsoleModifiers列挙体(System名前空間)がビット・フィールドとなっており、[Shift]キー、[Alt]キー、[Ctrl]キーのさまざまな組み合わせを、1つのConsoleModifiers値で表現できる。
次のコードは、実際に独自のEnum型にFlags属性を付与してビット・フィールドとして取り扱うコンソール・アプリケーションのサンプルである。
using System;
// Enum型をビット・フィールド化
[Flags]
public enum SampleOptions
{
A = 0x00,
B = 0x01,
C = 0x02,
}
class Program
{
static void Main(string[] args)
{
// SampleOptionsの「A」と「C」を組み合わせて1つの値を作成
SampleOptions opt = SampleOptions.A | SampleOptions.C;
// SampleOptions値に「A」と「C」が含まれているかを調べる
if (((opt & SampleOptions.A) == SampleOptions.A) &&
((opt & SampleOptions.C) == SampleOptions.C))
{
Console.WriteLine("AとCのフラグが含まれています。");
}
// 出力例:
// AフラグとCフラグが含まれています。
Console.ReadLine(); // 実行を停止
}
} |
' Enum型をビット・フィールド化
<Flags()> _
Public Enum SampleOptions
A = &H0
B = &H1
C = &H2
End Enum
Module Module1
Sub Main()
' SampleOptionsの「A」と「C」を組み合わせて1つの値を作成
Dim opt As SampleOptions = SampleOptions.A Or SampleOptions.C
' SampleOptions値に「A」と「C」が含まれているかを調べる
If (opt And SampleOptions.A) = SampleOptions.A AndAlso _
(opt And SampleOptions.C) = SampleOptions.C Then
Console.WriteLine("AとCのフラグが含まれています。")
End If
' 出力例:
' AフラグとCフラグが含まれています。
Console.ReadLine() ' 実行を停止
End Sub
End Module |
|
独自のEnum型にFlags属性を付与してビット・フィールドとして取り扱う例(上:C#、下:VB) |
上記のコードを見ると、複数のフラグを組み合わせて1つのSampleOptions値を作成する際には「ビットごとのOR演算子」を用い、逆にSampleOptions値に含まれているフラグを調べる(以降、フラグ判定)には「ビットごとのAND演算子」を用いればよいことが分かる。
フラグ判定において、上記のコード例では「A」と「C」の2つのフラグが両方とも含まれているかを調べているが、そのフラグ判定で調べるフラグの数が、例えば10個などと膨大になったり、あるいはその組み合わせパターンが数多くなったりしてくると、次第にその判定処理コードは煩雑で冗長になってきてしまう(可能性がある)。この問題を回避するために、.NET Framework 4のEnum型にはHasFlagメソッドが追加された。
HasFlagメソッドのパラメータには、調べたいフラグの組み合わせ(=ビットごとのOR演算。もちろん1つのフラグのみでも指定可能)で作成された(Enum型の)値を指定する。戻り値として、そのフラグの組み合わせがすべて含まれていればtrueを、1つでも含まれていないとfalseを返す。
次のコードは、上記のフラグ判定のコード個所をHasFlagメソッドに置き換えた例である(該当個所のみ抜粋)。
if (opt.HasFlag(SampleOptions.A | SampleOptions.C))
{
Console.WriteLine("AとCのフラグが含まれています。");
} |
If opt.HasFlag(SampleOptions.A Or SampleOptions.C) Then
Console.WriteLine("AとCのフラグが含まれています。")
End If |
|
(.NET Framework 4で追加された)HasFlagメソッドを用いたフラグ判定(上:C#、下:VB) |
HasFlagメソッドを使わないコード例では2行にわたっていた冗長なフラグ判定が、HasFlagメソッドを使った場合は1行のシンプルな条件文へ、すっきりと短く分かりやすくなっている。
カテゴリ:クラス・ライブラリ 処理対象:列挙体
使用ライブラリ:Enumクラス(System名前空間) |
|
generated by
|
|
Insider.NET 記事ランキング
本日
月間