平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“C#中的enum、struct和class三种类型的对比总结”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
在 C# 类型系统里,enum、struct 和 class 是三种最基础且最重要的类型定义方式。它们分别服务于不同的场景,理解其本质区别和适用场景,对于编写高质量的代码至关重要。本文将系统性地总结这三种类型的特性、差异及采用建议。
| 类型 | 分类 | 存储位置 | 核心用途 | 典型场景 |
|---|---|---|---|---|
| enum | 值类型 | 栈 | 定义一组命名常量 | 状态、选项、类型标识 |
| struct | 值类型 | 栈 | 封装小型数据组 | 坐标、参数、数据传输对象 |
| class | 引用类型 | 堆 | 定义复杂业务对象 | 服务、管理器、实体模型 |
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 是值类型,用来封装一组相关的数据字段,通常代表一个轻量级的、不可变的数据结构。
// 推荐:不可变结构体
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 也被修改)
class 是引用类型,用来定义具有状态和行为的复杂对象,是面向对象编程的核心。
// 抽象基类
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} 已销毁");
}
}
// 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
// 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 回收
}
| 特性 | enum | struct | class |
|---|---|---|---|
| 无参构造函数 | 不兼容 | 有限兼容 | 完全兼容 |
| 析构函数 | 不兼容 | 不兼容 | 兼容 |
| 继承类 | 不兼容 | 不兼容 | 兼容 |
| 实现接口 | 兼容 | 兼容 | 兼容 |
| 可为 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);
}
}
[Flags])// ✅ 显式指定值,便于序列化
public enum LogLevel
{
Debug = 10,
Info = 20,
Warning = 30,
Error = 40
}
// ✅ 位标志使用 2 的幂
[Flags]
public enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
// ❌ 避免复杂的逻辑判断
// ❌ 不要在枚举中定义方法(使用扩展方法替代)
// ✅ 设计为不可变类型
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) { }
// ❌ 避免在结构体中定义引用类型字段(会导致复制成本增加)
// ❌ 避免频繁装箱拆箱
// ✅ 遵循 SOLID 原则
// ✅ 需要继承时设计抽象基类
public abstract class Repository<T> { }
// ✅ 考虑使用接口定义契约
public interface IUserService { }
// ✅ 大型对象实现 IDisposable
public class DatabaseConnection : IDisposable
{
public void Dispose() { /* 释放资源 */ }
}
| 操作 | enum | struct | class |
|---|---|---|---|
| 新建小对象(<16B) | 最快 | 快 | 慢(堆分配) |
| 新建大对象 | N/A | 慢(复制成本高) | 快(引用传递) |
| 传递参数 | 快(值复制) | 小对象快,大对象慢 | 快(引用传递) |
| GC 压力 | 无 | 无 | 有 |
| 数组访问 | 快 | 连续内存 | 分散内存 |
enum、struct 和 class 是 C# 类型系统的三大基石,各有其独特的设计哲学和适用场景:
落到代码里,理解同时善用这三种类型,是写出高质量 C# 代码的关键。在真实项目中,根据数据大小、生命周期、共享需求和性能要求,选择最合适的类型,才能构建出既健壮又高效的应用程序。
到此这篇关于C#中的enum、struct和class三种类型的对比总结的文章就介绍到这了,更多相关C# enum struct和class内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!