C# Enumをビット演算する

Enumをビット演算する有用性

Enumを&でつないでビット演算したいときってありませんか?
例えばエラーの種類をEnumで定義している時、どれとどれのエラーが発生したかどうかを知るためには&で計算できると便利ですよね。
でもEnumはoperatorをoverrideすることができません。

operatorをoverrideできないEnumをビット演算する方法

そういうときにどうするのか。
Enumを16進数で定義すれば&で計算することができます。

using System;

namespace EnumCalcLikeErrorCode
{
    class Program
    {
        static void Main(string[] args)
        {
            var errorList = ErrorManager.Failure2() 
                | ErrorManager.Failure3() 
                | ErrorManager.Failure5() 
                | ErrorManager.Failure6();

            if (errorList.IsNone())
                Console.WriteLine("Any errors weren't occurred!");
            if (errorList.ContainsFailure2())
                Console.WriteLine("Failure2!");
            if (errorList.ContainsFailure6())
                Console.WriteLine("Failure6!");

            Console.WriteLine(Convert.ToString((int)errorList, 2));
            Console.ReadKey();
        }
    }

    internal static class ErrorManager
    {
        internal static Error Failure1() => Error.Error1;
        internal static Error Failure2() => Error.Error2;
        internal static Error Failure3() => Error.Error3;
        internal static Error Failure4() => Error.Error4;
        internal static Error Failure5() => Error.Error5;
        internal static Error Failure6() => Error.Error6;
    }

    internal enum Error
    {
        None = 0x00,
        Error1 = 0x01,
        Error2 = 0x02,
        Error3 = 0x04,
        Error4 = 0x08,
        Error5 = 0x10,
        Error6 = 0x20,
    }

    public static class FruitExTension
    {
        internal static bool IsNone(this Error error)
        {
            return error == Error.None;
        }
        internal static bool ContainsFailure2(this Error error)
        {
            return (error & Error.Error2) == Error.Error2;
        }
        internal static bool ContainsFailure6(this Error error)
        {
            return (error & Error.Error6) == Error.Error6;
        }
    }
}

結果は下記のようになります。

Enumをビット演算した結果

最後に & 関連書籍

以上になります。

分かりにくいところや、「もっとこうしてほしい」などのご意見がありましたら、ツイッターから連絡いただけると幸いです。
質問に関しても、お気軽にお問い合わせください。

C#でスマホアプリの開発を公開しています。

興味があれば見てみてください。

以下は関連書籍です。

[追記]

FlagsAttribute

また、Enumをbit演算する時に、各16ビットをそれぞれフラグと判断してくれる便利な属性があります。
それはFlagsAttributeです。
これを使えば、上記結果の110110のような場合
Error2、Error3、Error5、Error6の混合と判断してくれるようになります。

.NetでのFlagsAttributeを使用したクラスの一例

.NetのクラスでFlagsAttributeを使用しているものとしてCompareOptionsなどがあります。
CompareOptionsは文字列の比較で、大文字と小文字の違いを無視したいときや、
全角と半角の違いを無視したいときに使えます。
せっかくなんで大文字と小文字の違いと全角と半角の違いを無視した文字列比較の1例をあげてみます。

using System;
using System.Globalization;

namespace CompareInfo
{
    class Program
    {
        static void Main(string[] args)
        {
            var str0 = "HELLO";
            var str1 = "hello";
            var str2 = "HELLO";
            var str3 = "hello";

            Console.WriteLine(IsStringsSame(str0, str1));
            Console.WriteLine(IsStringsSame(str0, str2));
            Console.WriteLine(IsStringsSame(str0, str3));
        }
        
        static bool IsStringsSame(string str1, string str2)
        {
            var compareInfo = CultureInfo.CurrentCulture.CompareInfo;
            return compareInfo.IndexOf(
                str1, 
                str2, 
                CompareOptions.IgnoreCase | CompareOptions.IgnoreWidth
                ) >= 0;
        }
    }
}

結果は3つとも全てTrueとなります。

コメント

タイトルとURLをコピーしました