【C#】複数のbool型の変数値をひとつの変数で管理する方法【初心者向け】

# 概要
bool型の変数が複数ある場合、それぞれの変数の値をひとつの変数で管理する方法について記載しました。

# 説明
例えばWPFのMVVMパターンの場合、下記のようにとある画面 (以下、サンプル画面と表記します) にトグルボタンが3つあり、

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533049/c02c32dc-c1ea-04f2-e929-47387f196b2b.png" width=50%>

ViewModelに上記3つのボタンの押下状態を表すbool型のプロパティを持っているとします。

bool型のプロパティはそれぞれ、
- `isButtonASelected` (ボタンAの押下状態)
- `isButtonBSelected` (ボタンBの押下状態)
- `isButtonCSelected` (ボタンCの押下状態)

という名前になっているとします。

上記のような場合で、各ボタンの押下状態をどこかに保存したい場合にそのまま保存しようとすると、A～Cボタンそれぞれの押下状態 (`true` もしくは `false`) を保存することになり、保存領域も各ボタンの数の分だけ用意しないといけません。
※例えばボタンが5つあったら5つのbool値を保存することになるので、5つの保存領域が必要です。

上記のような場合に、保存領域をひとつのみで完結できる (ボタンの押下状態をひとつの変数で管理する) 方法を記載します。

# 方法
まず以下のように、`FlagsAttribute`を付与したenumを定義します。

```C#
    [Flags]
    enum ButtonStatus
    {
        None = 0,
        ButtonASelected = 1,
        ButtonBSelected = 2,
        ButtonCSelected = 4
    }
```
enumに`FlagsAttribute`を定義すると、emumをビットフラグとして扱えるようになります。

※参考
- [列挙体をビット・フィールドとして取り扱うには？](https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/1052enumflags/enumflags.html#:~:text=Enum%E5%9E%8B%E3%81%A7%E3%81%AF%E3%80%81Flags%E5%B1%9E%E6%80%A7%EF%BC%88%EF%BC%9DFlagsAttribute%E3%82%AF%E3%83%A9%E3%82%B9%EF%BC%89%E3%82%92%E4%BB%98%E4%B8%8E%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%A7%E3%80%81%E3%81%9D%E3%81%AEEnum%E5%9E%8B%E3%81%8C%E3%80%81%E3%80%8C%E3%83%93%E3%83%83%E3%83%88%E3%81%94%E3%81%A8%E3%81%AEOR%E6%BC%94%E7%AE%97%E3%80%8D%E3%81%8C%E8%A1%8C%E3%81%88%E3%82%8B%E3%83%93%E3%83%83%E3%83%88%E3%83%BB%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8B%E3%80%82,%E3%81%93%E3%82%8C%E3%81%AB%E3%82%88%E3%82%8A%E3%80%811%E3%81%A4%E3%81%AE%E5%80%A4%E3%81%A7%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%95%E3%83%A9%E3%82%B0%E3%81%AE%E7%B5%84%E3%81%BF%E5%90%88%E3%82%8F%E3%81%9B%E3%82%92%E6%89%B1%E3%81%88%E3%82%8B%E3%80%82)
- [C#で列挙型(enum)をビットフラグとして判定および演算する](https://johobase.com/judge-calculate-enum-csharp/)

上記の`FlagsAttribute`を定義したenumをもとに、今回はサンプル画面のボタンの押下状態を保存、復元してみます。

### サンプル画面のボタンの押下状態を取得する
まずはサンプル画面の各ボタンの押下状態をひとつの変数に代入する方法です。

```C#
    var buttonStatus = ButtonStatus.None;
    if (isButtonASelected) buttonStatus |= ButtonStatus.ButtonASelected;
    if (isButtonBSelected) buttonStatus |= ButtonStatus.ButtonBSelected;
    if (isButtonCSelected) buttonStatus |= ButtonStatus.ButtonCSelected;
```
上記の形で、変数`buttonStatus`に各ボタンの押下状態をまとめた値が代入されます。
もちろん通常のEmumと同様、int型にも変換ができます。
この`buttonStatus`の値をどこかに保存しておけば、いつでもサンプル画面のボタン押下状態を復元することができます。

### 保存しておいた値からトグルボタンの押下状態を復元する
[サンプル画面のボタンの押下状態を取得する](#サンプル画面のボタンの押下状態を取得する)で変数`buttonStatus`にボタンの押下状態を代入しましたが、次はこの変数を使用して、押下状態を復元する方法です。

```C#
    // ボタンAの復元
    bool isButtonASelected = (buttonStatus & ButtonStatus.ButtonASelected) != 0;
    // ボタンBの復元
    bool isButtonBSelected = (buttonStatus & ButtonStatus.ButtonBSelected) != 0;
    // ボタンCの復元
    bool isButtonCSelected = (buttonStatus & ButtonStatus.ButtonCSelected) != 0;
```
上記のかたちで`buttonStatus`の値をもとに、各bool型のプロパティに`true`もしくは`false`が格納されます。
上記コードの変数`buttonStatus`はenum型の想定ですが、通常のenumと同様に整数値からenum型にキャストすることもできます。なので保存していた値が整数値の場合は事前にenum型にキャストしてから、上記のコードのように行うと復元できます。

# 補足
最初に定義したenumですが、下記のように2進数で表現することもできます。
このようにすると見やすいかもしれません。
※例としてボタンがA～Fの6つある場合で記載しています。

```C#
    [Flags]
    enum ButtonStatus
    {
        None = 0b_000_000,
        ButtonASelected = 0b_000_001,
        ButtonBSelected = 0b_000_010,
        ButtonCSelected = 0b_000_100,
        ButtonDSelected = 0b_001_000,
        ButtonESelected = 0b_010_000,
        ButtonFSelected = 0b_100_000,
    }
```

:::note
二進数は先頭に`0b`をつけて表現します。
また`_`を付けて定位置で区切ると、視覚的にも見やすくなります。
:::

# 終わりに
今回はトグルボタン3つの例でしたが、これがチェックボックス等、他のON、OFFを表現するコントロールの場合でも同じように対応できます。(当たり前ですが)
またボタンが4つ以上の場合も今回のパターンをベースに対応が可能です。