C# 枚举---分析与理解
在这篇文章中,我们会以示例的形式讨论枚举(Enums)。在文章末尾,你会懂得枚举是什么,什么时候使用枚举,如何使用枚举。
为什么我们需要枚举?
枚举是强类型的名称常量。我们用示例理解一下枚举。一个名为Employee类,Gender属性。Gender是整型。
1、0是未知性别;
2、1是男性;
3、2是女性;
1 using System; 2 using System.Collections.Generic; 3 4 namespace EnumsDemo 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 //Create a collection to store employees 11 List<Employee> empList = new List<Employee>(); 12 empList.Add(new Employee() { Name = "Anurag", Gender = 0}); 13 empList.Add(new Employee() { Name = "Pranaya", Gender = 1 }); 14 empList.Add(new Employee() { Name = "Priyanka", Gender = 2 }); 15 empList.Add(new Employee() { Name = "Sambit", Gender = 3 }); 16 17 //Loop through each employees and print the Name and Gender 18 foreach (var emp in empList) 19 { 20 Console.WriteLine("Name = {0} && Gender = {1}", emp.Name, GetGender(emp.Gender)); 21 } 22 23 Console.ReadLine(); 24 } 25 26 //This method is used to return the Gender 27 public static string GetGender(int gender) 28 { 29 // The switch here is less readable because of these integral numbers 30 switch (gender) 31 { 32 case 0: 33 return "Unknown"; 34 case 1: 35 return "Male"; 36 case 2: 37 return "Female"; 38 default: 39 return "Invalid Data for Gender"; 40 } 41 } 42 } 43 44 // 0 - Unknown 45 // 1 - Male 46 // 2 - Female 47 public class Employee 48 { 49 public string Name { get; set; } 50 public int Gender { get; set; } 51 } 52 }
上述项目代码的缺点是可读性差,可维护性差。现在,我们看一下如何使用枚举进行整体替换,使项目代码具有更好的可读和可维护性。
首先,用枚举创建Gender
修改GetGender函数方法,如下所示:
像上面那样,我们用枚举代替了数字,可以使代码更加可读和可维护。
“Gender.Unknown”会提示错误,无法将Gender.Unknown隐式转换为int。因此,需要强制转换,完整代码如下:
1 using System; 2 using System.Collections.Generic; 3 4 namespace EnumsDemo 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 //Create a collection to store employees 11 List<Employee> empList = new List<Employee>(); 12 empList.Add(new Employee() { Name = "Anurag", Gender = 0}); 13 empList.Add(new Employee() { Name = "Pranaya", Gender = 1 }); 14 empList.Add(new Employee() { Name = "Priyanka", Gender = 2 }); 15 empList.Add(new Employee() { Name = "Sambit", Gender = 3 }); 16 17 //Loop through each employees and print the Name and Gender 18 foreach (var emp in empList) 19 { 20 Console.WriteLine("Name = {0} && Gender = {1}", emp.Name, GetGender(emp.Gender)); 21 } 22 23 Console.ReadLine(); 24 } 25 26 //This method is used to return the Gender 27 public static string GetGender(int gender) 28 { 29 // The switch here is now more readable and maintainable because 30 // of replacing the integral numbers with Gender enum 31 switch (gender) 32 { 33 case (int)Gender.Unknown: 34 return "Unknown"; 35 case (int)Gender.Male: 36 return "Male"; 37 case (int)Gender.Female: 38 return "Female"; 39 default: 40 return "Invalid Data for Gender"; 41 } 42 } 43 } 44 45 // 0 - Unknown 46 // 1 - Male 47 // 2 - Female 48 public class Employee 49 { 50 public string Name { get; set; } 51 public int Gender { get; set; } 52 } 53 54 public enum Gender 55 { 56 Unknown, 57 Male, 58 Female 59 } 60 }
所以,如果一个项目用的是一系列数字,可以考虑用枚举代替,这样程序代码会可读和可维护。
需要记住的枚举的几点
1、枚举是enumerations;
2、枚举是强类型的命名常量。因此,显式强制转换是需要将枚举类型转换成整型,反之亦然;同样地,一种类型的枚举不能隐式地赋值给另一种类型的枚举,尽管他们的成员的底层数值是一样的。
3、默认枚举的底层数据类型是int 。
4、枚举的第一个元素默认值为0,以1递增。
5、也可以自定义枚举的底层数据类型和数值。
6、枚举是值类型。
7、Enum关键字用于创建枚举类型,借鉴于Enum class ,枚举包含静态方法GetValues()和GetNames(),这两个函数能用于罗列枚举的底层类型和名称。
Gender枚举底层数据类型是short,数值从1开始,以1递增
所以,这样看的话,Male值是2,Female值是3;枚举值不必须是连续的,任何有效的底层数值都是允许的,如下面这样:
下面的枚举代码不是进行编译,因为short数据类型的最大值是32767
注:可以用short.MaxValue来找出short所能支持的最大数值。
显式转换可以将枚举类型转换为整型,反之亦然
int i = Gender.Male;
上面代码不会编译,编译错误创建如下:Cannot implicitly convert type ‘Gender’ to ‘int’. An explicit conversion exists (are you missing a cast?)
Gender female = 2;
上面代码也不会编译,类似编译错误创建如下:The left-hand side of an assignment must be a variable, property or indexer
一种类型的枚举不能隐式赋值给另一种类型的枚举
尽管底层的数据类型是一样的,但是一种类型的枚举不能赋值给另一种类型的枚举。在下面的示例中,需要进行显式转换:
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 Enums1 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 Gender gender = (Gender)Season.Summer; 15 Console.WriteLine("Gender.gender的值是{0}",gender); 16 Console.WriteLine("Gender.Male的值是{0}",(int)Gender.Female); 17 Console.WriteLine("Season.Summer的值是{0}",Season.Summer); 18 Console.ReadLine(); 19 } 20 public enum Gender : int 21 { 22 Unknown = 1, 23 Male = 2, 24 Female = 3 25 } 26 public enum Season : int 27 { 28 Winter = 1, 29 Spring = 2, 30 Summer = 3 31 } 32 } 33 }
了解GetValues()和GetNames()方法函数
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 Enums2 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 int[] Values = (int[])Enum.GetValues(typeof(Gender)); 15 Console.WriteLine("Gender Enum Values"); 16 Console.WriteLine("Gender的数据类型是{0}",typeof(Gender)); 17 foreach (int value in Values) 18 { 19 Console.WriteLine(value); 20 } 21 22 Console.WriteLine(); 23 string[] Names = Enum.GetNames(typeof(Gender)); 24 Console.WriteLine("Gender Enum Names"); 25 foreach (string Name in Names) 26 { 27 Console.WriteLine(Name); 28 } 29 Console.ReadKey(); 30 } 31 public enum Gender : int 32 { 33 Unknow = 1, 34 Male =2, 35 Female =3 36 } 37 } 38 }
不能从其它枚举继承
我们用以下示例理解一下枚举不能继承
当我们编译的时候,会报错,如下:
以上可见,一个枚举不能从其它枚举进行继承。但是,类可以继承枚举嘛?我们用示例看一下:
1 using System; 2 namespace EnumsDemo 3 { 4 class Program : WeekDays 5 { 6 static void Main(string[] args) 7 { 8 Console.WriteLine((int)WeekDays.Monday); 9 Console.WriteLine((int)WeekDays.Sunday); 10 Console.WriteLine((int)WeekDays.Tuesday); 11 Console.WriteLine((int)WeekDays.Wednesday); 12 Console.WriteLine((int)WeekDays.Thursday); 13 Console.WriteLine((int)WeekDays.Friday); 14 Console.WriteLine((int)WeekDays.Saturday); 15 16 Console.ReadKey(); 17 } 18 } 19 20 public enum WeekDays 21 { 22 Sunday, 23 Monday, 24 Tuesday, 25 Wednesday, 26 Thursday, 27 Friday, 28 Saturday 29 } 30 }
运行程序会有如下报错:
上面的错误表明类也不能继承自枚举。这是因为枚举是封闭类,因此适用于封闭类的规则也适用于枚举。
复制枚举成员
让我们创建两个名称相同的枚举成员,如下示例
1 using System; 2 namespace EnumsDemo 3 { 4 class Program 5 { 6 static void Main(string[] args) 7 { 8 Console.WriteLine((int)Gender.Unknown); 9 Console.WriteLine((int)Gender.Male); 10 Console.WriteLine((int)Gender.Female); 11 Console.ReadKey(); 12 } 13 } 14 15 public enum Gender 16 { 17 Unknown, 18 Male, 19 Female, 20 Unknown 21 } 22 }
依然会报错。枚举就像类,不能定义两个名称相同的成员。