C# Flags

一个数字表示多种状态

二进制:
1->有这个状态
0->没有这个状态
////////////////////////////////////////////////////////////
对于一个8位数的二进制数字
位编号 7 6 5 4 3 2 1 0
含义
比如我们约定:
位0表示等待消息
位1表示超时
位2表示断线
00000111就表示:等待消息+超时+断线

单独操作某一个数:
1.只打开位0(等待消息)
二进制 00000001 = 十进制 1
2.只打开位1(超时)
二进制 00000010 = 十进制 2
3.只打开位2(断线)
二进制 00000100 = 十进制 4

会发现:1、2、4、8、16、32......(2的幂次方)2^位

4.同时打开位0和位1
二进制 00000011 = 十进制 3(1+2=3)
5.同时打开位0和位1和位2
二进制 00000111 = 十进制 7(1+2+4=7)
//////////////////////////////////////////////////////////////////////////
左移运算符<<
1 << n 的意思:把二进制数字 1 向左移动 n 位。
1 << 0 -> 00000001 = 十进制1
1 << 1 -> 00000010 = 十进制2
1 << 2 -> 00000100 = 十进制4
1 << 3 -> 00001000 = 十进制8
1 << 4 -> 00010000 = 十进制16
1 << 5 -> 00100000 = 十进制32
//////////////////////////////////////////////////////////////////////////
按位或运算符 | , 作用是合并
有一个真就是真
全假才假
0 | 1 = 1
0 | 0 = 0

2 | 4 = 6
2: 00000010
4: 00000100
2 | 4:00000110 = 十进制 6
//////////////////////////////////////////////////////////////////////////
按位与运算符 & ,作用是检查是否包含某个状态
全真才为真
检查 6(二进制 00000110)里是否包含 4(二进制 00000100):
6 & 4
6: 00000110
4: 00000100
6 & 4:00000100 = = 十进制 4 不等于0表示包含4

检查 6 里是否包含 8(二进制 00001000):
6 & 4
6: 00000110
4: 00001000
6 & 8:00000000 = = 十进制 0 等于0表示不包含8
//////////////////////////////////////////////////////////////////////////
~ 是 按位取反运算符(也叫位非运算符)。
~ 把一个二进制数的每一位 0 变成 1,1 变成 0。
//////////////////////////////////////////////////////////////////////////
C# [Flags]
是一个标记,告诉编译器:
这个枚举是用来组合多个状态的
调用 .ToString() 时,输出 "WaitMsgPacket, TimeOut" 而不是 "6"
Flags枚举 = 用一个整数的每个二进制位当做一个独立的开关。| 用来组合开关,& 用来检查开关。

例子:
假设你是一个系统管理员,要给用户分配权限:
读权限(Read)
写权限(Write)
执行权限(Execute)
每个用户可以同时拥有多个权限(比如:读+写,或者 读+写+执行)。

[Flags]
enum Permission
{
    None    = 1 << 0,  // 1  (二进制 001)
    Read    = 1 << 1,  // 2  (二进制 010)
    Write   = 1 << 2,  // 4  (二进制 100)
    Execute = 1 << 3,  // 8  (二进制 1000)
    // ReadWrite = Read | Write,  // 2|4 = 6 (二进制 0110)
    // All = Read | Write | Execute  // 2|4|8 = 14 (二进制 1110)
}
class Program
{
    static void Main()
    {
        // 1. 给用户分配"读+写"权限(用 | 组合)
        Permission user1 = Permission.Read | Permission.Write;
        Console.WriteLine($"用户1的权限:{user1}");  // 输出:Read, Write
        
        // 2. 检查用户1有没有"读"权限(用 & 检查)
        bool hasRead = (user1 & Permission.Read) != 0;
        Console.WriteLine($"用户1有读权限吗?{hasRead}");  // True
        
        // 3. 检查用户1有没有"执行"权限
        bool hasExecute = (user1 & Permission.Execute) != 0;
        Console.WriteLine($"用户1有执行权限吗?{hasExecute}");  // False
        
        // 4. 给用户1加上"执行"权限(用 | 添加)
        user1 = user1 | Permission.Execute;
        Console.WriteLine($"用户1现在的权限:{user1}");  // 输出:Read, Write, Execute
        
        // 5. 去掉用户1的"写"权限(用 & 和 ~ 去掉)
        user1 = user1 & ~Permission.Write;
        Console.WriteLine($"用户1去掉写权限后:{user1}");  // 输出:Read, Execute
        
        // 6. 也可以用 HasFlag 方法(更简洁,但性能稍差)
        if (user1.HasFlag(Permission.Read))
        {
            Console.WriteLine("用户1可以读");
        }
    }
}

运行结果
用户1的权限:Read, Write
用户1有读权限吗?True
用户1有执行权限吗?False
用户1现在的权限:Read, Write, Execute
用户1去掉写权限后:Read, Execute
用户1可以读

//////////////////////////////////////////////////////////////////////////
总结:
|: 组合 Read | Write // 把两个权限合并
&: 检查 (user & Read) != 0 // 判断有没有某个权限
|: 添加 user | = Execute 等价于 user = user | Execute // 在原基础上加权限
& ~:移除 user & ~Write // 在原基础上减权限

posted @ 2026-06-06 16:41  apssic  阅读(9)  评论(0)    收藏  举报