(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!

    

enumのビットフラグでフラグを追加、削除する拡張メソッド【C#】【拡張メソッド】


このエントリーをはてなブックマークに追加




はじめに

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);
  }
  
}


AddFlagRemoveFlagというメソッドに置き換える事が出来ます。

こうする事でより直感的に分かりやすいコードにする事が出来ます。

//フラグ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製です。

(「ビットフラグってどう記述するんだったかな〜」みたいに思い出せない時にも便利)