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 }
复制代码

 

 知识延伸:

基础知识

位操作符处理位并执行逐位运算。真值表如下所示

pqp & qp | qp ^ 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 }
复制代码

 

posted @   chenlight  阅读(203)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示