有趣的C#枚举.获取一个创建的通用列表来存储您之前定义的一些枚举,并在其中添加一些项目.用foreach迭代或者GetEnumerator
指定一些其他枚举然后原始,看看会发生什么.我期待InvalidCastException或类似的东西,但它完美的工作:).
为了说明,我们采用一个简单的控制台应用程序并在那里创建两个枚举:汽车和动物:
public enum Cars { Honda = 0, Toyota = 1, Chevrolet = 2 } public enum Animals { Dog = 0, Cat = 1, Tiger = 2 }
并在主要方法中执行此操作:
public static void Main() { Listcars = new List (); List animals = new List (); cars.Add(Cars.Chevrolet); cars.Add(Cars.Honda); cars.Add(Cars.Toyota); foreach (Animals isItACar in cars) { Console.WriteLine(isItACar.ToString()); } Console.ReadLine(); }
它会在控制台中打印出来:
Tiger Dog Cat
为什么会这样?我的第一个猜测是,枚举实际上并不是一个自己的类型,它只是和int但是这不是真的:如果我们写:
Console.WriteLine(Animals.Tiger.GetType().FullName);
我们将打印出他的全名资格!那么为什么呢?
枚举类型是不同的,但你会被foreach中的隐式转换混淆.
让我们重写一下你的循环:
public static void Main() { Listcars = new List (); List animals = new List (); cars.Add(Cars.Chevrolet); cars.Add(Cars.Honda); cars.Add(Cars.Toyota); foreach (Cars value in cars) { // This time the cast is explicit. Animals isItACar = (Animals) value; Console.WriteLine(isItACar.ToString()); } Console.ReadLine(); }
现在结果让你感到惊讶吗?希望不是,除了你可以从一个枚举到另一个枚举的事实.这只是原始代码所做的更明确的版本.
事实上,每个foreach
循环都隐含了一个强制转换的事实(即使它通常是一个无操作),大多数开发人员都会觉得这一点令我感到困惑.
从C#3.0规范的第8.8.4节开始:
上述步骤,如果成功,则明确地生成集合类型C,枚举器类型E和元素类型T.表单的foreach语句
foreach (V v in x) embedded-statement
然后扩展到:
{ E e = ((C)(x)).GetEnumerator(); try { V v; while (e.MoveNext()) { v = (V)(T)e.Current; embedded-statement } } finally { ... // Dispose e } }
枚举转换本身在第6.2.2节中介绍:
显式枚举转换是:
从sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double或decimal到任何枚举类型.
从任何枚举类型到字节,字节,短,ushort,int,uint,long,ulong,char,float,double或decimal.
从任何枚举类型到任何其他枚举类型.
通过将任何参与的枚举类型视为该枚举类型的基础类型,然后在结果类型之间执行隐式或显式数字转换,处理两种类型之间的显式枚举转换.例如,给定枚举类型E with和基础类型int,从E到byte的转换作为显式数字转换(第6.2.1节)从int到byte处理,从byte到E的转换处理为从byte到int的隐式数值转换(第6.1.2节).