使用C#中的枚举很有趣。获取一个创建的通用列表来存储您之前定义的一些枚举,并在其中添加一些项目。使用foreach或GetEnumerator<T>()
进行迭代,但是指定一些其他枚举然后原始并查看会发生什么。我期待InvalidCastException或类似的东西,但它完美的工作:)。
为了说明,我们采用一个简单的控制台应用程序并在那里创建两个枚举:汽车和动物:
public enum Cars
{
Honda = 0,
Toyota = 1,
Chevrolet = 2
}
public enum Animals
{
Dog = 0,
Cat = 1,
Tiger = 2
}
并在主要方法中执行此操作:
public static void Main()
{
List<Cars> cars = new List<Cars>();
List<Animals> animals = new List<Animals>();
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
为什么会这样?我的第一个猜测是enum实际上并不是一个自己的类型它只是和int但是那不是真的:如果我们写:
Console.WriteLine(Animals.Tiger.GetType().FullName);
我们将打印出他的全名资格!那么为什么呢?
答案 0 :(得分:21)
枚举类型是不同的,但你会被foreach中的隐式转换混淆。
让我们稍微重写你的循环:
public static void Main()
{
List<Cars> cars = new List<Cars>();
List<Animals> animals = new List<Animals>();
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节中介绍:
显式枚举转换 是:
显式枚举转换 两种类型之间的处理方式 治疗任何参与的枚举类型 作为其基本类型 枚举类型,然后执行 隐式或显式数字 结果之间的转换 类型。例如,给定枚举类型 E with和底层类型的int,a 处理从E到字节的转换 作为显式数字转换 (§6.2.1)从int到byte,和a 处理从字节到E的转换 作为隐式数字转换 (§6.1.2)从byte到int。
答案 1 :(得分:2)
从概念上讲,Enum是一个静态类型的值,带有字符串表示和数字。当您在枚举上调用ToString()
时,它将返回字符串表示形式。当您在枚举上调用GetType()
时,您将获得静态枚举类型。如果将枚举转换为int
,则将获得枚举的整数值。
枚举应该是强类型的,但有一些事情你需要注意,比如任何整数都可以强制转换为任何枚举,即使它没有相应的声明(在这种情况下,字符串表示将与数字的相同)。
在CLR中,枚举(如bool
s)仅被视为int
,但如果您调用了GetType()或GetString(),则会调用执行上述操作的版本。
答案 2 :(得分:0)
您还可以从特定类型派生枚举。
public enum Cats : byte { ... }
public enum Dogs : int { ... }