简述C#枚举高级战术_C#教程

来源:脚本之家  责任编辑:小易  

说白了,就是让你以后维护或查看程序时候,知道这段代码是干什么用的包括以后就业,企业有注释规范,比如,一段程序百分之10-30都是注释,便于其他人员查看。还有很多规范,命名规范等等,第1点,有利于解释程序,第2点加强了代码的可读性,第3点方便程序员之间的交流讨论,本回答被网友采纳,注释就是为了解释程序的作用,加强代码的可读性本回答被网友采纳www.zgxue.com防采集请勿采集本网。

文章开头先给大家出一道面试题:

1、C程序主要由函数构成,C程序中有三种类型的函数: main():主函数,开发系统提供的特殊函数,每一个C程序必须且只有一个main()函数。它代表程序开始执行的起始位置。 开发系统提供的函数,如printf()、scanf()等。Turbo C开发系统提供三百多个

在设计某小型项目的数据库(假设用的是 MySQL)时,如果给用户表(User)添加一个字段(Roles)用来存储用户的角色,你会给这个字段设置什么类型?提示:要考虑到角色在后端开发时需要用枚举表示,且一个用户可能会拥有多个角色。

1,C / S也称为客户端/服务器或客户端/服务器模式。服务器通常使用高性能PC,工作站或小型计算机,并使用大型数据库系统,如Oracle,Sybase,Informix或SQL Server。客户端需要安装专用的客户端软件。 B / S是Brower / Server的缩写。客户端只需

映入你脑海的第一个答案可能是:varchar 类型,用分隔符的方式来存储多个角色,比如用 1|2|3 或 1,2,3 来表示用户拥有多个角色。当然如果角色数量可能超过个位数,考虑到数据库的查询方便(比如用 INSTR 或 POSITION 来判断用户是否包含某个角色),角色的值至少要从数字 10 开始。方案是可行的,可是不是太简单了,有没有更好的方案?更好的回答应是整型(int、bigint 等),优点是写 SQL 查询条件更方便,性能、空间上都优于 varchar。但整型毕竟只是一个数字,怎么表示多个角色呢?此时想到了二进制位操作的你,心中应该早有了答案。且保留你心中的答案,接着看完本文,或许你会有意外的收获,因为实际应用中可能还会遇到一连串的问题。为了更好的说明后面的问题,我们先来回顾一下枚举的基础知识。

高密度脂蛋白胆固醇(HDL-C):高密度脂蛋白胆固醇可通俗地理解为"好"胆固醇,因为HDL-C可减少患冠状动脉心脏病的危险。 增高:一般认为无临床意义,可见于原发性高HDL血症(家族性高α-脂蛋白血症),并发现此群家族中长寿者多。接受雌激素胰岛素

枚举基础

枚举类型的作用是限制其变量只能从有限的选项中取值,这些选项(枚举类型的成员)各自对应于一个数字,数字默认从 0 开始,并以此递增。例如:

顺序结构:顺序结构的程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行。 选择结构:选择程序结构用于判断给定的条件,根据判断的结果判断某些条件,根据判断的结果来控制程序的流程。使用选择

public enum Days{ Sunday, Monday, Tuesday, // ...}

1) 语言简洁,使用方便灵活 C语言是现有程序设计语言中规模最小的语言之一。C语言的关键字很少,ANSI C标准一共只有32个关键字,9种控制语句。C语言的书写形式比较自由,表达方法简洁,使用一些简单的方法就可以构造出相当复杂的数据类型和程序

其中 Sunday 的值是 0,Monday 是 1,以此类推。为了一眼能看出每个成员代表的值,一般推荐显示地将成员值写出来,不要省略:

public enum Days{ Sunday = 0, Monday = 1, Tuesday = 2, // ...}

C# 枚举成员的类型默认是 int 类型,通过继承可以声明枚举成员为其它类型,比如:

public enum Days : byte{ Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7}

枚举类型一定是继承自 byte、sbyte、short、ushort、int、uint、long 和 ulong 中的一种,不能是其它类型。下面是几个枚举的常见用法(以上面的 Days 枚举为例):

// 枚举转字符串string foo = Days.Saturday.ToString(); // "Saturday"string foo = Enum.GetName(typeof(Days), 6); // "Saturday"// 字符串转枚举Enum.TryParse("Tuesday", out Days bar); // true, bar = Days.Tuesday(Days)Enum.Parse(typeof(Days), "Tuesday"); // Days.Tuesday// 枚举转数字byte foo = (byte)Days.Monday; // 1// 数字转枚举Days foo = (Days)2; // Days.Tuesday// 获取枚举所属的数字类型Type foo = Enum.GetUnderlyingType(typeof(Days))); // System.Byte// 获取所有的枚举成员Array foo = Enum.GetValues(typeof(MyEnum);// 获取所有枚举成员的字段名string[] foo = Enum.GetNames(typeof(Days));

另外,值得注意的是,枚举可能会得到非预期的值(值没有对应的成员)。比如:

Days d = (Days)21; // 不会报错Enum.IsDefined(typeof(Days), d); // false

即使枚举没有值为 0 的成员,它的默认值永远都是 0。

var z = default(Days); // 0

枚举可以通过 Description、Display 等特性来为成员添加有用的辅助信息,比如:

public enum ApiStatus{ [Description("成功")] OK = 0, [Description("资源未找到")] NotFound = 2, [Description("拒绝访问")] AccessDenied = 3}static class EnumExtensions{ public static string GetDescription(this Enum val) { var field = val.GetType().GetField(val.ToString()); var customAttribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)); if (customAttribute == null) { return val.ToString(); } else { return ((DescriptionAttribute)customAttribute).Description; } }}static void Main(string[] args){ Console.WriteLine(ApiStatus.Ok.GetDescription()); // "成功"}

上面这些我认为已经包含了大部分我们日常用到的枚举知识了。下面我们继续回到文章开头说的用户角色存储问题。

用户角色存储问题

我们先定义一个枚举类型来表示两种用户角色:

public enum Roles{ Admin = 1, Member = 2}

这样,如果某个用户同时拥有 Admin 和 Member 两种角色,那么 User 表的 Roles 字段就应该存 3。那问题来了,此时若查询所有拥有 Admin 角色的用户的 SQL 该怎么写呢?对于有基础的程序员来说,这个问题很简单,只要用位操作符逻辑与(‘&')来查询即可。

SELECT * FROM `User` WHERE `Roles` & 1 = 1;

同理,查询同时拥有这两种角色的用户,SQL 语句应该这么写:

SELECT * FROM `User` WHERE `Roles` & 3 = 3;

对这条 SQL 语句用 C# 来实现查询是这样的(为了简单,这里使用了 Dapper):

public class User{ public int Id { get; set; } public Roles Roles { get; set; }}connection.Query<User>( "SELECT * FROM `User` WHERE `Roles` & @roles = @roles;", new { roles = Roles.Admin | Roles.Member });

对应的,在 C# 中要判断用户是否拥有某个角色,可以这么判断:

// 方式一if ((user.Roles & Roles.Admin) == Roles.Admin){ // 做管理员可以做的事情}// 方式二if (user.Roles.HasFlag(Roles.Admin)){ // 做管理员可以做的事情}

同理,在 C# 中你可以对枚举进行任意位逻辑运算,比如要把角色从某个枚举变量中移除:

var foo = Roles.Admin | Roles.Member;var bar = foo & ~Roles.Admin;

这就解决了文章前面提到的用整型来存储多角色的问题,不论数据库还是 C# 语言,操作上都是可行的,而且也很方便灵活。

枚举的 Flags 特性

下面我们提供一个通过角色来查询用户的方法,并演示如何调用,如下:

public IEnumerable<User> GetUsersInRoles(Roles roles){ _logger.LogDebug(roles.ToString()); _connection.Query<User>( "SELECT * FROM `User` WHERE `Roles` & @roles = @roles;", new { roles });}// 调用_repository.GetUsersInRoles(Roles.Admin | Roles.Member);

Roles.Admin | Roles.Member 的值是 3,由于 Roles 枚举类型中并没有定义一个值为 3 的字段,所以在方法内 roles 参数显示的是 3。3 这个信息对于我们调试或打印日志很不友好。在方法内,我们并不知道这个 3 代表的是什么。为了解决这个问题,C# 枚举有个很有用的特性:FlagsAtrribute。

[Flags]public enum Roles{ Admin = 1, Member = 2}

加上这个 Flags 特性后,我们再来调试 GetUsersInRoles(Roles roles) 方法时,roles 参数的值就会显示为 Admin|Member 了。简单来说,加不加 Flags 的区别是:

var roles = Roles.Admin | Roles.Member;Console.WriteLing(roles.ToString()); // "3",没有 Flags 特性Console.WriteLing(roles.ToString()); // "Admin, Member",有 Flags 特性

给枚举加上 Flags 特性,我觉得应当视为 C# 编程的一种最佳实践,在定义枚举时尽量加上 Flags 特性。

解决枚举值冲突:2 的幂

到这,枚举类型 Roles 一切看上去没什么问题,但如果现在要增加一个角色:Mananger,会发生什么情况?按照数字值递增的规则,Manager 的值应当设为 3。

[Flags]public enum Roles{ Admin = 1, Member = 2, Manager = 3}

能不能把 Manager 的值设为 3?显然不能,因为 Admin 和 Member 进行位的或逻辑运算(即:Admin | Member) 的值也是 3,表示同时拥有这两种角色,这和 Manager 冲突了。那怎样设值才能避免冲突呢?既然是二进制逻辑运算“或”会和成员值产生冲突,那就利用逻辑运算或的规律来解决。我们知道“或”运算的逻辑是两边只要出现一个 1 结果就会 1,比如 1|1、1|0 结果都是 1,只有 0|0 的情况结果才是 0。那么我们就要避免任意两个值在相同的位置上出现 1。根据二进制满 2 进 1 的特点,只要保证枚举的各项值都是 2 的幂即可。比如:

1:  00000001

2:  00000010

4:  00000100

8:  00001000

再往后增加的话就是 16、32、64..,其中各值不论怎么相加都不会和成员的任一值冲突。这样问题就解决了,所以我们要这样定义 Roles 枚举的值:

[Flags]public enum Roles{ Admin = 1, Member = 2, Manager = 4, Operator = 8}

不过在定义值的时候要在心中小小计算一下,如果你想懒一点,可以用下面这种“位移”的方法来定义:

[Flags]public enum Roles{ Admin = 1 << 0, Member = 1 << 1, Manager = 1 << 2, Operator = 1 << 3}

一直往下递增编值即可,阅读体验好,也不容易编错。两种方式是等效的,常量位移的计算是在编译的时候进行的,所以相比不会有额外的开销。

总结

本文通过一道小小的面试题引发一连串对枚举的思考。在小型系统中,把用户角色直接存储在用户表是很常见的做法,此时把角色字段设为整型(比如 int)是比较好的设计方案。但与此同时,也要考虑到一些最佳实践,比如使用 Flags 特性来帮助更好的调试和日志输出。也要考虑到实际开发中的各种潜在问题,比如多个枚举值进行或(‘|')运算与成员值发生冲突的问题。

到此这篇关于简述C#枚举高级战术的文章就介绍到这了,更多相关C# 枚举内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网! 您可能感兴趣的文章:C# 遍历枚举类型的所有元素C# 获取枚举值的简单实例深入理解C#中的枚举深入解析c#中枚举类型的定义与使用C#枚举数值与名称的转换实例分享C#实现获取枚举中元素个数的方法C#中可枚举类型详解C#枚举中的位运算权限分配浅谈C#编程中枚举类型的使用教程

C语言是国际上广泛流行的、很有发展前途的计算机高级语言。它适合作为系统描述语言,即可用来编写系e5a48de588b63231313335323631343130323136353331333332643265统软件,也可用来编写应用软件。 早期的操作系统等系统软件主要是用汇编语言编写的(包括 UNIX操作系统在内)。由于汇编语言依赖于计算机硬件,程序的可读性和可移植性都比较差。为了提高可读性和可移植性,最好改用高级语言,但一般的高级语言难以实现汇编语言的某些功能(汇编语言可以直接对硬件进行操作),例如:对内存地址的操作、位操作等)。人们设想能否找到一种既具有一般高级语言特性,又具有低级语言特性的语言,集它们的优点于一身。于是,C语言就在这种情况下应运而生了。 C语言是在B语言的基础上发展起来的,它的根源可以追溯到ALGOL 60。 1960年出现的ALGOL 60是一种面向问题的高级语言,它离硬件比较远,不宜用来编写系统程序。1963年英国的剑桥大学推出了CPL(CombinedProgram- ming Language)语言。CPL语言在ALGOL 60的基础上接近了硬件一些,但规模比较大,难以实现。1967年英国剑桥大学的Matin Richards对 CPL语言作了简化,推出了BCPL(Basic Combined Programming Language)语言。1970年美国贝尔实验室的 Ken Thompson以 BCPL语言为基础,又作了进一步简化,设计出了很简单的而且很接近硬件的 B语言( 取 BCPL的第一个字母),并用 B语言写第一个UNIX操作系统,在PDP-7上实现。 1971年在PDP-11/20上实现了B语言,并写了UNIX操作系统。但B语言过于简单,功能有限。1972年至 1973年间,贝尔实验室的 D.M.Ritchie在B语言的基础上设计出了C语言(取 BCPL的第二个字母)。C语言既保持了BCPL和B语言的优点(精练、接近硬件),又克服了它们的缺点(过于简单、数据无类型等)。 最初的C语言只是为描述和实现UNIX操作系统提供一种工作语言而设计的。1973年,K.Thom- pson和D.M.ritchie两人合作把UNIX的90%以上用 C改写(UNIX第5版。原来的 UNIX操作系统是1969年由美国的贝尔实验室的 K.Thompson和D.M.Ritchie开发成功的,是用汇编语言写的)。 后来,C语言多次作了改进,但主要还是在贝尔实验室内部使用。直到1- 975年UNIX第6版公布后 ,C语言的突出优点才引起人们普遍注意。1977年出现了不依赖于具体机器的C语言编译文本《可移植C语言编译程序》,使C移植到其它机器时所做的工作大大简化了,这也推动了UNIX操作系统迅速地在各种机器上实现。例如,VAX,AT&T等计算机系统都相继开发了UNIX。随着 UNIX的日益广泛使用,C语言也迅速得到推广。C语言和UNIX可以说是一对孪生兄弟,在发展过程中相辅相成。1978年以后,C语言已先后移植到大、中、小、微型机上,已独立于UNIX和PDP了。现在C语言已风靡全世界,成为世界上应用最广泛的几种计算机语言之一。 以1978年发表的UNIX第7版中的C编译程序为基础,Brian W.Kernighan和 Dennis M.Ritchie(合称K&R)合著了影响深远了名著《The C Programming Lan- guage》,这本书中介绍的C语言成为后来广泛使用的C语言版本的基础,它被称为标准C。1983年,美国国家标准化协会(ANSI)根据C语言问世以来各种版本对C的发展和扩充 ,制定了新的标准,称为ANSI C。ANSI C比原来的标准C有了很大的发展。K&R在1988年修改了他们的经典著作《The C Progra- mming Language》 ,按照ANSI C的标准重新写了该书。1987年,ANSI C又公布了新标准--87 ANSI C 。目前流行的C编译系统都是以它为基础的,C语言的原型ALGOL 60语言。(也称为e69da5e887aa62616964757a686964616f31333332643265A语言)1963年,剑桥大学将ALGOL 60语言发展成为CPL(Combined Programming Language)语言。1967年,剑桥大学的Matin Richards 对CPL语言进行了简化,于是产生了BCPL语言。1970年,美国贝尔实验室的Ken Thompson将BCPL进行了修改,并为它起了一个有趣的名字“B语言”。意思是将CPL语言煮干,提炼出它的精华。并且他用B语言写了第一个UNIX操作系统。而在1973年,B语言也给人“煮”了一下,美国贝尔实验室的D.M.RITCHIE在B语言的基础上最终设计出了一种新的语言,他取了BCPL的第二个字母作为这种语言的名字,这就是C语言。为了使UNIX操作系统推广,1977年Dennis M.Ritchie 发表了不依赖于具体机器系统的C语言编译文本《可移植的C语言编译程序》。即是著名的ANSI C。1978年Brian W.Kernighian和Dennis M.Ritchie出版了名著《C语言程序》(The C Programming Language),从而使C语言成为当时世界上流行最广泛的高级程序设计语言。1988年,随着微型计算机的日益普及, C语言出现了许多版本。由于没有统一的标准,使得这些C语言之间出现了一些不一致的地方。为了改变这种情况,美国国家标准研究所(ANSI)为C语言制定了一套ANSI标准, 成为现行的C语言标准3.C语言的主要特点 。C语言发展迅速, 而且成为最受欢迎的语言之一, 主要因为它具有强大的功能。许多著名的系统软件, 如DBASE Ⅲ PLUS、DBASE Ⅳ 都是由C 语言编写的。用C语言加上一些汇编语言子程序, 就更能显示C语言的优势了,象PC- DOS 、WORDSTAR等就是用这种方法编写的内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • 使用vs2005自带的混淆器防止你的程序被反编译的方法
  • c#抽象类与抽象方法详解
  • c# out关键词的应用实例
  • c# 3des加密详解
  • c#泛型概念的简介与泛型的使用
  • c#将hashtable中键列表或值列表复制到一维数组的方法
  • qt程序中调用c#编写的dll(推荐)
  • c#实现窗体与子线程的交互的方法
  • c#图像处理之木刻效果实现方法
  • unity shader实现高斯模糊效果
  • 简述C语言的发展
  • 请简述c语言注释的作用
  • 简述c程序的基本组成结构。
  • 简述c语言中数组特点
  • 简述C源程序的结构及其书写规则
  • 简述C/S和B/S模式的区别
  • 简述检测HDL-C的临床意义
  • 简述c语言中的三种基本控制结构,循环结构。
  • 简述题:c语言的特点
  • 简述c语言的运行过程
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全c#教程vbvb.netc 语言java编程delphijavaandroidiosswiftscala易语言汇编语言其它相关首页c# 遍历枚举类型的所有元素c# 获取枚举值的简单实例深入理解c#中的枚举深入解析c#中枚举类型的定义与使用c#枚举数值与名称的转换实例分享c#实现获取枚举中元素个数的方法c#中可枚举类型详解c#枚举中的位运算权限分配浅谈c#编程中枚举类型的使用教程使用vs2005自带的混淆器防止你的程序被反编译的方法c#抽象类与抽象方法详解c# out关键词的应用实例c# 3des加密详解c#泛型概念的简介与泛型的使用c#将hashtable中键列表或值列表复制到一维数组的方法qt程序中调用c#编写的dll(推荐)c#实现窗体与子线程的交互的方法c#图像处理之木刻效果实现方法unity shader实现高斯模糊效果c#几种截取字符串的方法小结c#中httpwebrequest的用法详解c# datagridview添加新行的2个方c#中list〈string〉和string[]数c# 一个wcf简单实例c#连接mysql数据库的方法c#的dllimport使用方法详解c#中使用split分割字符串的几种方c#处理3种json数据的实例c#实现16进制和字符串之间转换的c#生成条形码图片的简单方法理解c#编程中的静态类和静态成员以及密封c# winform程序处理后台繁忙导致前台控件c#简单访问sqlite数据库的方法(安装,连接c# 动态加载dll文件,并实现调用其中的方法c#利用正则判断输入是否为纯数字、容器类c# json格式化转换辅助类 convertjson基于c#实现一个最简单的http服务器实例c#获取所有sql server数据库名称的方法wpf自定义menuitem样式的实现方法
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved