原创C# 枚举 多状态 操作
C# 中枚举类型是一种值类型,目前(vs2012)还不能用于泛型。
状态量
示例一
[Flags] public enum ConnectionState { Closed = 0, Open = 1, Connecting = 2, Executing = 4, Fetching = 8, Broken = 16, }
常量
示例二
[Flags] [ComVisible(true)] [Serializable] public enum FileAttributes { ReadOnly = 1, Hidden = 2, System = 4, Directory = 16, Archive = 32, Device = 64, Normal = 128, Temporary = 256, SparseFile = 512, ReparsePoint = 1024, Compressed = 2048, Offline = 4096, NotContentIndexed = 8192, Encrypted = 16384, [ComVisible(false)] IntegrityStream = 32768, [ComVisible(false)] NoScrubData = 131072, }
在使用中,平时使用频率最多的是:使用switch case 语句来判断枚举中的一个值,比如:
示例三
enum ActionStep { /// <summary> /// 第一步:打开主页 /// </summary> Home, /// <summary> /// 第二步:查找输入框与提交按钮,输入关键字后提交 /// </summary> FindAndQuery, /// <summary> /// 第三步:查找指定连接,找到后导航到它 /// </summary> Search, /// <summary> /// 第四步:等待15秒后关闭 /// </summary> WaittingForClose, End }
switch (action.Step) { case ActionStep.Home: Navigate(task.Home); break; case ActionStep.FindAndQuery: InputAndSubmit(task); break; case ActionStep.Search: SearchTarget(task); break; case ActionStep.WaittingForClose: WaitForClose(task); break; }
然而,我们有时候也需要多状态的情况,比如:文件属性 FileAttributes。
那么,如何来操作呢?
正常的思路是声明一个变量,在需要的时候进行 与 或 非 操作。(不是还有hasFlag嘛?......),比如:C# Enum设计和使用的相关技巧 中的示例
示例四
例如定义了权限Enum Permission: [Flags] public enum Permission{ Select = 1, Edit = 2, Delete = 4, View = 8, All = Select | Edit | Delete | View } 可以采用这个函数进行计算: public static Permission ClearFlag(Permission value, Permission flag) { value = value & (Permission.All^ flag); return value; }
使用起来应该很方便,但是如果遇到,像下面的情况
示例五
[Flags] public enum AuthorState { BlogListDownloading = 1, BlogListParsing = 2, BlogDownloading = 4, BlogParsing = 8, BlogWritting = 16, MetaDownloading = 32, MetaParsing = 64, MetaWritting = 128, MetasParsedDone = 2048,//所的的元素解析全部完成 DownloadList = 256, CheckUpdate = 512, NeedUpdate = 1024//需要更新 }
/// <summary> /// 状态辅助类 /// </summary> public class EnumHelper { private AuthorState _state; /// <summary> /// 添加一个状态 /// </summary> /// <param name="state"></param> public void In(AuthorState state) { if (!Include(state)) _state |= state; } /// <summary> /// 删除一个状态 /// </summary> /// <param name="state"></param> public void Out(AuthorState state) { if(!Include(state)) _state ^= state; //_state ^= state; } /// <summary> /// 判断一个状态是否在其中 /// </summary> /// <param name="state"></param> /// <returns></returns> public bool Include(AuthorState state) { return (_state & state) == state; } }
State.In(AuthorState.DownloadList); _download.DownloadBlogList(url); State.Out(AuthorState.DownloadList);
即,添加了一个状态,在之后的操作中会去除这个状态。
然而,我在写出了示例五之后总感觉这样做代码量增加太多了,虽然有智能提示。很是怀想delphi下的 In 操作:
示例六
procedure TForm1.Edit1KeyPress(Sender: TObject; var..Key: Char); begin if not(key in['0'..'9',#8])then begin key:=#0; MessageBeep(1); //Beep; 调用系统声音也行! end; end;
C#中的In是不会让你这么用的,那么,要怎么办?扩展!扩展枚举,增加一些方法
google了一下,找到了 如何:为枚举创建新方法(C# 编程指南)
下面是我修改之后的代码
示例七
[Flags] public enum MyEnum { Zero =1 , One = 2, Two = 4, Three =8 }
扩展
public static class Extensions { public static MyEnum Host = MyEnum.One; public static bool Contained(this MyEnum value) { return (Host & value) == value; } public static void Add(this MyEnum value) { if (value.Contained()) return; Host |= value; } public static void Remove(this MyEnum value) { if (value.Contained()) Host ^= value; } }
使用方法
public class TestCls { private MyEnum _initValue = MyEnum.One; public void Test(MyEnum value) { Extensions.Host = _initValue;//控制变量 value.Contained(); value.Add(); value.Remove(); } }
那么,好吧,你现在会用了。
示例八
MyEnum.One.Add(); MyEnum.One.Remove();