C# Enumをビット演算する

Enumを&でつないで計算したいときってありませんか?

例えばエラーの種類をEnumで切っている時などですよね。
エラーが発生したかどうかを知るためには&で計算できると便利です。

でもEnumはoperatorをoverrideすることができません。

そういうときにどうするのか。
ビット演算を使えば&で計算することができます。

    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をbit演算する時に、まとめて扱ってくれる便利な属性があります。
それはFlagsAttributeです。
これを使えば、上記結果の110110のような場合
Error2、Error3、Error5、Error6の混合と判断してくれるようになります。

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

        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をコピーしました