日期:2014-05-20  浏览次数:20962 次

再谈enum-=运算[抛砖引玉]
问题出发点http://topic.csdn.net/u/20100404/11/fa54404c-1510-4027-a799-1bc420c53444.html?14163
原文:
C# code
    enum TU
    {
        A=0x01,
        B=0x04,
        C=0x05,
        D=0x15,
        E=0x0
    }

TU t=TU.D;
t-=TU.A;//这是对的
t+=TU.A//错误
t=t+TU.A//错误
t=t-TU.A//错误


-----------------------------------------
1.-=在枚举中的意义
二元 - 运算符是为所有数值类型和枚举类型预定义的,其功能是从第一个操作数中减去第二个操作数。
猜想:从整体上来看在此处t -= TU.A的应该是移除效果.
为什么会猜想是移除,原因要从enum的[FlagsAttribute]说起.
enum按位运算很常用,例如: FileAttributes.ReadOnly | FileAttributes.Hidden;
说到enum的按位运算,当定义的enum元素用 2 的幂(即 1、2、4、8 等)定义枚举常量。这意味着组合的枚举常量中的各个标志都不重叠.在使用ToString()时,才能枚举出所有的元素值.有以下例子:
C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            TU t =  TU.One| TU.Two | TU.Four;
            Console.WriteLine(((Int32)t).ToString());
            Console.WriteLine(t.ToString());
            t -= TU.One;//从t中移除TU.One
            Console.WriteLine(((Int32)t).ToString());
            Console.WriteLine(t.ToString());
        }
    }
    [FlagsAttribute]
    enum TU
    {
        One = 1,
        Two = 2,
        Four = 4,
        Eight = 8,
        Sixteen =16
    }
}


运行结果

7
One,Two,Four
6
Two,Four


2.为什么不提供+=
a.从意义上来说+=和|=的作用相当.所以不必提供该操作.
b.实际上个人觉得+=(|=)比-=更容易产生不可预知的问题.例如FileAttributes.Normal和 FileAttributes.Hidden;FileAttributes.Normal标识文件未设置任何属性,FileAttributes.Hidden则是标识文件是隐藏的,两者相异.这其中有一些微妙的地方,下文将说到.

3.enum的微妙之处
以下引自MSDN中<<对FlagsAttribute 和 Enum 的准则>>的第二条.
用 2 的幂(即 1、2、4、8 等)定义枚举常量。这意味着组合的枚举常量中的各个标志都不重叠。
enum在实际应用中会有类似FileAttributes.Normal的情况.例如存在一个自定义的文件操作枚举FileOperations,假设该枚举存在一个值None ,该值是用于标识未指定其他值的情况.
该enum如下.
C# code

        [FlagsAttribute]
        enum FileOperations
        {
            Read = 1,
            Write = 2,
            Delete = 4,
            Hidden = 8,
            None = 16
        }


然后进行以下实验
C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            FileOperations f = FileOperations.Delete | FileOperations.Read;
            Console.WriteLine("原始的值\r\n" + f.ToString());
            f -= FileOperations.Delete;
            Console.WriteLine("移除Delete后的值\r\n"+f.ToString());
            f -= FileOperations.Read;
            Console.WriteLine("移除Read后的值\r\n" + f.ToString());
        }

        [FlagsAttribute]
        enum FileOperations
        {
            Read = 1,
            Write = 2,
            Delete = 4,
            Hidden = 8,
            None = 16,
        }
    }
}


运行结果:

原始的值
Read,Delete
移除Delete后的值
Read
移除Read后的值
0
请按任意键继续. . .

这里我们可以看到,FileOperations f = FileOperations.Delete | FileOperations.Read依次移除后,状态应该是前面提到的该值是用于标识未指定其他值的情况.,即None,但实际上f并没得到我们想要的值.
然后我们将代码加经改进
C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            FileOperations f = FileOperations.Delete | FileOperations.Read;
            Console.WriteLine("原始的值\r\n" + f.ToString());
            f -= FileOperations.Delete;
            Console.WriteLine("移除Delete后的值\r\n"+f.ToString());
            f -= FileOperations.Read;
            Console.WriteLine("移除Read后的值\r\n" + f.ToString());
        }

        [FlagsAttribute]
        enum FileOperations
        {
            Read = 1,
            Write = 2,
            Delete = 4,
            Hidden = 8,
            None = 0,//这里是主要变化
        }
    }
}