投稿数 - 437, コメント - 56274, トラックバック - 156

FlagsAttribute - ビット演算は一般的ではないか

ある値が複数の意味を持つ場合、それぞれのビットに意味を持たせる。

C/C++ 等では定数を定義して、unsigned int 等と組み合わせて使う。.NET では FlagsAttribute と enum を組み合わせて使えるので便利だ。

私は FlagsAttribute を割と頻繁に使うのだが、これが分かりにくいというクレームを受けた。例えば以下のようにしていたとしよう。

[Flags]
public enum TestFlags {
    A = 0x1,
    B = 0x2,
    C = 0x4
}
 
public class TestClass {
    public TestFlags Flag;
}

クレームをつけた本人は理解しているのだが、「ビット演算は難しい。使用法を間違う人もいる。それぞれをプロパティで持たせればよい」と言った。例えば以下のように。

public class TestClass {
    public bool EnableA;
    public bool EnableB;
    public bool EnableC;
}

確かに一理ある。しかし「間違う人がいるか?こんなのが分からないという人は、(言語仕様の一部なのだから)if 文が分からないと言っているのと一緒だ」と思ったが、現にビット演算がよく分からなくて変なコードを書く人がいる。

以下のように 2 つの変数があり、一方がもう一方にに立っているビットの少なくとも一つがあるかをチェックしたいときは、 if 文 1 つで済む、というのが私の言い分だ。

public void Func1() {
    TestClass t1 = new TestClass();
    TestClass t2 = new TestClass();
 
    if ((t1.Flag & t2.Flag) != 0) {
    }
}

相手の言い分は、例えば以下のように書くのは違和感があるという事だ。

public void Func2() {
    TestClass test = new TestClass();
    checkBox1.Checked = (test.Flag & TestFlags.A) != 0;
    checkBox1.Checked = (test.Flag & TestFlags.B) != 0;
    checkBox1.Checked = (test.Flag & TestFlags.C) != 0;
}

上記を次のように書けた方がよい。

public void Func2() {
    TestClass test = new TestClass();
    checkBox1.Checked = test.EnableA;
    checkBox1.Checked = test.EnableB;
    checkBox1.Checked = test.EnableC;
}

私はどちらの書き方でも何の違和感もないし、Flag である事がわかるなら、前者の方がいいぐらいだ。

…で、家への帰路の間考えていたが、やはり私の方が間違っていて、フィールドやプロパティに FlagsAttribute の enum は持たせない方がよいのではないか、と考え直した。

オブジェクト指向言語では、フィールドやプロパティを幾らでもオブジェクトに持たせる事ができるのに、わざわざ一つのプロパティに複数の意味を持たせる必要はない。

では、FlagsAttribute の enum はいつ使われるのか。

恐らく、メソッドへの引数が唯一の正確な使用法なのだろう。

投稿日時 : 2006年12月19日 22:53

フィードバック

# re: FlagsAttribute - ビット演算は一般的ではないか

FlagsAttributeですか。。。個人的にはあまり好きじゃないですねぇ。
(理解はできますよ:笑)

Type type = typeof(Sample);
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
MethodIno[] methodInfos = type.GetMethods(flags);

『Public 「かつ」 Instance』 なのに or(|)で結ぶ。。。
フラグの論理演算だからあってるんだけど、、、直感的じゃないような気がします。

2006/12/19 23:30 | ネットクラゲ

# re: FlagsAttribute - ビット演算は一般的ではないか

インスタンスで値を保持していると考えれば、引数に関しても代用可能な手段は存在しますね。
まあ、値型な単純データ型という意味では、使っていきたい存在に見えます。

ただ (複合データの場合に限定されますが) 引数として使うまでの道のり (準備が終了する) までの方が、とっつきにくそうですね。> 例にあがった人たち
2006/12/19 23:36 | じゃんぬねっと

# re: FlagsAttribute - ビット演算は一般的ではないか

> 『Public 「かつ」 Instance』 なのに or(|)で結ぶ。。。
> フラグの論理演算だからあってるんだけど、、、直感的じゃないような気がします。

OR の演算結果なので、直感的だと思いますが...
2006/12/19 23:37 | じゃんぬねっと

# re: FlagsAttribute - ビット演算は一般的ではないか

大きな採用理由の違いに値の種類の変動性があると思います。
デザインで言えば個々のチェックボックスになるかCheckedListBoxになるか、というところでしょうか。
メンバが増えた場合にどちらもそれに対する追加のみで互換性の維持ができると思いますが
ビット論理和の場合、その属性メンバに依存しない処理の場合は完全に互換性が保たれますね。(実装の修正無し)

たまたま今の仕事でユーザークラスにFlags属性のユーザー権限プロパティを持たせましたが
同時にHasPermission(value As Permission) As Booleanメソッドを実装しました。
どっちかというとBool演算が面倒というのが理由ですけど。
2006/12/19 23:43 | まどか

# re: FlagsAttribute - ビット演算は一般的ではないか

コメントありがとうございます。
簡単な概念なのですけど、直感的ではないというのは頷けます。
普通の OR とビット演算の OR は意味が食い違う場合が確かにありますね。
ビット論理和の場合は実装の修正無しで互換性が保たれるという利点は。特にDBのテーブルと対応する場合は列の追加の必要がなく便利です。
2006/12/20 12:34 | 囚人

# re: FlagsAttribute - ビット演算は一般的ではないか

MSDNのサンプルが結構おもしろいす。 ちゃんと比較されてあるので
2006/12/20 14:43 | おぎわら

# re: FlagsAttribute - ビット演算は一般的ではないか

お~、そうなんですか?あまりサンプルを見ないので気づきませんでした。
見てみます。
2006/12/20 20:04 | 囚人

# re: FlagsAttribute - ビット演算は一般的ではないか

C# はまったく知らないので、C++ の話ですが、
flags は #define でビット幅まで自由に使えるのが便利です。
OOのプロパティという概念を重視するなら、なるほど bool とも
思いました。

実際にはファイルアクセスする際に、flags だと1回で済むのが
最大の利点だと思っていましたが、Vistaでメモリキャッシュ
されたならプロパティ方式の方がいいかも・・・とか考えています。
2006/12/21 1:41 | RAPT

# re: FlagsAttribute - ビット演算は一般的ではないか

>実際にはファイルアクセスする際に、flags だと1回で済むのが
>最大の利点だと思っていましたが、Vistaでメモリキャッシュ
>されたならプロパティ方式の方がいいかも・・・とか考えています。

ちょっとよく分からないのですが、変数単位で I/O が発生するシステムがあるという意味でしょうか?
2006/12/21 12:44 | 囚人

# re: FlagsAttribute - ビット演算は一般的ではないか

>> 『Public 「かつ」 Instance』 なのに or(|)で結ぶ。。。
>> フラグの論理演算だからあってるんだけど、、、直感的じゃないような気がします。
>
>OR の演算結果なので、直感的だと思いますが...
>2006/12/19 23:37 | じゃんぬねっと
んと、私の中ではですが、
とってくるメンバーの条件を指定している感覚なんですよね。

SQLのWHERE句で考えると、
WHERE 公開度="Public" AND 所属="Instance"

そのままプログラムに持ってくると

BindingFlags.Public & BindingFlags.Instance

あれ?ってなるわけです(笑)
たぶん、そこがビットフラグだって意識が薄いせいでしょうね。
2006/12/24 11:57 | ネットクラゲ

# コピー専門店

とにかく丁寧な対応をしていただき、
高価な買い物でしたが安心して購入できました。
ネットで見るよりもすばらしいダイヤです。
一生物のお買い物ができ、実店舗があるということで
とても信頼できました。
またご縁がありましたらリピートしたいと思っております。
コピー専門店 https://www.bagraku.com/Product/PicView/-picid=31648&proid=7682.htm
2022/09/30 21:25 | hwpkfv@live.jp

コメントの投稿

タイトル
名前
URL
コメント