はじめに
C#ではenumを使ってビット(2進数)フラグを簡単に実装出来ます。
今回はそのビットフラグでフラグを追加&削除する拡張メソッドの紹介です!
SampleFlag flag = SampleFlag.Flag1; Debug.Log($"{flag}"); //フラグ2追加 EnumExtensions.AddFlag(ref flag, SampleFlag.Flag2); Debug.Log($"{flag}"); //フラグ1削除 EnumExtensions.RemoveFlag(ref flag, SampleFlag.Flag1); Debug.Log($"{flag}");
なお、Unityでの使用を想定しているためDebugを使っています。
フラグを追加、削除する拡張メソッド
例えば以下のようなビットフラグがあった場合、
//サンプルのenumのビットフラグ、フラグ1~3 [Flags] public enum SampleFlag { Flag1 = 1 << 0, Flag2 = 1 << 1, Flag3 = 1 << 2, }
通常、フラグを追加する時には|=、削除する時には&=を使います。
SampleFlag flag = SampleFlag.Flag1; Debug.Log($"{flag}"); //フラグ2追加 flag |= SampleFlag.Flag2; Debug.Log($"{flag}"); //フラグ1削除 flag &= ~SampleFlag.Flag1; Debug.Log($"{flag}");
それを以下のような拡張メソッド(とそれを実装しているクラス)を用意する事で、
using System; /// <summary> /// enum 型の拡張メソッドを管理するクラス /// </summary> public static class EnumExtensions { //================================================================================= //ビットフラグ //================================================================================= /// <summary> /// ビットフラグから一つの状態を除く /// </summary> public static T RemoveFlag<T>(this T self, T flag) where T : Enum { return (T)Enum.ToObject(typeof(T), (int)(object)self & ~(int)(object)flag); } /// <summary> /// ビットフラグに一つの状態を追加 /// </summary> public static T AddFlag<T>(this T self, T flag) where T : Enum { return (T)Enum.ToObject(typeof(T), (int)(object)self | (int)(object)flag); } }
AddFlagとRemoveFlagというメソッドに置き換える事が出来ます。
こうする事でより直感的に分かりやすいコードにする事が出来ます。
//フラグ2追加 flag = flag.AddFlag(SampleFlag.Flag2); //フラグ1削除 flag = flag.RemoveFlag(SampleFlag.Flag1);
なお、返り値なしにしたい場合は以下のような感じに。
/// <summary> /// ビットフラグから一つの状態を除く /// </summary> public static void RemoveFlag<T>(ref T self, T flag) where T : struct, Enum { self = (T)Enum.ToObject(typeof(T), (int)(object)self & ~(int)(object)flag); } /// <summary> /// ビットフラグに一つの状態を追加 /// </summary> public static void AddFlag<T>(ref T self, T flag) where T : struct, Enum { self = (T)Enum.ToObject(typeof(T), (int)(object)self | (int)(object)flag); }
//フラグ2追加 EnumExtensions.AddFlag(ref flag, SampleFlag.Flag2); //フラグ1削除 EnumExtensions.RemoveFlag(ref flag, SampleFlag.Flag1);
ちなみにこれらのコードはAI(GitHub Copilot + Chatbot)で書いていたりします。
最初の拡張メソッドはもちろん、
それを返り値なしに書き換えたり、
サンプルのビットフラグも自体もAI製です。
(「ビットフラグってどう記述するんだったかな〜」みたいに思い出せない時にも便利)