C#中的enum、struct和class三種類型的對比總結(jié)
引言
在 C# 類型系統(tǒng)中,enum、struct 和 class 是三種最基礎(chǔ)且最重要的類型定義方式。它們分別服務(wù)于不同的場景,理解其本質(zhì)區(qū)別和適用場景,對于編寫高質(zhì)量的代碼至關(guān)重要。本文將系統(tǒng)性地總結(jié)這三種類型的特性、差異及使用建議。
一、三者概覽
| 類型 | 分類 | 存儲位置 | 核心用途 | 典型場景 |
|---|---|---|---|---|
| enum | 值類型 | 棧 | 定義一組命名常量 | 狀態(tài)、選項、類型標(biāo)識 |
| struct | 值類型 | 棧 | 封裝小型數(shù)據(jù)組 | 坐標(biāo)、參數(shù)、數(shù)據(jù)傳輸對象 |
| class | 引用類型 | 堆 | 定義復(fù)雜業(yè)務(wù)對象 | 服務(wù)、管理器、實體模型 |
二、enum:常量的集合
本質(zhì)
enum 是值類型,本質(zhì)上是整數(shù)類型(默認(rèn)為 int)的封裝,用于定義一組相關(guān)的命名常量。
核心特點
- 簡單純粹:只能包含枚舉成員,每個成員對應(yīng)一個常量值
- 類型安全:避免使用魔法數(shù)字,編譯時檢查
- 支持標(biāo)志位:通過
[Flags]特性支持位運算組合
代碼示例
// 基礎(chǔ)枚舉:訂單狀態(tài)
public enum OrderStatus
{
Pending = 1, // 待支付
Paid = 2, // 已支付
Shipped = 3, // 已發(fā)貨
Delivered = 4, // 已送達
Cancelled = 5 // 已取消
}
// 標(biāo)志位枚舉:用戶權(quán)限
[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; }
}
// 權(quán)限組合
Permission userPerm = Permission.Read | Permission.Write;
if (userPerm.HasFlag(Permission.Write))
{
Console.WriteLine("用戶有寫入權(quán)限");
}
適用場景
- 狀態(tài)機:訂單狀態(tài)、審批狀態(tài)、任務(wù)狀態(tài)
- 選項配置:用戶角色、權(quán)限級別、支付方式
- 類型標(biāo)識:日志級別、錯誤類型、文件類型
- 方向/方位:方向(上/下/左/右)、星期幾、月份
三、struct:輕量級數(shù)據(jù)容器
本質(zhì)
struct 是值類型,用于封裝一組相關(guān)的數(shù)據(jù)字段,通常代表一個輕量級的、不可變的數(shù)據(jù)結(jié)構(gòu)。
核心特點
- 值語義:賦值時復(fù)制整個數(shù)據(jù),修改互不影響
- 棧分配:小對象分配和釋放效率高,無 GC 壓力
- 不可變性建議:微軟推薦將 struct 設(shè)計為不可變類型
- 限制:不能繼承類,不能定義無參構(gòu)造函數(shù)(C# 10 前)
代碼示例
// 推薦:不可變結(jié)構(gòu)體
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}";
}
// 坐標(biāo)結(jié)構(gòu)體
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);
}
}
// 數(shù)據(jù)傳輸對象
public struct ProductInfo
{
public int Id;
public string Name;
public decimal Price;
}
賦值行為演示
// struct:值類型,復(fù)制整個數(shù)據(jù)
Point p1 = new Point { X = 10, Y = 20 };
Point p2 = p1; // 復(fù)制 p1 的所有數(shù)據(jù)
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 也被修改)
適用場景
- 數(shù)學(xué)概念:坐標(biāo)(Point)、尺寸(Size)、矩形(Rectangle)
- 顏色值:RGB、ARGB 顏色表示
- 日期區(qū)間:DateRange、TimeRange
- 數(shù)值區(qū)間:Range、Interval
- 輕量級 DTO:頻繁傳輸?shù)男⌒蛿?shù)據(jù)包
四、class:復(fù)雜業(yè)務(wù)對象
本質(zhì)
class 是引用類型,用于定義具有狀態(tài)和行為的復(fù)雜對象,是面向?qū)ο缶幊痰暮诵摹?/p>
核心特點
- 引用語義:賦值時傳遞引用,多處共享同一實例
- 堆分配:支持復(fù)雜的生命周期管理
- 完整的 OOP 支持:繼承、多態(tài)、封裝、析構(gòu)函數(shù)
- 靈活性:可定義無參構(gòu)造、析構(gòu)函數(shù)、虛方法等
代碼示例
// 抽象基類
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("管理員權(quán)限已激活");
}
}
public class RegularUser : User
{
public override string GetRole() => "普通用戶";
}
// 服務(wù)類(單例模式)
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} 已銷毀");
}
}
適用場景
- 業(yè)務(wù)實體:用戶、訂單、產(chǎn)品、客戶
- 服務(wù)類:用戶服務(wù)、郵件服務(wù)、數(shù)據(jù)庫服務(wù)
- 管理器:連接池、緩存管理、配置管理
- 復(fù)雜對象:需要繼承和多態(tài)的領(lǐng)域模型
- UI 組件:窗體、控件、視圖模型
五、關(guān)鍵差異詳解
1. 賦值行為對比
// enum:賦值整數(shù)常量
OrderStatus status1 = OrderStatus.Paid;
OrderStatus status2 = status1; // 復(fù)制值
// struct:復(fù)制全部數(shù)據(jù)
struct Rectangle { public int Width, Height; }
Rectangle rect1 = new Rectangle { Width = 10, Height = 20 };
Rectangle rect2 = rect1; // 復(fù)制整個結(jié)構(gòu)體
rect2.Width = 30; // rect1.Width 仍為 10
// class:復(fù)制引用
class RectangleClass { public int Width, Height; }
RectangleClass rect3 = new RectangleClass { Width = 10, Height = 20 };
RectangleClass rect4 = rect3; // 指向同一對象
rect4.Width = 30; // rect3.Width 變?yōu)?302. 內(nèi)存分配與性能
// struct:棧分配,GC 友好
public void ProcessColors()
{
var colors = new Color[10000]; // 連續(xù)內(nèi)存,訪問快
// 方法結(jié)束自動釋放,無 GC 壓力
}
// class:堆分配,GC 管理
public void ProcessUsers()
{
var users = new List<User>(); // 堆分配,需 GC 回收
users.Add(new Admin());
users.Add(new RegularUser());
// 需等待 GC 回收
}
3. 類型限制對比
| 特性 | enum | struct | class |
|---|---|---|---|
| 無參構(gòu)造函數(shù) | 不支持 | 有限支持 | 完全支持 |
| 析構(gòu)函數(shù) | 不支持 | 不支持 | 支持 |
| 繼承類 | 不支持 | 不支持 | 支持 |
| 實現(xiàn)接口 | 支持 | 支持 | 支持 |
| 可為 null | 可 | 可 | 是 |
| 默認(rèn)值 | 第一個成員 | 所有字段為默認(rèn)值 | null |
六、通用場景示例
綜合運用三種類型的實際場景:
場景一:電商系統(tǒng)
// enum:訂單狀態(tài)
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;
}
}
場景二:圖形處理系統(tǒng)
// 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:坐標(biāo)點
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() { }
}
場景三:權(quán)限管理系統(tǒng)
// enum:權(quán)限標(biāo)志位
[Flags]
public enum Permission
{
None = 0,
View = 1,
Create = 2,
Edit = 4,
Delete = 8,
Full = View | Create | Edit | Delete
}
// struct:權(quán)限組(輕量級組合)
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:用戶服務(wù)
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 當(dāng)
- 需要定義一組相關(guān)的常量值(如狀態(tài)、類型、選項)
- 替代魔法數(shù)字,增強代碼可讀性
- 需要位標(biāo)志組合(使用
[Flags]) - 做 switch-case 判斷
使用 struct 當(dāng)
- 數(shù)據(jù)量?。ńㄗh < 16 字節(jié))
- 代表單一的值(如坐標(biāo)、顏色、范圍)
- 生命周期短暫,頻繁創(chuàng)建銷毀
- 希望值語義,數(shù)據(jù)獨立
- 不需要繼承和多態(tài)
使用 class 當(dāng)
- 對象包含復(fù)雜行為和狀態(tài)
- 需要繼承和多態(tài)
- 對象較大,復(fù)制成本高
- 需要在多處共享同一實例
- 需要實現(xiàn) IDisposable 進行資源管理
八、最佳實踐總結(jié)
1. enum 最佳實踐
// ? 顯式指定值,便于序列化
public enum LogLevel
{
Debug = 10,
Info = 20,
Warning = 30,
Error = 40
}
// ? 位標(biāo)志使用 2 的冪
[Flags]
public enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
// ? 避免復(fù)雜的邏輯判斷
// ? 不要在枚舉中定義方法(使用擴展方法替代)
2. struct 最佳實踐
// ? 設(shè)計為不可變類型
public struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) { X = x; Y = y; }
}
// ? 保持結(jié)構(gòu)體小巧
// ? 需要修改時傳遞 ref 參數(shù)
public void UpdatePoint(ref Point point, int dx, int dy) { }
// ? 避免在結(jié)構(gòu)體中定義引用類型字段(會導(dǎo)致復(fù)制成本增加)
// ? 避免頻繁裝箱拆箱
3. class 最佳實踐
// ? 遵循 SOLID 原則
// ? 需要繼承時設(shè)計抽象基類
public abstract class Repository<T> { }
// ? 考慮使用接口定義契約
public interface IUserService { }
// ? 大型對象實現(xiàn) IDisposable
public class DatabaseConnection : IDisposable
{
public void Dispose() { /* 釋放資源 */ }
}
九、性能考量速查表
| 操作 | enum | struct | class |
|---|---|---|---|
| 創(chuàng)建小對象(<16B) | 最快 | 快 | 慢(堆分配) |
| 創(chuàng)建大對象 | N/A | 慢(復(fù)制成本高) | 快(引用傳遞) |
| 傳遞參數(shù) | 快(值復(fù)制) | 小對象快,大對象慢 | 快(引用傳遞) |
| GC 壓力 | 無 | 無 | 有 |
| 數(shù)組訪問 | 快 | 連續(xù)內(nèi)存 | 分散內(nèi)存 |
結(jié)語
enum、struct 和 class 是 C# 類型系統(tǒng)的三大基石,各有其獨特的設(shè)計哲學(xué)和適用場景:
- enum:用命名常量代替魔法數(shù)字,讓代碼更清晰
- struct:用值語義封裝輕量數(shù)據(jù),讓性能更高效
- class:用引用語義構(gòu)建復(fù)雜對象,讓設(shè)計更靈活
理解并善用這三種類型,是寫出高質(zhì)量 C# 代碼的關(guān)鍵。在實際開發(fā)中,根據(jù)數(shù)據(jù)大小、生命周期、共享需求和性能要求,選擇最合適的類型,才能構(gòu)建出既健壯又高效的應(yīng)用程序。
到此這篇關(guān)于C#中的enum、struct和class三種類型的對比總結(jié)的文章就介紹到這了,更多相關(guān)C# enum struct和class內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

