C#中的enum、struct和class三种类型的对比总结

 更新时间:2026年03月27日 08:44:51   作者:杰西笔记  
在 C# 类型系统中,enum、struct 和 class 是三种最基础且最重要的类型定义方式,本文将系统性地总结这三种类型的特性、差异及使用建议,希望对大家有所帮助

引言

在 C# 类型系统中,enumstructclass 是三种最基础且最重要的类型定义方式。它们分别服务于不同的场景,理解其本质区别和适用场景,对于编写高质量的代码至关重要。本文将系统性地总结这三种类型的特性、差异及使用建议。

一、三者概览

类型分类存储位置核心用途典型场景
enum值类型定义一组命名常量状态、选项、类型标识
struct值类型封装小型数据组坐标、参数、数据传输对象
class引用类型定义复杂业务对象服务、管理器、实体模型

二、enum:常量的集合

本质

enum 是值类型,本质上是整数类型(默认为 int)的封装,用于定义一组相关的命名常量。

核心特点

  • 简单纯粹:只能包含枚举成员,每个成员对应一个常量值
  • 类型安全:避免使用魔法数字,编译时检查
  • 支持标志位:通过 [Flags] 特性支持位运算组合

代码示例

// 基础枚举:订单状态
public enum OrderStatus
{
    Pending = 1,      // 待支付
    Paid = 2,         // 已支付
    Shipped = 3,      // 已发货
    Delivered = 4,    // 已送达
    Cancelled = 5     // 已取消
}

// 标志位枚举:用户权限
[Flags]
public enum Permission
{
    None = 0,
    Read = 1 << 0,    // 1
    Write = 1 << 1,   // 2
    Delete = 1 << 2,  // 4
    Admin = Read | Write | Delete  // 7
}

// 使用示例
public class Order
{
    public OrderStatus Status { get; set; }
}

// 权限组合
Permission userPerm = Permission.Read | Permission.Write;
if (userPerm.HasFlag(Permission.Write))
{
    Console.WriteLine("用户有写入权限");
}

适用场景

  • 状态机:订单状态、审批状态、任务状态
  • 选项配置:用户角色、权限级别、支付方式
  • 类型标识:日志级别、错误类型、文件类型
  • 方向/方位:方向(上/下/左/右)、星期几、月份

三、struct:轻量级数据容器

本质

struct 是值类型,用于封装一组相关的数据字段,通常代表一个轻量级的、不可变的数据结构。

核心特点

  • 值语义:赋值时复制整个数据,修改互不影响
  • 栈分配:小对象分配和释放效率高,无 GC 压力
  • 不可变性建议:微软推荐将 struct 设计为不可变类型
  • 限制:不能继承类,不能定义无参构造函数(C# 10 前)

代码示例

// 推荐:不可变结构体
public struct Color
{
    public byte R { get; }
    public byte G { get; }
    public byte B { get; }
    
    public Color(byte r, byte g, byte b)
    {
        R = r;
        G = g;
        B = b;
    }
    
    public string ToHex() => $"#{R:X2}{G:X2}{B:X2}";
}

// 坐标结构体
public struct Point
{
    public double X { get; set; }
    public double Y { get; set; }
    
    public double DistanceTo(Point other)
    {
        double dx = X - other.X;
        double dy = Y - other.Y;
        return Math.Sqrt(dx * dx + dy * dy);
    }
}

// 数据传输对象
public struct ProductInfo
{
    public int Id;
    public string Name;
    public decimal Price;
}

赋值行为演示

// struct:值类型,复制整个数据
Point p1 = new Point { X = 10, Y = 20 };
Point p2 = p1;        // 复制 p1 的所有数据
p2.X = 30;            // 只修改 p2
Console.WriteLine(p1.X);  // 输出: 10 (p1 不受影响)

// 对比 class
class PointClass { public int X, Y; }
PointClass c1 = new PointClass { X = 10, Y = 20 };
PointClass c2 = c1;   // c2 和 c1 指向同一个对象
c2.X = 30;            // 修改的是同一个对象
Console.WriteLine(c1.X);  // 输出: 30 (c1 也被修改)

适用场景

  • 数学概念:坐标(Point)、尺寸(Size)、矩形(Rectangle)
  • 颜色值:RGB、ARGB 颜色表示
  • 日期区间:DateRange、TimeRange
  • 数值区间:Range、Interval
  • 轻量级 DTO:频繁传输的小型数据包

四、class:复杂业务对象

本质

class 是引用类型,用于定义具有状态和行为的复杂对象,是面向对象编程的核心。

核心特点

  • 引用语义:赋值时传递引用,多处共享同一实例
  • 堆分配:支持复杂的生命周期管理
  • 完整的 OOP 支持:继承、多态、封装、析构函数
  • 灵活性:可定义无参构造、析构函数、虚方法等

代码示例

// 抽象基类
public abstract class User
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public abstract string GetRole();
    
    public virtual void Login()
    {
        Console.WriteLine($"{UserName} 登录成功");
    }
}

// 派生类
public class Admin : User
{
    public override string GetRole() => "管理员";
    
    public override void Login()
    {
        base.Login();
        Console.WriteLine("管理员权限已激活");
    }
}

public class RegularUser : User
{
    public override string GetRole() => "普通用户";
}

// 服务类(单例模式)
public class UserService
{
    private static UserService _instance;
    private List<User> _users = new List<User>();
    
    private UserService() { }
    
    public static UserService Instance => _instance ??= new UserService();
    
    public void AddUser(User user) => _users.Add(user);
    public List<User> GetAllUsers() => _users;
}

// 实体类
public class ShoppingCart
{
    public int CartId { get; set; }
    private List<Product> _items = new List<Product>();
    
    public void AddItem(Product product)
    {
        _items.Add(product);
    }
    
    public decimal GetTotal()
    {
        return _items.Sum(item => item.Price);
    }
    
    ~ShoppingCart()
    {
        Console.WriteLine($"购物车 {CartId} 已销毁");
    }
}

适用场景

  • 业务实体:用户、订单、产品、客户
  • 服务类:用户服务、邮件服务、数据库服务
  • 管理器:连接池、缓存管理、配置管理
  • 复杂对象:需要继承和多态的领域模型
  • UI 组件:窗体、控件、视图模型

五、关键差异详解

1. 赋值行为对比

// enum:赋值整数常量
OrderStatus status1 = OrderStatus.Paid;
OrderStatus status2 = status1;  // 复制值
// struct:复制全部数据
struct Rectangle { public int Width, Height; }
Rectangle rect1 = new Rectangle { Width = 10, Height = 20 };
Rectangle rect2 = rect1;        // 复制整个结构体
rect2.Width = 30;               // rect1.Width 仍为 10
// class:复制引用
class RectangleClass { public int Width, Height; }
RectangleClass rect3 = new RectangleClass { Width = 10, Height = 20 };
RectangleClass rect4 = rect3;   // 指向同一对象
rect4.Width = 30;               // rect3.Width 变为 30

2. 内存分配与性能

// struct:栈分配,GC 友好
public void ProcessColors()
{
    var colors = new Color[10000];      // 连续内存,访问快
    // 方法结束自动释放,无 GC 压力
}

// class:堆分配,GC 管理
public void ProcessUsers()
{
    var users = new List<User>();       // 堆分配,需 GC 回收
    users.Add(new Admin());
    users.Add(new RegularUser());
    // 需等待 GC 回收
}

3. 类型限制对比

特性enumstructclass
无参构造函数不支持有限支持完全支持
析构函数不支持不支持支持
继承类不支持不支持支持
实现接口支持支持支持
可为 null
默认值第一个成员所有字段为默认值null

六、通用场景示例

综合运用三种类型的实际场景:

场景一:电商系统

// enum:订单状态
public enum OrderStatus
{
    Pending,
    Paid,
    Shipped,
    Completed,
    Cancelled
}

// enum:支付方式
public enum PaymentMethod
{
    CreditCard,
    Alipay,
    WeChat,
    BankTransfer
}

// struct:金额(不可变值类型)
public struct Money
{
    public decimal Amount { get; }
    public string Currency { get; }
    
    public Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }
    
    public Money Add(Money other)
    {
        if (Currency != other.Currency)
            throw new InvalidOperationException("货币类型不一致");
        return new Money(Amount + other.Amount, Currency);
    }
}

// class:订单实体
public class Order
{
    public int OrderId { get; set; }
    public OrderStatus Status { get; set; }
    public PaymentMethod PaymentMethod { get; set; }
    public Money TotalAmount { get; set; }
    private List<OrderItem> _items = new List<OrderItem>();
    
    public void AddItem(Product product, int quantity)
    {
        _items.Add(new OrderItem(product, quantity));
        RecalculateTotal();
    }
    
    private void RecalculateTotal()
    {
        decimal total = _items.Sum(item => item.Subtotal.Amount);
        TotalAmount = new Money(total, "CNY");
    }
    
    public void Pay(PaymentMethod method)
    {
        PaymentMethod = method;
        Status = OrderStatus.Paid;
    }
}

场景二:图形处理系统

// struct:颜色(值类型)
public struct Color
{
    public byte R, G, B, A;
    public Color(byte r, byte g, byte b, byte a = 255)
    {
        R = r; G = g; B = b; A = a;
    }
}

// struct:坐标点
public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
}

// class:图形基类(引用类型)
public abstract class Shape
{
    public Color FillColor { get; set; }
    public abstract double GetArea();
    public abstract void Draw();
}

public class Rectangle : Shape
{
    public Point Position { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    
    public override double GetArea() => Width * Height;
    public override void Draw() { }
}

场景三:权限管理系统

// enum:权限标志位
[Flags]
public enum Permission
{
    None = 0,
    View = 1,
    Create = 2,
    Edit = 4,
    Delete = 8,
    Full = View | Create | Edit | Delete
}

// struct:权限组(轻量级组合)
public struct PermissionGroup
{
    public string Name { get; }
    public Permission Permissions { get; }
    
    public PermissionGroup(string name, Permission perms)
    {
        Name = name;
        Permissions = perms;
    }
    
    public bool HasPermission(Permission perm) => Permissions.HasFlag(perm);
}

// class:用户服务
public class UserService
{
    private Dictionary<string, PermissionGroup> _groups;
    
    public UserService()
    {
        _groups = new Dictionary<string, PermissionGroup>();
    }
    
    public void AddGroup(PermissionGroup group)
    {
        _groups[group.Name] = group;
    }
    
    public bool CheckPermission(string groupName, Permission required)
    {
        return _groups.TryGetValue(groupName, out var group) &&
               group.HasPermission(required);
    }
}

七、选择指南

使用 enum 当

  • 需要定义一组相关的常量值(如状态、类型、选项)
  • 替代魔法数字,增强代码可读性
  • 需要位标志组合(使用 [Flags]
  • 做 switch-case 判断

使用 struct 当

  • 数据量小(建议 < 16 字节)
  • 代表单一的值(如坐标、颜色、范围)
  • 生命周期短暂,频繁创建销毁
  • 希望值语义,数据独立
  • 不需要继承和多态

使用 class 当

  • 对象包含复杂行为和状态
  • 需要继承和多态
  • 对象较大,复制成本高
  • 需要在多处共享同一实例
  • 需要实现 IDisposable 进行资源管理

八、最佳实践总结

1. enum 最佳实践

// ✅ 显式指定值,便于序列化
public enum LogLevel
{
    Debug = 10,
    Info = 20,
    Warning = 30,
    Error = 40
}

// ✅ 位标志使用 2 的幂
[Flags]
public enum FileAccess
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4
}

// ❌ 避免复杂的逻辑判断
// ❌ 不要在枚举中定义方法(使用扩展方法替代)

2. struct 最佳实践

// ✅ 设计为不可变类型
public struct Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) { X = x; Y = y; }
}

// ✅ 保持结构体小巧
// ✅ 需要修改时传递 ref 参数
public void UpdatePoint(ref Point point, int dx, int dy) { }

// ❌ 避免在结构体中定义引用类型字段(会导致复制成本增加)
// ❌ 避免频繁装箱拆箱

3. class 最佳实践

// ✅ 遵循 SOLID 原则
// ✅ 需要继承时设计抽象基类
public abstract class Repository<T> { }

// ✅ 考虑使用接口定义契约
public interface IUserService { }

// ✅ 大型对象实现 IDisposable
public class DatabaseConnection : IDisposable
{
    public void Dispose() { /* 释放资源 */ }
}

九、性能考量速查表

操作enumstructclass
创建小对象(<16B)最快慢(堆分配)
创建大对象N/A慢(复制成本高)快(引用传递)
传递参数快(值复制)小对象快,大对象慢快(引用传递)
GC 压力
数组访问连续内存分散内存

结语

enumstructclass 是 C# 类型系统的三大基石,各有其独特的设计哲学和适用场景:

  • enum:用命名常量代替魔法数字,让代码更清晰
  • struct:用值语义封装轻量数据,让性能更高效
  • class:用引用语义构建复杂对象,让设计更灵活

理解并善用这三种类型,是写出高质量 C# 代码的关键。在实际开发中,根据数据大小、生命周期、共享需求和性能要求,选择最合适的类型,才能构建出既健壮又高效的应用程序。

到此这篇关于C#中的enum、struct和class三种类型的对比总结的文章就介绍到这了,更多相关C# enum struct和class内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#拼图游戏编写代码(2)

    C#拼图游戏编写代码(2)

    这篇文章主要为大家详细介绍了C#拼图游戏的编写代码下篇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • c#消息提示框messagebox的详解及使用

    c#消息提示框messagebox的详解及使用

    这篇文章主要介绍了c#消息提示框messagebox的详解及使用的相关资料,需要的朋友可以参考下
    2017-03-03
  • C#实现将Excel(xlsx或xls)转换为HTML的完整指南

    C#实现将Excel(xlsx或xls)转换为HTML的完整指南

    在很多情况下,你可能需要把 Excel 文件(XLS 或 XLSX)转换成 HTML 格式,本文将教你如何使用 C# 将 Excel 转换为 HTML,并通过几个例子涵盖不同的应用场景,有需要的可以了解下
    2026-01-01
  • C#中 const 和 readonly 的不同

    C#中 const 和 readonly 的不同

    const 和 readonly 的区别,总是不太清楚,于是查了查资料。
    2013-04-04
  • C# Onnx实现特征匹配DeDoDe检测

    C# Onnx实现特征匹配DeDoDe检测

    这篇文章主要为大家详细介绍了C# Onnx如何实现特征匹配DeDoDe检测,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-11-11
  • C#如何实现Excel中图片的提取与本地保存方法

    C#如何实现Excel中图片的提取与本地保存方法

    这篇文章主要介绍了C#实现Excel中图片的提取与本地保存方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • C#利用KPM算法解决字符串匹配问题详解

    C#利用KPM算法解决字符串匹配问题详解

    Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置。本文将利用该算法解决字符串匹配问题,感兴趣的可以学习一下
    2022-11-11
  • C#11新特性使用案例详解

    C#11新特性使用案例详解

    这篇文章主要为大家介绍了C#11新特性的使用案例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 通过特性(attribute)为枚举添加更多信息示例

    通过特性(attribute)为枚举添加更多信息示例

    这篇文章主要介绍了通过特性(Attribute)为枚举添加更多的信息,大家参考使用吧
    2014-01-01
  • C# 使用modbus 读取PLC 寄存器地址的方法

    C# 使用modbus 读取PLC 寄存器地址的方法

    今天通过本文给大家介绍C# 使用modbus 读取PLC 寄存器地址的方法,使用的组件Nmodbus,文中通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-10-10

最新评论