C#enum枚举解析(含IL解析)(一)
enum枚举用于存储命名的和神奇的内容。一般在collection、if和switch中使用enum枚举。
Enum枚举:
思考一下,一个项目存储有代表性的花,花可能会有紫色的颜色,一个枚举可以代表各种颜色---这比string类型更加强大。
Enum枚举用法:
在C#程序中,我们必须以类似于类的方式来指定一个枚举。然后我们可以在需要的地方重复使用它。枚举类似于int整数,添加了编译器检查。
Enum示例:
这是一个枚举示例,表达重要性的。枚举类型内部包含了一个枚举器列表。数值(像Trivial 和 Critical)是整数,从1到4.
Int: 枚举的底层默认值是int。当我们使用一个Importance变量时,我们正在使用的就是一个int值。
If:我们用包含if-else语句块的if语句测试枚举值。这个值是Critical,所以“True”打印出来了。
第一步:我们指定一个枚举变量并将它分配给Importance.Critical。这就像一个int,但是有特殊的约束。
第二步:我们用if语句测试枚举值,值是Critical,所以打印出来“True”;
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 EnumDemo1 9 { 10 class Program 11 { 12 enum Importance 13 { 14 None, 15 Trivial, 16 Regular, 17 Important, 18 Critical 19 } 20 21 static void Main(string[] args) 22 { 23 //Step 1:create an enum local. 24 Importance value = Importance.Critical; 25 26 //Step 2:test against a known Importance value. 27 if (value == Importance.Critical) 28 { 29 Console.WriteLine(true); 30 } 31 } 32 } 33 }
Parse用法
有时候我们有个string值,我们想要转换成一个等效的枚举值 。我们调用Enum.Prase泛型函数来完成这种转换。(注意:Enum.Prase泛型函数是.NET5.0里面的,Visual Studio 2010无法使用,所以我们更换一种方式)
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 using System.Runtime; 8 9 namespace EnumPraseDemo 10 { 11 class Program 12 { 13 enum PetType 14 { 15 None,Cat,Dog 16 } 17 18 static void Main(string[] args) 19 { 20 string test = "Baby"; 21 //Get enum from string 22 PetType result = (PetType)Enum.Parse(typeof(PetType),test); 23 Console.WriteLine(result); 24 } 25 } 26 }
这样产生了错误,因为Baby在PetType枚举中是不存在的,所以PetType无法完成转换,产生异常。
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 using System.Runtime; 8 9 namespace Enum.PraseDemo 10 { 11 class Program 12 { 13 enum PetType 14 { 15 None,Cat,Dog 16 } 17 18 static void Main(string[] args) 19 { 20 string test = "Dog"; 21 //Get enum from string 22 PetType result = (PetType)Enum.Parse(typeof(PetType),test); 23 Console.WriteLine(result); 24 } 25 } 26 }
第9行命名空间与第22行的Enum.Parse产生了冲突,所以一般命名空间中尽量少使用“.”号;
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 using System.Runtime; 8 9 namespace EnumPraseDemo 10 { 11 class Program 12 { 13 enum PetType 14 { 15 None,Cat,Dog 16 } 17 18 static void Main(string[] args) 19 { 20 string test = "Dog"; 21 //Get enum from string 22 PetType result = (PetType)Enum.Parse(typeof(PetType),test); 23 Console.WriteLine(result); 24 } 25 } 26 }
本次运行成功,输出为Dog
提示:使用.NET时调用内置函数进行转换(如果存在的话)通常是最好的方式。
调试器:
我们检查了枚举在Visual Studio调试器中的样子。我们可以看到枚举每个都是独立的类型。调试器显示tagValue是Program.TagType类型。
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 EnumDebuggerDemo 9 { 10 class Program 11 { 12 enum TagType 13 { 14 None,BoldTag,ItalicsTag,HyperlinkTag 15 } 16 17 static void Main(string[] args) 18 { 19 //指定一个tag实例 20 TagType tagValue = TagType.BoldTag; 21 22 23 if (tagValue == TagType.BoldTag) 24 { 25 Console.WriteLine("Bold"); 26 } 27 if (tagValue == TagType.HyperlinkTag) 28 { 29 Console.WriteLine("Not True"); 30 } 31 Console.WriteLine("tagValue is the type :{0}", tagValue.GetType()); 32 Console.WriteLine("ItalicsTag is the type :{0}", TagType.ItalicsTag.GetType()); 33 } 34 } 35 }
info:从上面示例可以看出 ,每个enum枚举类型都是独立的,我们无法尝试将TagType类型变为PetType类型。
枚举的优势:
使用枚举,常数是独立分开的。这种模块化设计可以使事情更加容易理解。很少会引入Bug。
考虑一下这个项目---颜色blue被认为拥有数值9001.我们可以将这个颜色储存在枚举中以便于维护。
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 EnumAdvantageDemo 9 { 10 enum CaseColor 11 { 12 Uncolored = 0, 13 Red = 8001, 14 Blue = 9001 15 } 16 17 class Program 18 { 19 static void Main(string[] args) 20 { 21 //This makes sense to read. 22 Console.WriteLine("Color:{0},{1}", 23 CaseColor.Blue, 24 (int)CaseColor.Blue); 25 //This is more confuing to read. 26 Console.WriteLine("Color:{0},{1}", 27 "Blue", 28 9001); 29 } 30 } 31 }
注:在Visual Studio中,枚举可以与IntelliSense一起使用。此功能将猜测您键入的值。我们只需按tab键,就选择我们想要的枚举类型。这是使用枚举的一个优势。
strings:
我们将在Console中显示枚举转换成strings。枚举值一直都有一个名称,比如TagType.None(在上面的例子中)。
为了打印出来枚举值,你可以在项目中调用枚举的ToString。另一种方法,比如Console.Writeline能自动调用ToString函数。
在内部,ToString调用使用了反射的函数来获取string表示方法。
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 EnumStringsDemo 9 { 10 class Program 11 { 12 enum Visibility 13 { 14 None, 15 Hidden = 2 , 16 Visible = 4 17 } 18 19 enum AnimaoType 20 { 21 None, 22 Cat =1, 23 Dog =2 24 } 25 26 static void Main(string[] args) 27 { 28 //...Two enum variables 29 AnimaoType animal = AnimaoType.Dog; 30 Visibility visible = Visibility.Hidden; 31 32 //...Use Console.WriteLine to print out heir values 33 Console.WriteLine(animal); 34 Console.WriteLine(visible); 35 } 36 } 37 }
Switch:
我们经常将if语句和枚举一起使用。但是,switch是另一种选择。并且,switch有时会编译成更加高效的IL。
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 EnumSwitchDemo 9 { 10 class Program 11 { 12 enum FormatType 13 { 14 None, 15 BoldFormat, 16 ItalicsFormat, 17 Hyperlink 18 } 19 20 static void Main(string[] args) 21 { 22 //Test enum with switch method 23 FormatType formatValue = FormatType.None; 24 if (IsFormat(formatValue)) 25 { 26 //this is printed , as we receive true from IsFormat. 27 Console.WriteLine("Error"); 28 } 29 30 formatValue = FormatType.ItalicsFormat; 31 if (IsFormat(formatValue)) 32 { 33 Console.WriteLine("True"); 34 } 35 } 36 37 static bool IsFormat(FormatType value) 38 { 39 switch (value) 40 { 41 case FormatType.BoldFormat: 42 case FormatType.ItalicsFormat: 43 { 44 //These 2 values are format values. 45 return true; 46 } 47 default: 48 { 49 //The argument is not a format value. 50 return false; 51 } 52 } 53 } 54 } 55 }
IsFormat:这个方法就像一个过滤器,告诉我们一些关于枚举值设置的信息——它包含一个switch语句。我们可以在这里把逻辑分开,而不是重复自己。这有助于阐明程序逻辑。