首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

Effective C# 原則 6:區分實值型別與參考型別的設計抉擇

     編輯:關於C#

struct(實值型別)還是 class(參考型別)?這是設計伊始必須決定、後期極難變更的抉擇。C++ 全值傳遞導致物件切割;Java 全參考傳遞犧牲效能。C# 讓你依型別職責選擇:

實值型別 = 儲存資料;參考型別 = 表現行為。

回傳值語意差異

private MyData _data;
public MyData Foo() => _data; // 實值型別:回傳副本,安全封裝
                              // 參考型別:洩露內部參考,破壞封裝

若需回傳參考型別且保護封裝,須 Clone() 產生副本,但配置額外堆積物件、需執行期型別檢查、效能低落。

介面導向回傳:參考型別優勢

private MyType _impl;
public IMyInterface Foo() => _impl; // 回傳介面,隱藏具體型別,存取行為而非資料
// MyType 應為參考型別:職責在行為多型,非資料儲存

記憶體配置模型差異

class C { private MyType _a, _b; }
var c = new C();
// MyType 為實值型別:1 次堆積配置,大小 = 2 × sizeof(MyType),內嵌儲存
// MyType 為參考型別:3 次堆積配置(C + _a + _b),各 8 位元組參考指標

陣列更明顯:MyType[100] 實值型別 = 1 次配置 100 個實體;參考型別 = 1 次配置 100 個 null 參考,後續 100 次逐一配置實體 → 碎片化、效能差。

型別演進陷阱:Employee 案例

// 版本 1:實值型別
struct Employee { public decimal Salary; public void Pay(Account a) => a.Balance += Salary; }
// 版本 2:改為參考型別加入多型
class Employee { public virtual void Pay(Account a) => a.Balance += Salary; }

既有程式碼:

var e = Employees.Find("CEO");
e.Salary += Bonus; // 版本 1:修改副本;版本 2:修改原物件 → CEO 永久加薪!

行為劇變,編譯器不警告,只在執行期產生 Bug。

選擇決策樹:全 YES 才用 struct

  1. 核心職責是儲存資料?
  2. 屬性提供完整公開介面存取資料?
  3. 確定無衍生類別需求?
  4. 確定無多型行為需求?

任何一項 NO → 參考型別。拿不準時 → 參考型別。

核心心法

  • 實值型別:高效資料容器,無多型、無繼承、副本語意保護封裝、極少 GC 壓力。
  • 參考型別:行為多型基石、身分識別、參考語意、靈活擴展。
  • 應用層邏輯用參考型別建模;資料傳輸層、簡單資料載體用實值型別。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved