1. 枚举

枚举类型 (enum type) 是一种独特的值类型(第 4.1 节),它用于声明一组命名的常量。

下面的示例

enum Color
{
Red,
Green,
Blue
}

声明一个名为 Color 的枚举类型,该类型具有三个成员:Red、Green 和 Blue。

1.1 枚举声明

枚举声明用于声明新的枚举类型。枚举声明以关键字 enum 开始,然后定义该枚举的名称、可访问性、基础类型和成员。

enum-declaration:
attributesopt   enum-modifiersopt   enum  
identifier   enum-baseopt   enum-body  
;opt

enum-base:
:  
integral-type

enum-body:
{  
enum-member-declarationsopt  
}
{  
enum-member-declarations   ,   }

每个枚举类型都有一个相应的整型类型,称为该枚举类型的基础类型 (underlying type)。此基础类型必须能够表示该枚举中定义的所有枚举数值。枚举声明可以显式地声明 byte、sbyte、short、ushort、int、uint、long 或 ulong 的基础类型。请注意 char 不能用作基础类型。没有显式地声明基础类型的枚举声明意味着所对应的基础类型是 int。

下面的示例

enum Color:
long
{
Red,
Green,
Blue
}

声明了一个基础类型为 long 的枚举。开发人员可以像本示例一样选择使用 long 基础类型,以便能够使用在 long 范围内而不是在 int 范围内的值,或者保留此选项供将来使用。

1.2 枚举修饰符

enum-declaration 可以根据需要包含一个枚举修饰符序列:

enum-modifiers:
enum-modifier
enum-modifiers   enum-modifier

enum-modifier:
new
public
protected
internal
private

同一修饰符在一个枚举声明中多次出现属于编译时错误。

枚举声明的修饰符与类声明(第 10.1.1 节)的修饰符具有同样的意义。然而请注意,在枚举声明中不允许使用 abstract 和 sealed 修饰符。枚举不能是抽象的,也不允许派生。

1.3 枚举成员

枚举类型声明体用于定义零个或多个枚举成员,这些成员是该枚举类型的命名常量。任意两个枚举成员不能具有相同的名称。

enum-member-declarations:
enum-member-declaration
enum-member-declarations   ,   enum-member-declaration

enum-member-declaration:
attributesopt   identifier
attributesopt  
identifier   =   constant-expression

每个枚举成员均具有相关联的常量值。此值的类型就是包含了它的那个枚举的基础类型。每个枚举成员的常量值必须在该枚举的基础类型的范围之内。下面的示例

enum Color:
uint
{
Red = -1,
Green = -2,
Blue = -3
}

会导致编译时错误,因为常量值 -1、-2 和 –3 不处于基础整型 uint 的范围中。

多个枚举成员可以共享同一个关联值。下面的示例

enum Color
{
Red,
Green,
Blue,

Max = Blue
}

演示一个枚举,其中的两个枚举成员(Blue 和 Max)具有相同的关联值。

一个枚举成员的关联值或隐式地、或显式地被赋值。如果枚举成员的声明中具有 constant-expression 初始值设定项,则该常量表达式的值(它隐式转换为枚举的基础类型)就是该枚举成员的关联值。如果枚举成员的声明不具有初始值设定项,则它的关联值按下面规则隐式地设置:

  • 如果枚举成员是在枚举类型中声明的第一个枚举成员,则它的关联值为零。
  • 否则,枚举成员的关联值是通过将前一个枚举成员(按照文本顺序)的关联值加 1 得到的。这样增加后的值必须在该基础类型可表示的值的范围内;否则,会出现编译时错误。

下面的示例

using System;

enum Color
{
Red,
Green = 10,
Blue
}

class Test
{
static void Main() {
     Console.WriteLine(StringFromColor(Color.Red));
     Console.WriteLine(StringFromColor(Color.Green));
     Console.WriteLine(StringFromColor(Color.Blue));
}

static string StringFromColor(Color c) {
     switch (c) {
        case Color.Red:
            return String.Format("Red
= {0}", (int) c);

case Color.Green:
            return
String.Format("Green = {0}", (int) c);

case Color.Blue:
            return
String.Format("Blue = {0}", (int) c);

default:
            return "Invalid
color";
     }
}
}

输出枚举成员名称和它们的关联值。输出为:

Red = 0
Green = 10
Blue = 11

原因如下:

  • 枚举成员
    Red 被自动赋予零值(因为它不具有初始值设定项并且是第一个枚举成员);
  • 枚举成员
    Green 被显式赋予值 10;
  • 而枚举成员
    Blue 被自动赋予比文本上位于它前面的成员大 1 的值。

枚举成员的关联值不能直接或间接地使用它自己的关联枚举成员的值。除了这个循环性限制外,枚举成员初始值设定项可以自由地引用其他的枚举成员初始值设定项,而不必考虑它们所在的文本位置的排列顺序。在枚举成员初始值设定项内,其他枚举成员的值始终被视为属于所对应的基础类型,因此在引用其他枚举成员时,没有必要使用强制转换。

下面的示例

enum Circular
{
A = B,
B
}

产生编译时错误,因为 A 和 B 的声明是循环的。A 显式依赖于 B,而 B 隐式依赖于 A。

枚举成员的命名方式和作用范围与类中的字段完全类似。枚举成员的范围是包含了它的枚举类型的体。在该范围内,枚举成员可以用它们的简单名称引用。在所有其他代码中,枚举成员的名称必须用它的枚举类型的名称限定。枚举成员不具有任何声明可访问性,如果一个枚举类型是可访问的,则它所含的所有枚举成员都是可访问的。

1.4 System.Enum
类型

System.Enum 类型是所有枚举类型的抽象基类(它是一种与枚举类型的基础类型不同的独特类型),并且从 System.Enum 继承的成员在任何枚举类型中都可用。存在从任何枚举类型到 System.Enum 的装箱转换(第 4.3.1 节),并且存在从 System.Enum 到任何枚举类型的取消装箱转换(第 4.3.2 节)。

请注意,System.Enum 本身不是
enum-type。而是
class-type,所有
enum-type 都是从它派生的。类型 System.Enum 从类型 System.ValueType(第 4.1.1 节)继承,而后者又从类型 object
继承。在运行时,类型 System.Enum 的值可以是 null 或是对任何枚举类型的装箱值的引用。

1.5 枚举值和运算

每个枚举类型都定义了一个不同的类型;需要使用显式枚举转换(第 6.2.2 节)在枚举类型和整型之间或在两个枚举类型之间进行转换。一个枚举类型的值域不受它的枚举成员限制。具体而言,一个枚举的基础类型的任何一个值都可以被强制转换为该枚举类型,成为该枚举类型的一个独特的有效值。

枚举成员所属的类型就是声明了它们的那个枚举(出现在其他枚举成员初始值设定项中时除外:请参见第 14.3 节)。在枚举类型 E 中声明且关联值为 v 的枚举成员的值为 (E)v。

以下运算符可用于枚举类型的值:==、!=、<、>、<=、>=(第 7.10.5 节)、二元 +(第 7.8.4 节)、二元 ‑(第 7.8.5 节)^、&、|(第 7.11.2 节)、~(第 7.7.4 节)、++ 和 --(第 7.6.9 节和第 7.7.5 节)。

每个枚举类型自动派生自类 System.Enum (后者又派生自 System.ValueType 和 object) \t "See also Enum" \t "See also Enum"  \t "See also Enum"  \t "See Enum" \t "See also
Enum"  \t "See Enum" 。因此,此类的派生方法和属性可以用在枚举类型的值上。

C# 语言规范_版本5.0 (第14章 枚举)的更多相关文章

  1. C# 语言规范_版本5.0 (第2章 词法结构)

    1. 词法结构 1.1 程序 C# 程序 (program) 由一个或多个源文件 (source file) 组成,源文件的正式名称是编译单元 (compilation unit)(第 9.1 节). ...

  2. C# 语言规范_版本5.0 (第10章 类)

    1. 类 类是一种数据结构,它可以包含数据成员(常量和字段).函数成员(方法.属性.事件.索引器.运算符.实例构造函数.静态构造函数和析构函数)以及嵌套类型.类类型支持继承,继承是一种机制,它使派生类 ...

  3. C# 语言规范_版本5.0 (第3章 基本概念)

    1. 基本概念 1.1 应用程序启动 具有入口点 (entry point) 的程序集称为应用程序 (application).应用程序运行时,将创建新的应用程序域 (application doma ...

  4. C# 语言规范_版本5.0 (第18章 不安全代码)

    1. 不安全代码 **(注:此章对于跨多语言编程开发非常重要,如遇异常无法完成跨语言,建议使用此种方式.) 如前面几章所定义,核心 C# 语言没有将指针列入它所支持的数据类型,从而与 C 和 C++ ...

  5. C# 语言规范_版本5.0 (第17章 特性)

    1. 特性 C# 语言的一个重要特征是使程序员能够为程序中定义的实体指定声明性信息.例如,类中方法的可访问性是通过使用 method-modifiers(public.protected.intern ...

  6. C# 语言规范_版本5.0 (第11章 结构)

    1. 结构 结构与类的相似之处在于,它们都表示可以包含数据成员和函数成员的数据结构.但是,与类不同,结构是一种值类型,并且不需要堆分配.结构类型的变量直接包含了该结构的数据,而类类型的变量所包含的只是 ...

  7. C# 语言规范_版本5.0 (第8章 语句)

    1. 语句 C# 提供各种语句.使用过 C 和 C++ 编程的开发人员熟悉其中大多数语句. statement: labeled-statement declaration-statement emb ...

  8. C# 语言规范_版本5.0 (第7章 表达式)

    1. 表达式 表达式是一个运算符和操作数的序列.本章定义语法.操作数和运算符的计算顺序以及表达式的含义. 1.1 表达式的分类 一个表达式可归类为下列类别之一: 值.每个值都有关联的类型. 变量.每个 ...

  9. C# 语言规范_版本5.0 (第6章 转换)

    1. 转换 转换(conversion) 使表达式可以被视为一种特定类型.转换可导致将给定类型的表达式视为具有不同的类型,或其可导致没有类型的表达式获得一种类型.转换可以是隐式的 (implicit) ...

随机推荐

  1. java文件上传--基于ajaxFileUpload+struts2

    jQuery插件ajaxFileUpload可以实现ajax文件上传,使用非常简单. 下面做一个简单的demo(以上传图片为例),实现图片上传,图片显示,图片下载 注:以下的代码是在项目的基础上进行开 ...

  2. iOS 开发之协议-代理传值

    刚开始做iOS开发的时候,对 protocol.delegate 的理解一直都是晕晕乎乎一知半解的状态,不知道两个UIViewController之间怎么进行传值. 面试过几个童鞋,问道怎么用 del ...

  3. Introduction to SharePoint hierarchy

    /* Author: Jiangong SUN */ I've participated in a SharePoint 2010 project to build an intranet. Base ...

  4. django User model

    django User model operation this tutorial will guide us to know how to manipulate django User model. ...

  5. [置顶] github 出现 Permission denied (publickey)的解决

    今天写了一篇博客,想push到github上的时候出现了以下错误 Permission denied (publickey). fatal: The remote end hung up unexpe ...

  6. hdu 1671 Phone List(字典树)

    知道bug的时候我眼泪掉下来... 我的第一道字典树,看了字典树的注意事项和实现方式,我写这道题的时候格外认真,就是奔着1A去的.结果这是几A来着? 第一遍写的时候提交MLA,我看了一下,是因为我释放 ...

  7. mysql基础:数据库的创建,增删改查

    =============查看数据库========================== 使用SHOW语句找出服务器上当前存在什么数据库: mysql> SHOW DATABASES; +--- ...

  8. hdu 4515 年月份模拟题

    小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) ...

  9. 正经学C#_表达式与其运算符[算术运算符]:《c#入门经典》

    表达式:正如字面意义,它是通过算术运算符来进行运算的数学公式.表达式的意义我们都是很明白的,大白话就是一个公式嘛.不是很难懂. 表达式不是一个单独的存在,必然有操作数或者操作符的.在c#中有操作符有很 ...

  10. MySQL分表

    一.概念 1.为什么要分表和分区?日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询 ...