C# enum [Flags]的使用

用枚举保存状态是很方便的 利用位运算可以简洁明了

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

[Flags]
public enum TestState
{
    aaa = 1,//0001
    bbb = 2,//0010
    ccc = 20,//0011
    ddd = 4,//0100
    eee = 7,//0111
    fff = 8,//1000
    ggg = 12,//1100
}

[Flags]
public enum StateMunte
{
    金 = 0x0001,
    木 = 0x0002,
    水 = 0x0004,
    火 = 0x0008,
    土 = 0x0010,
    生 = 0x0020,
    旦 = 0x0040,
    净 = 0x0080,
    末 = 0x0100,
    丑 = 0x0200
}
[Flags]
public enum StateBin
{
    金 = 1,
    木 = 1 << 1,
    水 = 1 << 2,
    火 = 1 << 3,
    土 = 1 << 4,
    生 = 1 << 5,
    旦 = 1 << 6,
    净 = 1 << 7,
    末 = 1 << 8,
    丑 = 1 << 9,
}
public class TestNum : MonoBehaviour
{
    TestState testState = TestState.bbb;//不需要用new关键字
    TestState stateCom;//不需要用new关键字
    TestState statecccggg;//
    TestState stateeeefff;//
    StateMunte stateMunte;
    StateBin stateBin;
    StateMunte munteCom;
    void Start()
    {
        Debug.Log("testState:" + testState);//print:testState:bbb
        stateCom = TestState.aaa | TestState.bbb;//| &是做位运算,也是二进制运算1|2就是0001|0010 →0011=3,3→ccc
        Debug.Log("stateCom:" + stateCom);//print:stateCom:ccc
        stateCom = TestState.aaa | TestState.ddd;//0001|0100→ 0101=5,如果没有flags标记,5在enum列表中没有对应的话,debug出来的是数字5, enum 本就是 int值类型,在标记flags时,如果5能够每拆解成对应的枚举状态,那就会被拆解
        Debug.Log("stateCom:" + stateCom);//print:stateCom:aaa, ddd
        stateCom = TestState.bbb & TestState.ccc;//0010&0011→0010
        Debug.Log("stateCom:" + stateCom);//print:stateCom:bbb
        stateCom = (TestState)5;
        Debug.Log("(TestState)5:" + stateCom);//print:(TestState)5:aaa, ddd
        stateCom = TestState.bbb | TestState.ccc;//0010|0011
        Debug.Log("stateCom:" + stateCom);//print:stateCom:ccc

        statecccggg = TestState.ccc | TestState.ggg;//0011|1100→1111=15;
        stateeeefff = TestState.eee | TestState.fff;//0111|1000→1111=15;
        Debug.Log("statecccggg:" + statecccggg);//print:statecccggg:ccc, ggg
        Debug.Log("stateeeefff:" + stateeeefff);//print:statecccggg:ccc, ggg;两者打印结果相同可见,枚举类型做位运算其实就是对int进行位运算,算出来的结果也是int,然后转换成枚举,在没有flags的情况下若没有直接对应的状态值,则会输出为数字,在有flags的情况下,若没有直接应的状态值,则会检索枚举中能组合成该值得状态组合.按两者打印相同的结果来看,检索是有检索规则的,按对应int值从小到大检索,匹配成功则确定了枚举值;对此检索规则产生怀疑:有可能是按照枚举状态在列表中的位置来检索的,我调整过枚举对应的位置,把 eee放在ccc的前面,但结果是一样的,所以一个int的值转换成在flags的枚举若没有直接对应的状态则会考虑分解判断.目前可分解成两个,那是否可分解成3个或更多,下面来做测试.在上面枚举1011的状态时没有的,但可以由0001 0010 1000组成,也可以由0011  1000组成.1011=11

        Debug.Log(" (TestState)11:" + (TestState)11);//print: (TestState)11:ccc, fff;当我把ccc的值调整,让0011不存在,0011  1000组合也就不成立了, 然后再测试 print:(TestState)11:aaa, bbb, fff; 由此可见 分解考虑会先从数量少的开始匹配.如果没有则加深检测
        Debug.Log("```````````````````````````````````华丽的分割线`````````````````````````````````");
        Type type = typeof(StateMunte);
        FieldInfo[] fieldInfos = type.GetFields();
        for (int i = 0; i < fieldInfos.Length; i++)
        {
            Debug.Log(string.Format(" fieldInfos[{0}]:{1}", i, fieldInfos[i]));
            Debug.Log(string.Format(" fieldInfos[{0}].name:{1}", i, fieldInfos[i].Name));
        }
        Debug.Log("```````````````````````````````````华丽的分割线`````````````````````````````````");
        stateMunte = StateMunte.木 | StateMunte.水 | StateMunte.火 | StateMunte.土;
        stateBin = StateBin.丑;
        Debug.Log("stateMunte:" + stateMunte);
        Debug.Log("(int)stateMunte:" + (int)stateMunte);
        Debug.Log("stateBin:" + stateBin);
        Debug.Log("(int)stateBin:" + (int)stateBin);

        munteCom = StateMunte.水 | StateMunte.火 | StateMunte.土;
        Debug.Log(" munteCom.CompareTo(stateMunte):" + munteCom.CompareTo(stateMunte));//比大小
        //munteCom.HasFlag();
        stateMunte.Equals(munteCom & stateMunte);
        if (stateMunte.Equals(munteCom & stateMunte))
        {
            Debug.Log(true);
        }
        else
        {
            Debug.Log(false);
        }
    }
}

你可能感兴趣的:(C#,enum,Flags)