C#基础10-结构体和枚举

零、文章目录

C#基础10-结构体和枚举

1、结构体

(1)核心特性
  • 值类型本质
    • 内存分配在栈上(类在堆上)
    • 赋值时复制完整数据副本(非引用)
csharp 复制代码
PointStruct p1 = new PointStruct(1, 2);  
PointStruct p2 = p1;  // p2是p1的独立副本  
p2.X = 3;             // p1.X仍为1 
  • 默认构造函数限制
    • 不能自定义无参构造函数(编译器强制隐式生成)
    • 有参构造函数必须初始化所有字段:
csharp 复制代码
public struct Point {  
    public int X;  
    public int Y;  
    public Point(int x, int y) {  
        X = x;  // 必须初始化  
        Y = y;  // 否则编译错误  
    }  
}  
  • 字段初始化限制:声明时禁止直接赋初值(类允许)
csharp 复制代码
public struct BadExample {  
    public int Value = 10; // 编译错误 
}  
  • 继承与多态
    • 不支持继承其他结构体或类(隐式继承System.ValueType
    • 可实现接口(如 IComparable
(2)结构体 vs 类
特性 结构体(struct) 类(class)
类型 值类型(栈内存) 引用类型(堆内存)
赋值行为 复制完整数据副本 复制引用地址
null值 不可为null(除非Nullable<T> 默认值为null
内存开销 小对象高效(通常<16字节) 大对象或长期存在对象更合适
构造函数 不能自定义无参构造 可自定义无参构造
字段初始化 声明时禁止赋初值 允许声明时初始化
继承 不支持 支持单继承和多态
  • 赋值差异图示:
(3)适用场景与最佳实践
  • 优先使用结构体
    • 轻量级数据对象(如坐标Point、颜色Color
    • 数据大小小于16字节(避免复制开销过大)
    • 需要高频创建销毁的临时对象(栈分配更快)
    • 设计为不可变类型(避免值复制引发逻辑错误)
  • 避免使用结构体
    • 需继承或多态的场景
    • 对象状态需频繁修改(值类型复制开销大)
    • 大小超过16KB(栈内存限制)
  • 性能优化技巧
    • 避免频繁装箱拆箱(如存入ArrayList改用List<T>
    • 只读结构体提升安全性:
csharp 复制代码
public readonly struct ImmutablePoint {  
    public int X { get; }  // 只读属性  
    public int Y { get; }  
}  
(4)关键注意事项
  • 慎用大型结构体 :超过16字节时,赋值复制可能比引用传递更慢
  • 接口实现限制:通过接口访问结构体会触发装箱操作(性能损失)
  • 默认值问题:未显式初始化时,数值类型为0,布尔类型为false

2、枚举

(1)基础定义与特性
  • 核心作用
    • 定义一组命名常量的值类型,用于表示有限且互斥的选项(如状态码、类型分类)。
    • 默认基础类型为 int,可显式指定为其他整数类型(byte, long 等)。
  • 声明语法
csharp 复制代码
public enum Season 
{
    Spring,  // 默认值 0 
    Summer,  // 默认值 1
    Autumn = 2,  // 显式赋值 
    Winter   // 自动递增为 3
}
  • 默认值规则
    • 首成员未赋值时默认为 0,后续成员依次递增 1。
    • 重要限制:枚举变量未初始化时默认值为 0(即使未定义值为 0 的成员)。
(2)高级用法:位标志(Flags)
  • 通过 [Flags] 特性支持组合值,用于多选场景(如权限系统):
csharp 复制代码
[Flags]
public enum FileAccess 
{
    None = 0,        // 避免使用 0 表示有效标志 
    Read = 1 << 0,   // 二进制 0001 (值 1)
    Write = 1 << 1,  // 二进制 0010 (值 2)
    Execute = 1 << 2 // 二进制 0100 (值 4)
}
 
// 使用按位或组合选项 
var access = FileAccess.Read | FileAccess.Write; // 值 3 (二进制 0011)
Console.WriteLine(access); // 输出 "Read, Write"
  • 关键要点:
    • 成员值需为 2 的幂次方,确保位运算正确 。
    • 避免用 0 表示有效标志(None 除外)。
(3)枚举转换与操作
  • 与整数互转
csharp 复制代码
int value = (int)Season.Summer;      // 1
Season season = (Season)2;           // Autumn 
  • 与字符串互转
csharp 复制代码
string name = Season.Spring.ToString();      // "Spring"
Season parsed;
bool success = Enum.TryParse("Winter", out parsed); // true
  • 反射操作
csharp 复制代码
// 获取所有成员名 
string[] names = Enum.GetNames(typeof(Season)); 
// 获取所有值 
Array values = Enum.GetValues(typeof(Season)); 
// 获取基础类型 
Type baseType = Enum.GetUnderlyingType(typeof(Season)); // System.Int32 
(4)最佳实践与场景
  • 适用场景
    • 状态码(如 HTTP 状态 200_OK, 404_NotFound)。
    • 分类选项(如用户等级 Gold, Silver)。
    • 多选标志(权限控制、选项组合)。
  • 设计建议
    • 为成员添加 XML 注释或 Description 特性增强可读性。
    • 避免重复值,强制显式赋值以提升代码可维护性。
csharp 复制代码
public enum UserLevel
{
    [Description("金牌会员")]
    Gold = 1,
    [Description("银牌会员")]
    Silver = 2
}
️(5)常见误区
  • 未处理非法值 :使用 Enum.IsDefined 验证值合法性:
csharp 复制代码
Season invalid = (Season)10; // 合法但无对应成员
Console.WriteLine(invalid);  // 输出 "10"
csharp 复制代码
if (Enum.IsDefined(typeof(Season), value)) { ... }
  • 忽略默认值风险:未初始化的枚举变量值为 0,需确保 0 值有明确语义(如 None)。
(6)枚举与描述转换
csharp 复制代码
public static class EnumExtensions 
{
    public static string GetDescription(this Enum value)
    {
        FieldInfo field = value.GetType().GetField(value.ToString());
        DescriptionAttribute attribute = field.GetCustomAttribute<DescriptionAttribute>();
        return attribute?.Description ?? value.ToString();
    }
}
 
// 使用 
UserLevel level = UserLevel.Gold;
Console.WriteLine(level.GetDescription()); // 输出 "金牌会员"
相关推荐
带娃的IT创业者3 小时前
第4集:配置管理的艺术:环境变量、多环境配置与安全实践
开发语言·python·安全·项目配置·开发基础
领创工作室3 小时前
安卓设备分区作用详解-测试机红米K40
android·java·linux
省四收割者3 小时前
Go语言入门(20)-nil
开发语言·vscode·golang
19岁开始学习3 小时前
Go语言中的Zap日志库
开发语言·golang·xcode
数据知道3 小时前
Go基础:用Go语言操作MongoDB详解
服务器·开发语言·数据库·后端·mongodb·golang·go语言
爱喝白开水a4 小时前
2025时序数据库选型,从架构基因到AI赋能来解析
开发语言·数据库·人工智能·架构·langchain·transformer·时序数据库
朝新_4 小时前
【EE初阶 - 网络原理】网络通信
java·开发语言·网络·php·javaee
TeleostNaCl4 小时前
使用 jintellitype 库在 Java 程序中实现监听 Windows 全局快捷键(热键)
java·开发语言·windows·经验分享·kotlin·电脑
GISer_Jing4 小时前
前端GIS篇——WebGIS、WebGL、Java后端篇
java·前端·webgl