C#enum枚举解析(含IL解析)(二)
default默认值:
当值是类的字段时,它们总是被初始化为0。创建类时,枚举字段也将被初始化为零(以及等效的值)。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumDefaultDemo 9 { 10 enum CatFurColor 11 { 12 None, 13 Orange, 14 Grey 15 } 16 17 class Program 18 { 19 static CatFurColor _color; 20 21 static void Main(string[] args) 22 { 23 Console.WriteLine("Default Enum Value is {0}",_color); 24 } 25 } 26 }
若要使枚举有效,请始终使用默认值零。这样,我们可以测试字段的默认值。这个问题不值得修复。但是它通常对验证正确性很有用。你可以在枚举块的末尾放置一个分号(但这通常不是必需的或没有帮助的)
collections集合:
在这里,我们应用.NET中的Stack集合。使用Stack,我们可以开发一个解析器,将最近遇到的枚举值放在顶部。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumCollectionsDemo 9 { 10 class Program 11 { 12 enum TagType 13 { 14 None, 15 BoldTag, 16 ItalicsTag, 17 HyperlinkTag 18 } 19 20 static void Main(string[] args) 21 { 22 //Create a Stack of enums 23 var stack = new Stack<TagType>(); 24 25 //...Add enum values to our stack 26 stack.Push(TagType.BoldTag); //Add bold 27 stack.Push(TagType.ItalicsTag); //Add italics 28 29 //...Get the top enum value 30 TagType thisTag = stack.Pop(); //Get top tag. 31 Console.WriteLine("Pop Result:" + thisTag); 32 33 //peek at the top. 34 var peeked = stack.Peek(); 35 Console.WriteLine("Peek Result:" + peeked); 36 } 37 } 38 }
在这里,只有TagType类型的数值才能添加到Stack集合中。上面是类型检查和类型有效的示例。
使用Pop函数我们从stack集合中得到了顶部的元素。这就是TagType.ItalicsTag。
在这个程序的执行过程中,stack增加了两个枚举,删除了一个。
Type类型:
枚举有一个基础类型。每次使用枚举时,我们都在使用基础类型。枚举在顶部有语法糖。
int 枚举默认的是一个int类型,但是我们可以将其调整为不同的数值类型。
Byte 这里我们创建一个byte类型的枚举。有时候在小的枚举上面很有用。一个byte仅包含256种数值。
1 using System; 2 3 class Program 4 { 5 enum CoffeeSize : byte 6 { 7 None, 8 Tall, 9 Venti, 10 Grande 11 }; 12 13 static void Main() 14 { 15 // ... Create a coffee size local. 16 CoffeeSize size = CoffeeSize.Venti; 17 Console.WriteLine(size); 18 } 19 } 20 Venti
CoffeeSize枚举将使用相当于一个字节的内存。这样可以让类更有效率,更小。
GetUnderlyingType:
在运行时中我们能决定一个枚举的类型(比如int)。Enum.GetUnderlyingType,是一个静态函数,它决定基础类型。
Next 我们声明一个枚举Importance。对于这个示例它使用了一个byte的基础类型。
Then 当GetUnderlying函数被调用的时候,就会返回Syetem.Byte类型。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumGetUnderlyingTypeDemo 9 { 10 class Program 11 { 12 enum Importance : byte 13 { 14 Low, 15 Medium, 16 High 17 } 18 19 static void Main(string[] args) 20 { 21 //Determine the underlying type of the enum 22 Type type = 23 Enum.GetUnderlyingType(typeof(Importance)); 24 Console.WriteLine(type); 25 } 26 } 27 }
Null,none:
枚举值不能是null。它是一个类似int的值类型。为避免“cannot convert null”错误信息,使用一个特殊的None常量做为第一个枚举项。
1 enum Color 2 { 3 None, 4 Blue, 5 Red 6 } 7 8 class Program 9 { 10 static void Main() 11 { 12 Color c = null; 13 } 14 } 15 Error CS0037 16 Cannot convert null to 'Color' because it is a non-nullable value type 17 enum Color 18 { 19 None, 20 Blue, 21 Red 22 } 23 24 class Program 25 { 26 static void Main() 27 { 28 Color c = Color.None; 29 } 30 }
Flags:
C#语言允许我们在枚举上指定一个Flags特性。这使得枚举可以做为字段使用。我们可以这样使用枚举值的组合。
Here 我们有个枚举叫做DataInfo,它有四种不同的flag值。我们在Main()函数中设置他们中的两种。
And 在if语句中,我们发现OptionA和OptionC是设置为true,但是OptionB没有设置。这是正确的结果。
[Flags]表示该枚举可以支持C#位运算
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumNullDemo 9 { 10 class Program 11 { 12 [Flags] 13 enum DataInfo 14 { 15 None = 0, 16 OptionA = 1, 17 OptionB = 2, 18 OptionC = 4 19 } 20 21 static void Main(string[] args) 22 { 23 var info = DataInfo.OptionA|DataInfo.OptionC; 24 Console.WriteLine("info is :{0}",info); 25 26 27 //See if current flag is set. 28 if ((info & DataInfo.OptionA) == DataInfo.OptionA && 29 (info & DataInfo.OptionB) != DataInfo.OptionB && 30 (info & DataInfo.OptionC) == DataInfo.OptionC) 31 { 32 Console.WriteLine("Has OptionA,OptionC,but not OptionB."); 33 } 34 } 35 } 36 }
知识延伸:
基础知识
位操作符处理位并执行逐位运算。真值表如下所示
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
以上面的示例进行计算,OptionA = 1,OptionC = 4,它们的二进制格式如下
OptionA = 0001
OptionC = 0100
则OptionA|OptionC = 0101 (注:|操作符按位运算,只要有一方为true,那么运算结果就为true),将0101转换为十进制,其值为5;
var info = DataInfo.OptionA | DataInfo.OptionC;枚举会自动计算OptionA/OptionB/OptionC三者的值进行匹配,如果单个枚举值或几个枚举值的和等于5,则将这几个枚举赋给info。
测试程序一如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumNullDemo 9 { 10 class Program 11 { 12 [Flags] 13 enum DataInfo 14 { 15 None = 0, 16 OptionA = 1, 17 OptionB = 2, 18 OptionC = 4 19 } 20 21 static void Main(string[] args) 22 { 23 var info = DataInfo.OptionA | DataInfo.OptionC; 24 25 //测试 26 Console.WriteLine("info is :{0}", info); 27 Console.WriteLine("info value is {0}",(int)info); 28 Console.WriteLine("info type is {0}",info.GetType()); 29 30 31 //See if current flag is set. 32 if ((info & DataInfo.OptionA) == DataInfo.OptionA && 33 (info & DataInfo.OptionB) != DataInfo.OptionB && 34 (info & DataInfo.OptionC) == DataInfo.OptionC) 35 { 36 Console.WriteLine("Has OptionA,OptionC,but not OptionB."); 37 } 38 } 39 } 40 }
测试程序二如下:
我将各枚举值调整为OptionA = 3,OptionB = 4,OptionC = 5
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumNullDemo 9 { 10 class Program 11 { 12 [Flags] 13 enum DataInfo 14 { 15 None = 0, 16 OptionA = 3, 17 OptionB = 4, 18 OptionC = 5 19 } 20 21 static void Main(string[] args) 22 { 23 var info = DataInfo.OptionA | DataInfo.OptionC; 24 25 //测试 26 Console.WriteLine("info is :{0}", info); 27 Console.WriteLine("info value is {0}",(int)info); 28 Console.WriteLine("info type is {0}",info.GetType()); 29 30 31 //See if current flag is set. 32 if ((info & DataInfo.OptionA) == DataInfo.OptionA && 33 (info & DataInfo.OptionB) != DataInfo.OptionB && 34 (info & DataInfo.OptionC) == DataInfo.OptionC) 35 { 36 Console.WriteLine("Has OptionA,OptionC,but not OptionB."); 37 } 38 } 39 } 40 }
OptionA = 3,二进制为0011;optionB = 5 ,二进制为0101,则OptionA|OptionC = 0111,转换为十进制为7。
OptionA 和OptionB 的枚举值之和是7,系统应该显示为OptionA 和OptionB。但是实际显示出来的是数字7;
具体原因待知识积累后再进行探讨!
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Windows.Forms; 7 8 namespace EnumNullDemo 9 { 10 class Program 11 { 12 [Flags] 13 enum DataInfo 14 { 15 None = 0, 16 a = 1, 17 b = 2, 18 OptionA = 3, 19 OptionB = 4, 20 OptionC = 5 21 } 22 23 static void Main(string[] args) 24 { 25 var info = DataInfo.OptionA | DataInfo.OptionC; 26 27 //测试 28 Console.WriteLine("info is :{0}", info); 29 Console.WriteLine("info value is {0}",(int)info); 30 Console.WriteLine("info type is {0}",info.GetType()); 31 32 33 //See if current flag is set. 34 if ((info & DataInfo.OptionA) == DataInfo.OptionA && 35 (info & DataInfo.OptionB) != DataInfo.OptionB && 36 (info & DataInfo.OptionC) == DataInfo.OptionC) 37 { 38 Console.WriteLine("Has OptionA,OptionC,but not OptionB."); 39 } 40 } 41 } 42 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)