一、复杂数据类型概述
1.1 为什么需要复杂类型?
当处理包含多个关联值的复合数据时,基础数据类型(int、string等)会面临以下问题:
- 可读性差 :
if(status == 2)
中的数字难以理解 - 维护困难:多个地方使用相同含义的魔法数字
- 类型不安全:无法在编译时检查有效性
1.2 常见复杂类型
类型 | 特点 | 适用场景 |
---|---|---|
类(Class) | 引用类型,支持继承 | 业务实体建模 |
结构体(Struct) | 值类型,轻量级 | 小型数据结构 |
枚举(Enum) | 命名常量集合 | 状态/类型标识 |
数组(Array) | 固定大小的集合 | 批量数据处理 |
那么是什么是枚举呢:
cs
//枚举是一个比较特别的存在
//它是一个被命名的整形常量的集合
//一般用它来表示 状态 类型等
//申明枚举 和 申明枚举变量 是两个概念
//申明枚举 : 相当于是 创建一个自定义的枚举类型
//申明枚举变量 :使用申明的自定义枚举类型 创建一个枚举变量
二、枚举的核心价值
2.1 解决实际问题
优化前代码:
cs
if (order.Status == 3) // 3代表已发货
{
// 处理发货逻辑
}
优化后代码:
cs
enum E_OrderStatus
{
Pending,//待定
Processing,//加工
Shipped //运输
}
if (order.Status == OrderStatus.Shipped)
{
// 逻辑清晰可见
}
2.2 核心优势
- 代码自文档化
- 编译时类型检查
- 避免无效值输入
- 提升代码可维护性
三、枚举的声明与定义
3.1 基本语法
cs
enum 枚举名称
{
枚举项1, // 默认从0开始
枚举项2, // 自动递增为1
枚举项3 = 5, // 显式赋值
枚举项4 // 自动递增为6
}
3.2 声明位置规则
- 命名空间级别(推荐):
cs
namespace MyApplication
{
enum Weekday { Mon, Tue, Wed }
}
2、类/结构体内部:
cs
class Player
{
enum State { Idle, Moving }
}
3、禁止在方法内部声明:
cs
void Process()
{
// enum Error { } // 编译错误!
}
3.3 命名规范建议
- 使用名词组合(ColorType优于ColorEnum)
- 避免使用复数形式(Color代替Colors)
- 首字母大写(符合Pascal命名法)
- 最好在你的枚举类型前面加上E_,这样别人一下就能知道这是枚举类型的变量
四、枚举的基本使用
4.1 声明与赋值
cs
enum GameState
{
MainMenu,
Playing,
Paused
}
class Game
{
GameState currentState = GameState.MainMenu;
}
4.2 逻辑判断
cs
// if判断
if (currentState == GameState.Playing)
{
// 处理游戏逻辑
}
// switch判断(最佳实践)
switch (currentState)
{
case GameState.MainMenu:
ShowMenu();
break;
case GameState.Playing:
UpdateGame();
break;
case GameState.Paused:
ShowPauseMenu();
break;
}
五、类型转换详解
cs
enum GameState
{
MainMenu,
Playing,
Paused
}
5.1 枚举与整型互转
cs
// 枚举转int
GameState state = GameState.Playing;
int stateCode = (int)state; // 结果为1
// int转枚举(注意有效性检查)
int input = 2;
if (Enum.IsDefined(typeof(GameState), input))
{
GameState newState = (GameState)input;
}
5.2 枚举与字符串互转
cs
// 枚举转字符串
string stateName = GameState.Playing.ToString(); // "Playing"
// 字符串转枚举(严格区分大小写)
string input = "Paused";
if (Enum.TryParse(input, out GameState result))
{
currentState = result;
}
else
{
Console.WriteLine("无效状态!");
}
转换方向 | 代码示例 | 注意事项 |
---|---|---|
枚举 → 整型 | int code = (int)E_GameState.Playing; |
直接显式转换 |
整型 → 枚举 | E_GameState state = (E_GameState)2; |
需验证值有效性 |
枚举 → 字符串 | string str = E_GameState.Paused.ToString() |
返回枚举项名称 |
字符串 → 枚举 | Enum.Parse(typeof(E_GameState), "GameOver") |
严格区分大小写,建议TryParse |
六、枚举的高级用法
1、多状态组合(位标志)
在C#中,[Flags]
是用于枚举的特殊特性(Attribute),它开启了枚举的位运算模式,让枚举值可以像开关位一样进行组合操作。后面我们在学习反射的时候会仔细讲述。
cs
[Flags]
enum Permission
{
None = 0, // 0000
Read = 1 << 0, // 0001
Write = 1 << 1, // 0010
Execute = 1 << 2, // 0100
All = Read | Write | Execute // 0111
}
// 用户权限设置
var userPermission = Permission.Read | Permission.Write;
// 权限验证
if (userPermission.HasFlag(Permission.Write))
{
Console.WriteLine("可执行写入操作");
}
参考使用:用户权限系统,文件属性设置。
2、配置选项管理
cs
enum DisplayOptions
{
ShowHeader = 1 // 二进制 0001
ShowFooter = 2 // 二进制 0010 (1 << 1)
DarkMode = 4 // 二进制 0100 (1 << 2)
}
// 组合配置项
var currentOptions = DisplayOptions.ShowHeader | DisplayOptions.DarkMode;
// 配置检查
if ((currentOptions & DisplayOptions.DarkMode) != 0)
{
ApplyDarkTheme();
}
这个示例确实基于位标志的原理,即使没有显式使用[Flags]
特性,只要正确设置枚举值,仍然可以进行位运算操作。但是必须得保障每一个元素都是2的幂
3、游戏状态机
cs
enum PlayerState
{
Idle,
Walking,
Attacking,
Dead
}
class Player
{
private PlayerState _state;
public void TakeDamage()
{
if (_state != PlayerState.Dead)
{
_state = PlayerState.Dead;
PlayDeathAnimation();
}
}
}
4、API参数约束
cs
enum SortOrder
{
Ascending,
Descending
}
// Web API 接口
[HttpGet("products")]
public IActionResult GetProducts(SortOrder order = SortOrder.Ascending)
{
var query = order == SortOrder.Ascending
? _db.Products.OrderBy(p => p.Price)
: _db.Products.OrderByDescending(p => p.Price);
return Ok(query.ToList());
}
5、UI控件状态管理
cs
enum ButtonState
{
Normal,
Hover,
Pressed,
Disabled
}
void UpdateButtonAppearance(ButtonState state)
{
switch (state)
{
case ButtonState.Hover:
button.BackColor = Color.LightBlue;
break;
case ButtonState.Pressed:
button.BackColor = Color.Blue;
break;
case ButtonState.Disabled:
button.Enabled = false;
break;
default:
button.ResetVisuals();
break;
}
}
总结:枚举类型主要是帮助我们分辨变量的含义。而非魔法数值,让人捉摸不透。OK,下一篇预告C#中的数组