C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 149 を表示中)
■86937 / )  Re[2]: フラグを操作するジェネリックメソッドを作る方法
□投稿者/ MTK (40回)-(2018/04/04(Wed) 14:38:54)
No86934 (魔界の仮面弁士 さん) に返信

回答ありがとうございます。


> Where ではなく where ですね。
whereですね、失礼しました。




> 列挙型は型制約として指定できないので、struct で代用しておいた上で
> さらにメソッド内で Type.IsEnum による型チェックを施す感じでしょうか。
>
> public static class BitFlagHelper
> {
>  public static void SetFlag<TEnum>(ref this TEnum self, TEnum flag) where TEnum : struct
>  {
>   System.Diagnostics.Debug.Assert(typeof(TEnum).IsEnum);
>   var bits = Convert.ToUInt64(self) | Convert.ToUInt64(flag);
>   self = (TEnum)System.Enum.ToObject(typeof(TEnum), bits);
>  }
> }

すいません 例で出して頂いたプログラムを調べていますが、まだちゃんと理解できていません;;
型制約をstructで指定しておいて、メソッド内で型チェックをする という理屈は理解できていると思います。
お時間があれば、少し教えて頂けたらと思います。


> public static void SetFlag<TEnum>(ref this TEnum self, TEnum flag) where TEnum : struct
ref this TEnum self  というように this を使っているということはこれは後述されている拡張メソッドなのでしょうか?


> System.Diagnostics.Debug.Assert(typeof(TEnum).IsEnum);
これは型が TEnumかチェックを行い、違っていたらメッセージボックスで呼び出し履歴を表示ですかね


> var bits = Convert.ToUInt64(self) | Convert.ToUInt64(flag);
論理和を使えるように、受け取った変数とフラグをUInt64に変換している? この場合、bitsはUInt64として扱われるのでしょうか?


> self = (TEnum)System.Enum.ToObject(typeof(TEnum), bits);
UInt64型になっている bits を TEnum型に変換し、受け取った変数に保存している?




> しかし、ジェネリックを使うかどうかは抜きにしても、そもそも
> C# では、ref や out な引数にプロパティを渡せない仕様なので、
> 残念ながらそういうことはできません。

ref や out な引数にはプロパティを渡せないんですね。
勉強不足でした。
変数を経由して渡せば、実装は可能なのですね。




> ジェネリック クラスのかわりに、拡張メソッドを使うのはどうでしょうか。
>
> たとえば DateTime 型の Add 何某メソッドは、「日付の加減算結果を返す」メソッドであり、
>   dateTimePicker1.Value = dateTimePicker1.Value.AddDays(1); // 翌日の日付に変更
> などのように書けますが、それを真似て
>  objClassA.PropA = objClassA.PropA.SetFlag(FlagEnumA.Visible); // Visible フラグを立てる
> などと書ける様な SetFlag 拡張メソッドを追加するなど。

こんなやり方があるんですね。
やや冗長になってはしまいますが、汎用的に使えるのは魅力ですね!




> あるいは汎用化に拘らず、クラスA 自身に
>  public bool this[FlagEnumA flag]
>  {
>   get { return this.PropA.HasFlag(flag); }
>   set { if (value) { this.PropA |= flag; } else { this.PropA &= ~flag; } }
>  }
> のようなインデクサを用意して、利用する側から
>  objClassA[FlagEnumA.Visible] = true;
> のようにしてビットフラグを読み書きできるようにしておくとか。
> 今回の目的からは離れてしまいますけれども。

インデクサって使ったことがなかったですが、こんな風に活用できるんですね。
勉強になります。
ありがとうございました。
解決済み
返信 編集キー/


管理者用

- Child Tree -