再谈enum-=运算[抛砖引玉]
问题出发点http://topic.csdn.net/u/20100404/11/fa54404c-1510-4027-a799-1bc420c53444.html?14163
原文:
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//错误
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 }}
[FlagsAttribute] enum FileOperations { Read = 1, Write = 2, Delete = 4, Hidden = 8, None = 16 }
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, } }}
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,//这里是主要变化 } }}
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 | FileOperations.Write | FileOperations.Hidden; 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()); f -= FileOperations.Write; Console.WriteLine("移除Write后的值\r\n" + f.ToString()); f -= FileOperations.Hidden; Console.WriteLine("移除Hidden后的值\r\n" + f.ToString()); } [FlagsAttribute] enum FileOperations { None = 0, Read = 1, Write = 2, Delete = 4, Hidden = 8, All = 15//此处是关键 } }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { FileOperations f = FileOperations.Hidden; Console.WriteLine("原始的值\r\n" + f.ToString()); f -= FileOperations.Delete; Console.WriteLine("移除Delete后的值\r\n"+f.ToString()); } [FlagsAttribute] enum FileOperations { None = 0, Read = 1, Write = 2, Delete = 4, Hidden = 8, All = 15 } }}
enum TU { A,B,C,D,E }TU t = TU.D;t -= TU.A; // 按我的理解,这应该是等价于 t = (TU)(t - TU.A);
[解决办法]
enum TU { A,B,C,D,E }TU t = TU.D;t -= TU.A; // 可以t = (TU)(t - TU.A); // 可以,等价于上行t = t - TU.A; // 错误// 类比:byte b = 78;b -= 5; // 可以b = (byte)(b - 5); // 可以,等价于上行b = b - 5; // 错误
[解决办法]
两个 Enum 类型的变量相减的结果为 int,这点和 byte 类型的变量相减类似。
但两个 Enum 类型的变量不能相加,这和 byte 类型是不同的。
两个枚举变量相减的意思就是它们之间相隔多远,结果是 int。
两个枚举变量相加就没有明显的、自然的意义了,所以不允许。
正如两个 DateTime 型的变量相减的意思是时间间隔,结果是 TimeSpan 型的变量,
而两个 DateTime 型的变量相加没有意义,不允许。
------解决方案--------------------
要除去一个值,应该取反再与,哪能直接减啊……
[解决办法]
using System;[Flags]enum FileOperations{ Delete = 4, Hidden = 8,}class Program{ static void Main() { FileOperations a, b = FileOperations.Delete; // 想从 a 中移除 b,正确的做法如下: a = FileOperations.Hidden; a &= ~b; // 不论 a 是否含有 b,都可以得到正确的结果 Console.WriteLine(a); // 输出 Hideden,正确。 // 想从 a 中移除 b,不正确的做法如下: a = FileOperations.Hidden; a -= b; // 如果 a 不含有 b,就不能得到正确的结果 Console.WriteLine(a); // 输出 Delete,错误。 // 想从 a 中移除 b,另一种做法: a = FileOperations.Hidden; if (( a & b) == b) a -= b; // 先判断 a 是否含有 b,再相减,可以。 Console.WriteLine(a); // 输出 Hideden,正确。 }}
[解决办法]
如果枚举量 a 只含有部分的 b,从 a 移除 b 正确而简单的做法仍然是:a &= ~b;
a -= b; 就没有办法做到从 a 移除 b 了,无论是是否判断 a 含有 b。
using System;[Flags]enum FileOperations{ Read = 1, Write = 2, Delete = 4, Hidden = 8,}class Program{ static void Main() { FileOperations a, b = FileOperations.Delete | FileOperations.Read; // 想从 a 中移除 b,正确的做法如下: a = FileOperations.Hidden | FileOperations.Delete; a &= ~b; // 不论 a 是否部分含有 b,都正确。 Console.WriteLine(a); // 输出 Hideden,正确。 // 想从 a 中移除 b,不正确的做法如下: a = FileOperations.Hidden | FileOperations.Delete; a -= b; // 如果 a 含有部分的 b,结果不知所云。 Console.WriteLine(a); // 输出 Read, Write, Delete,错误。 // 想从 a 中移除 b,另一种做法(错误): a = FileOperations.Hidden | FileOperations.Delete; if (( a & b) == b) a -= b; // 先判断 a 是否完全含有 b,再相减。 Console.WriteLine(a); // 输出 Delete, Hidden,错误。 // 想从 a 中移除 b,还一种做法(也不正确): a = FileOperations.Hidden | FileOperations.Delete; if (( a & b) != 0) a -= b; // 先判断 a 是否部分含有 b,再相减。 Console.WriteLine(a); // 输出 Read, Write, Delete,也不正确。 }}
[解决办法]
总结:两个枚举量相减的结果是 int,意义是它们的间隔,
再转换为枚举没有什么实际意义,只是在某些特定的情况下表现为移除的效果。
所以 a -= b; 是不好的写法,因为把枚举量的间隔转换为枚举在很多情况下没意义。
移除的正确而简单的写法是:a &= ~b;
[解决办法]
两个枚举量相减的结果是有意义的,就是它们的间隔(结果是 int 型的,而不是枚举型的)。
如果 a 和 b 是两个相同类型的枚举量,则表达式 a - b 是有意义的,如上所述。
但 a -= b; 只不过是 a = (a的类型)(a - b); 的简便写法而已,把一个 int 型的量(枚举量的间隔)转换为枚举量,在很多情况下没意义。
[解决办法]
枚举量的 a -= b; 在语法上是正确的,但在语义上不正确,是不好的写法。
[解决办法]
a &= ~b;
这个去除功能不错
[解决办法]
在使用FlagAttribute标记的枚举时不建议使用+和-,建议使用 | 和 ^