CodeGym /课程 /C# SELF /枚举(enum)在C#中:超方便的命名常量

枚举(enum)在C#中:超方便的命名常量

C# SELF
第 10 级, 课程 4
可用

1. 入门

写代码的时候,经常要用到一堆提前就知道的、有限的选项。比如:星期几、红绿灯的颜色、游戏难度等级、订单状态。这些选项通常都是固定的值。说到这就要聊聊今天的主角——枚举(enum)。

枚举就是一种特殊的数据类型,让你能声明一组有名字的常量。
enum就像一个分好格子的盒子,每个格子贴着独一无二的标签,标签和数字一一对应。

  • 你的代码会变得更好读,而且自带注释;
  • 不用再写那些神秘的“魔法数字”比如0、1、2,直接用有意义的名字:DayOfWeek.Monday 或 TrafficLight.Red;
  • 如果你赋值错了,编译器会直接报错;
  • 其实每个枚举成员背后……就是个普通的整数!(后面还会讲到)

2. 枚举的声明语法

来,咱们先写个第一个枚举——天气类型,以后做天气App能用上。代码长这样:


// 天气条件的枚举
public enum WeatherCondition
{
    Sunny,       // 0
    Cloudy,      // 1
    Rainy,       // 2
    Stormy,      // 3
    Snowy        // 4
}
声明枚举 WeatherCondition
  • 关键字enum就是声明新类型。
  • 大括号里写的是选项的名字。默认每个选项对应一个整数,从0开始(Sunny == 0,Cloudy == 1,以此类推)。
  • 你也可以手动指定值:
public enum WeatherCondition
{
    Sunny = 1,
    Cloudy = 2,
    Rainy = 4,
    Stormy = 8,
    Snowy = 16
}

如果你要让这些值和外部标准或者协议对上号,这样写就很方便。

3. 枚举的用法

假设你写了个小App——控制台程序,根据天气做点反应。

// 应用程序类
class Program
{
    static void Main()
    {
        // 用我们的枚举存天气状态
        WeatherCondition todayWeather = WeatherCondition.Sunny;

        // 打印出来
        Console.WriteLine($"今天的天气:{todayWeather} ({(int)todayWeather})");

        // 模拟天气变化
        todayWeather = WeatherCondition.Rainy;
        Console.WriteLine($"哎呀!天气变了:{todayWeather} ({(int)todayWeather})");
    }
}

会发生啥?


今天的天气:Sunny (0)
哎呀!天气变了:Rainy (2)
  • todayWeather不是字符串,也不是数字,而是枚举的一个成员。
  • 强制转成(int)可以看到它背后的“数字代码”。

顺便说一句,枚举和条件判断配合得贼好:

if (todayWeather == WeatherCondition.Rainy)
    Console.WriteLine("带把伞吧!");

4. enum的实际用法场景

枚举都用在哪?

  • 业务系统:订单状态(New、Processing、Shipped、Cancelled)。
  • 用户管理系统:权限等级(User、Moderator、Admin)。
  • 游戏:角色状态(Idle、Moving、Jumping、Falling)。
  • GUI:按钮、消息、图标颜色啥的。

如果你深入.NET,会发现标准库里一大半类都用枚举!比如文件操作就有枚举来指定打开模式(读、写、创建)。

5. 显式赋值和取值范围

有时候你想把代码里用到的一组int值变成enum,其实很简单:


public enum CompassDirection
{
    North = 10,
    East = 20,
    South = 30,
    West = 40
}
带显式值的枚举

现在CompassDirection.North = 10,East = 20,以此类推。如果有成员没写值,它会自动比前一个大1。

存储类型

默认enum用int(4字节整数)存。但你想省内存也可以指定底层类型:

public enum TinyEnum : byte
{
    First,  // 0
    Second, // 1
    Third   // 2
}

这样每个枚举值只占一个字节!

可选类型有:byte、sbyte、short、ushort、int、uint、long、ulong。

6. enum和数字/字符串的转换

枚举 enum ↔ int 的转换:

要把enum转成int或者反过来,直接强制类型转换就行:

WeatherCondition current = WeatherCondition.Cloudy;
int number = (int)current; // 得到1

WeatherCondition fromNumber = (WeatherCondition)2; // 得到Rainy

枚举 enum ↔ string 的转换:

把enum转成字符串很简单:直接用ToString()方法。

// 枚举转字符串
string name = WeatherCondition.Stormy.ToString(); // "Stormy"

// 字符串转枚举用Enum.Parse
WeatherCondition parsed = (WeatherCondition)Enum.Parse(typeof(WeatherCondition), "Stormy");

// 也可以用Enum.TryParse
WeatherCondition parsedOk;
if (Enum.TryParse("Snowy", out parsedOk))
{
    Console.WriteLine(parsedOk); // Snowy
}

常见错误:
如果你把一个数字强转成enum,但这个数字没对应的成员,编译器不会报错,但你会得到一个“虚拟”状态。
比如:

WeatherCondition weird = (WeatherCondition)999;
Console.WriteLine(weird); // 999(不会变成"Unknown"!)

所以,写这种转换的时候要小心点。

7. switch和enum天生一对

枚举(enum)和switch配合起来超爽。这样你可以很直观地“对不同枚举值做不同反应”,不用一堆if-else。

例子:根据天气做反应

public enum WeatherCondition
{
    Sunny,
    Cloudy,
    Rainy,
    Stormy,
    Snowy
}

WeatherCondition today = WeatherCondition.Rainy;

switch (today)
{
    case WeatherCondition.Sunny:
        Console.WriteLine("晴天!可以出去玩。");
        break;
    case WeatherCondition.Cloudy:
        Console.WriteLine("阴天。可以带件外套。");
        break;
    case WeatherCondition.Rainy:
        Console.WriteLine("下雨了。别忘了带伞!");
        break;
    case WeatherCondition.Stormy:
        Console.WriteLine("暴风雨!最好宅家里。");
        break;
    case WeatherCondition.Snowy:
        Console.WriteLine("下雪啦——记得戴帽子!");
        break;
    default:
        Console.WriteLine("未知天气...");
        break;
}
  • 每个case对应一个枚举值。
  • 如果没匹配到任何已知选项,就会走default(比如变量里进了个奇怪的值)。

为啥enum+switch这么香?

  • 代码好读:所有可能的选项一目了然。
  • 扩展方便:加了新天气类型,直接多写一个case就行。
  • 更安全:编译器会提醒你是不是漏处理了某些情况(C# 8.0起还能强制检查全覆盖)。

例子:游戏里的状态枚举

public enum GameState
{
    Start,
    Playing,
    Paused,
    GameOver
}

void PrintState(GameState state)
{
    switch (state)
    {
        case GameState.Start:
            Console.WriteLine("欢迎来到游戏!");
            break;
        case GameState.Playing:
            Console.WriteLine("游戏进行中。加油!");
            break;
        case GameState.Paused:
            Console.WriteLine("暂停。可以休息下。");
            break;
        case GameState.GameOver:
            Console.WriteLine("游戏结束。再来一次吧!");
            break;
        default:
            Console.WriteLine("未知游戏状态。");
            break;
    }
}

小建议:

  • 如果有好几个选项要做一样的事,可以合并:
switch (today)
{
    case WeatherCondition.Rainy:
    case WeatherCondition.Stormy:
        Console.WriteLine("别忘了带伞和穿暖点!");
        break;
}
  • 别忘了写default,防止遇到奇怪的值(比如有人直接把数字转成enum)。
  • 用switch做“状态机”、菜单、各种固定选项的系统都很方便。

8. 枚举和.NET的常用方法/服务

.NET给枚举提供了很多好用的方法:

  • Enum.GetNames(typeof(WeatherCondition)) —— 获取所有名字。
  • Enum.GetValues(typeof(WeatherCondition)) —— 获取所有值。
  • Enum.IsDefined(typeof(WeatherCondition), "Rainy") —— 判断枚举里有没有这个成员。
  • 文档:System.Enum

例子:打印所有天气选项

foreach (var name in Enum.GetNames(typeof(WeatherCondition)))
{
    Console.WriteLine(name);
}

9. 常见错误和“坑”

  • 用“魔法数字”代替枚举,代码难读。
  • 没处理枚举里没定义的值(见前面数字强转enum的例子)。
  • 枚举成员名字没意义(Value1、Value2……过一阵谁都忘了啥意思)。
  • 一个枚举里混着不同类型的东西,违反单一职责原则。

最好的做法:只要有固定选项就用枚举,成员名字一定要有意义、能自解释。

2
任务
C# SELF, 第 10 级, 课程 4
已锁定
使用枚举来管理设置
使用枚举来管理设置
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION