C# Enum

初识枚举


     1、枚举其实可以理解为一个恒量的结合,又或者可以认为它是一种类型。比如以下枚举定义:  

1 publicenum MicrosoftTechnology
2 {
3   CSharp,
4   ASPNETMVC,
5   SQLServer,
6   WCF,
7   SilverLight,
8 }

此枚举默认为int型,当然我们可以根据需要指定枚举的数据类型。比如 public enum MicrosoftTechnology: long{....} 等。
MicrosoftTechnology枚举int值分别为 Csharp:0;ASPNETMVC:1;SQLServer:2;WCF:3;SilverLight:4, 以自增1的形式自动赋值。当然也可以指定每个枚举项的值。

    2、枚举的位运算:

          Flag特性表示枚举支持位运算。一般情况下我们用到的位运算符有:&(与)、|(或)、~(非)。

          首先我们为枚举加上[Flags]特性后再指定枚举值

          将1、中的代码修改如下:      

复制代码
[Flags]
publicenum MicrosoftTechnology
{
CSharp
=1,
ASPNETMVC
=2,
SQLServer
=4,
WCF
=8,
SilverLight
=16,
}
复制代码

      这里指定枚举值主要是为了使用与、或、非这三个位运算符。将枚举值转化成二进制值:

      CSharp: 1 = 0001

      ASPNETMVC: 2 = 0010

      SQLServer: 4 = 0100

      WCF: 8 = 1000

      SilverLight: 16 = 10000

     举例说明:

          如果某位开发者选择两项微软技术分别为CSharp和ASPNETMVC 用位运算表达为 0001 | 0010 = 0011。经过不懈的努力这位开发者掌握了以上两项技术“0011”。现在我们想通过位运算检测出这位开发者是否精通CSharp:代码为:

(MicrosoftTechnology.CSharp|MicrosoftTechnology.ASPNETMVC) & MicrosoftTechnology.CSharp 等同 (0001 | 0010 = 0011)& 0001 等于 0001(CSharp :1) 
讲到这里我想您应该不难理解:为了对枚举运用位操作时指定枚举值的缘故了。非(~)操作符这里就留给读者自己实践了。


枚举基础:

1. 枚举定义

  普通情况下,枚举字段常数可以是汉字,英文,但不能是数字。当不指定值时,默认值从0开始,如下:待处理=0,审核中=1

 public enum Status
{
待处理,   //0
审核中,   //1
交易终止, //2
交易完成  //3
}

  当需要自定义值时则直接在后面赋值即可

 public enum Status
{
待处理 = 0,
审核中 = 10,
交易终止 = 20,
交易完成 = 99
}

  定义枚举Description

public enum Status
{
[Description("未审核")]
Untreated = 0,
[Description("审核中")]
Process = 10,
[Description("交易终止")]
Cancel = 20,
[Description("交易完成")]
Over= 99
}

  2.枚举取值

  通过枚举类型,常量名称取key 

Status.待处理

 

  通过枚举类型,和key,获指定的常量名称


Type type = typeof(Status); String enumName = Enum.GetName(type, key);

  通过枚举类型,和key,获指枚举Description

 public static string GetEnumDescription(Type enumType, int key)
{
FieldInfo EnumInfo = enumType.GetField(Enum.GetName(enumType, key));
DescriptionAttribute[] attributes = (DescriptionAttribute[])EnumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
return GetEnumText(enumType, key.ToString());
}

枚举类型是一种的值类型,它用于声明一组命名的常数。
   (1)枚举的声明:枚举声明用于声明新的枚举类型。



    访问修辞符 enum 枚举名:基础类型
    {
        枚举成员
    }
    基 础类型必须能够表示该枚举中定义的所有枚举数值。枚举声明可以显式地声明 byte、sbyte、short、ushort、int、uint、 long 或 ulong 类型作为对应的基础类型。没有显式地声明基础类型的枚举声明意味着所对应的基础类型是 int。
    (2)枚举成员
        枚举成员是该枚举类型的命名常数。任意两个枚举成员不能具有相同的名称。每个枚举成员均具有相关联的常数值。此值的类型就是枚举的基础类型。每个枚举成员的常数值必须在该枚举的基础类型的范围之内。
    示例:
 public enum TimeofDay:uint
        {
            Morning=-3,
            Afternoon=-2,
            Evening=-1
         }   
    产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型 uint 的范围内。
    (3)枚举成员默认值         
        在枚举类型中声明的第一个枚举成员它的默值为零。 
        以后的枚举成员值是将前一个枚举成员(按照文本顺序)的值加 1 得到的。这样增加后的值必须在该基础类型可表示的值的范围内;否则,会出现编译时错误。 
    示例:
  public enum TimeofDay:uint
        {
            Morning,
            Afternoon,
            Evening
         }   
    Morning的值为0,Afternoon的值为1,Evening的值为2。
    (4)为枚举成员显示赋值
        允许多个枚举成员有相同的值.
        没有显示赋值的枚举成员的值,总是前一个枚举成员的值+1.
      示例
public enum Number
        {
            a=1,
            b,
            c=1,
            d
        }
        b的值为2,d的值为2.
    注意:以上枚举值都不能超过它的基础类型范围。否则会报错.
    (5)枚举类型与基础类型的转换
     基础类型不能隐式转换为枚举类型
     枚举类型也不能隐式转换为基础类型
    示例:
  public enum Number
    {
        a,
        b,
        c,
        d
    } 
class Test
    {
        public static void Main()
        {
            int i=Number.a;//错误,要强制类型转换(int)Number.a
            Number n;
            n=2            //错误,要强制类型转换(Number)2
        }
    }
    (6)System.Enum类型
    System.Enum 类型是所有枚举类型的抽象基类,并且从 System.Enum 继承的成员在任何枚举类型中都可用。
    System.Enum 本身不是枚举类型。相反,它是一个类类型,所有枚举类型都是从它派生的。
    System.Enum 从类型 System.ValueType派生

 

(7)使用枚举类型    

using System;
        public enum TimeofDay
        {
             Morning,
             Afternoon,
             Evening
        }    
        class Test 
        {
             static void WriteGreeting(TimeofDay timeofDay)
             {            
                  switch(timeofDay)
                  {
                       case TimeofDay.Morning:
                            Console.WriteLine("good morning");
                            break;
                       case TimeofDay.Afternoon:
                            Console.WriteLine("good afternoon");
                            break;
                       case TimeofDay.Evening:
                            Console.WriteLine("good evening");
                            break;
                  }
             }
             static void Main() 
             {
                  WriteGreeting(TimeofDay.Morning); 
                  WriteGreeting(TimeofDay.Evening);
                  WriteGreeting(TimeofDay.Afternoon);
             }
        }
 

Unity中的Enum

1) 同一个class中定义和使用enum:

    using UnityEngine;
    using System.Collections;
     
    public class UIScript : MonoBehaviour {
     
        private enum enMenuScreen {Main, Options, Extras};
        // Use this for initialization
        void Start () {
          
        }
       
        void OnGUI()
        {
            switch (enMenuScreen)
            {
                case enMenuScreen .Main:
                {
                    if(GUI.Button (new Rect(140,80,140,70), ""))
                    {
                        Application.LoadLevel("loadingscreen");
                    }
                    if(GUI.Button (new Rect(180,80,140,70), ""))
                    {
                        enMenuScreen = Options;
                    }
                    break;
                }
                case enMenuScreen.Options:
                {
                    if(GUI.Button (new Rect(140,80,200,150), ""))
                    {
                       
                    }
                    break;
                }
            }
           
        }
    }

2) 通过inspector使用其他script里定义的enum

其他类中Enum可以定义在该类外或者类内,类外时任何调用的script都可以访问到这个Enum类型名,类内则需要调用的script调用时加上类全部名

// From example.js

enum GameType { Survival, Escape, Prevail }

var game = GameType.Survival;
//From Example2.js

var target : Example;    //在inspector里dragexample.js到taget项里

function Start () {
    switch (target.game) {
        case GameType.Survival:
            Debug.Log("hello");
            break;
    }
}

How to get global access to enum types in C#?

可以先看这里的例子:

Let say that I have the following enum coded in a file.

    public class EnumList : ScriptableObject {
     
    public enum E_COLORS { RAINBOW, RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET, LENGTH };
    public enum E_NUMBERS { INF, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, LENGTH };
     
    // Use this for initialization
    void Start () {
     
    }
     
    // Update is called once per frame
    void Update () {
     
    }
    }

How can I gain 使用其他script定义的enum?

使用class enum:

//You can just write:

    EnumList.E_COLORS

//Or if you wanted a class that has one of those colours:

    public class myNewClass : MonoBehaviour
    {
    private EnumList.E_COLORS _color = EnumList.E_COLORS.RED;
    }

使用全局enum:

You can declare the enum outside a class declaration. This way it will be accessible in the whole assembly (all C# scripts). You don't need ScriptableObject to create enums. Just move the enums outside of any class in any script file you like. And they will be available in all scripts. Don't forget to set enum as public. 比如如下的例子

// file "GameController.cs"
public enum PlantType    //declare the enum outside a class declaration
{
    Squash,
    GroundVeggie,
    Tree,

    nPlantTypeCount
}

public class GameController : MonoBehaviour
{
    // some code here
}

// file "Plant.cs"
public class Plant : MonoBehaviour
{
    PlantType plantType = PlantType.Tree;
}

 Conclusion:

Enums are types, just like classes. When you declare an enum inside a class, it's just a nested type. A nested enum just hides other enums with the same name that are declared in outer scopes, but you can still refer to the hidden enum through its fully qualified name (using the namespace prefix, in your example).

The decision whether to declare a top level enum or a nested enum depends on your design and whether those enums will be used by anything other than the class. You can also make a nested enum private or protected to its enclosing type. But, top level enums are far more common.

If you put the enumerations inside the class, you would need to specify the class name every time you use it outside of the class, for example:
//class Bar.cs

namespace Foo
{

    public class Bar()
    {
         public enum Game{ High, Low};
        public enum Switch{On, Off};
        // Blah
    }
}
// other class
SomeLongClassName x = new SomeLongClassName(SomeLongClassName.Game.High, SomeLongClassName.Switch.On);

如果定义在class外,就简单多了

SomeLongClassName x = new SomeLongClassName(Game.High, Switch.On);

You could decide to put the ennumeration inside a class if it's used only by that class, but that kind of isolation only works for classes. If you have an enumeration that is only used by a single method, you can't put it inside the method.

 3) 使用enum property
 
posted @ 2012-12-30 14:51  若愚Shawn  阅读(1179)  评论(0编辑  收藏  举报