枚举只是整数,类型或两者都没有?

时间:2008-12-09 09:03:42

标签: c# enums

使用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); 我们将打印出他的全名资格!那么为什么呢?

3 个答案:

答案 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节中介绍:

  

显式枚举转换   是:

  • 从sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double或decimal到任何枚举类型。
  • 从任何enum-type到sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double或decimal。
  • 从任何枚举类型到任何其他枚举类型。
  

显式枚举转换   两种类型之间的处理方式   治疗任何参与的枚举类型   作为其基本类型   枚举类型,然后执行   隐式或显式数字   结果之间的转换   类型。例如,给定枚举类型   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 { ... }