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

C# 類別與物件深度解析:從語法到設計模式

     編輯:關於C語言

前言

類別是 C# 面向對象程式設計的基石。本文系統梳理類別宣告、成員分類、存取修飾詞、繼承、多型、建構子/解構子、屬性/索引器/事件/運算子等核心概念,並以實務設計原則(SOLID、封裝、組合優於繼承)穿插說明,幫助你寫出可維護、可擴充的程式碼。

一、類別宣告與基本結構

[attributes] [modifiers] class Identifier [: base-class, interfaces]
{
    // 成員宣告
}
  • modifiers:public、internal、abstract、sealed、static、partial。
  • base-class:單一繼承,預設為 object。
  • interfaces:多重實作,以逗號分隔。

二、成員完整分類表

分類成員類型關鍵字/語法說明
資料常數const編譯期常值,隱含 static
欄位field實例/靜態變數,建議 private + 屬性封裝
函式方法method可多載、虛擬、覆寫、抽象
屬性propertyget/set 存取子,語法糖封裝欄位
索引器this[]讓物件像陣列一樣存取
事件event發布/訂閱模式,基於委派
運算子operator多載 + - == != 等,必須 public static
建構子ctor實例/靜態初始化,無回傳型別
解構子~Class()Finalizer,GC 呼叫,非決定性
型別nested type巢狀類別/結構/介面/委派

三、存取修飾詞與可見性

修飾詞可見範圍典型用途
public無限制公開 API
internal同一組件內部實作細節
protected衍生類別給子類別擴充點
protected internal同組件或衍生類別跨組件擴充
private僅含宣告類別預設,封裝細節
private protected同組件且衍生類別極少用,嚴格封裝
原則:預設 private,需要時再放寬。欄位永遠 private readonly,對外暴露屬性。

四、繼承與多型

基礎語法

public class Point { public int X, Y; public Point(int x, int y) { X=x; Y=y; } }
public class Point3D : Point { public int Z; public Point3D(int x,int y,int z):base(x,y){ Z=z; } }
  • 衍生類別隱式包含基底類別所有非建構子成員。
  • Point p = new Point3D(1,2,3); 隱含向上轉型。
  • virtual / override / abstract / sealed 控制多型行為。

抽象類別與介面選擇指南

特性abstract classinterface
多重實作單一繼承多重實作
可包含實作是C# 8+ default implementation
可含狀態是不可 (僅 static 欄位)
建構子可有不可
版本演進破壞性較大較易擴充
現代 C# 傾向:介面定義契約,抽象類別提供共用實作(如 abstract class RepositoryBase : IRepository)。

五、欄位、常數、唯讀


public class Color
{
    public static readonly Color Red = new Color(255,0,0); // 靜態唯讀,執行期初始化
    public const string ColorSpace = "sRGB";                // 編譯期常值
    private readonly byte _r, _g, _b;                       // 實例唯讀,建構子賦值
    public Color(byte r, byte g, byte b) { _r=r; _g=g; _b=b; }
}
  • const:隱含 static,值編譯期嵌入呼叫端 IL,修改需重新編譯所有參考組件。
  • readonly:執行期初始化,支援建構子邏輯,二進位相容性佳。

六、方法進階

參數傳遞模式

關鍵字方向說明
(無)In值傳遞 (參考型別傳址)
refIn/Out呼叫端需初始化
outOut呼叫端無需初始化,方法必須指派
inIn唯讀傳址,防止意外修改 (C# 7.2+)
paramsIn可變參數陣列,僅最後一個參數

方法多載解析優先序

  1. 確切匹配 (含隱含轉換)
  2. 隱含數值轉換 (int→long→float→double)
  3. params 擴展
  4. 使用者定義隱含轉換
避免模稜兩可的多載(如 F(object) vs F(int)),必要時用強制轉型 F((object)1) 指定。

七、屬性、索引器、事件、運算子

屬性模式


// 傳統
private int _age;
public int Age { get => _age; set => _age = value >= 0 ? value : throw new ArgumentException(); }

// C# 6+ 自動實作 + 初始化
public int Age { get; set; } = 18;

// C# 9+ init-only (不可變物件)
public int Age { get; init; }

// 唯讀自動實作 (C# 6+)
public int Id { get; } = Guid.NewGuid().GetHashCode();

索引器


public class BitArray
{
    private readonly uint[] _bits;
    public bool this[int index]
    {
        get => (_bits[index >> 5] & (1u << (index & 31))) != 0;
        set
        {
            if (value) _bits[index >> 5] |= 1u << (index & 31);
            else _bits[index >> 5] &= ~(1u << (index & 31));
        }
    }
}

事件標準模式


public class Timer
{
    public event EventHandler Elapsed;
    protected virtual void OnElapsed(ElapsedEventArgs e) => Elapsed?.Invoke(this, e);
}
// 訂閱
timer.Elapsed += (s, e) => Console.WriteLine(e.SignalTime);

運算子多載


public struct Money
{
    public decimal Amount { get; }
    public string Currency { get; }
    public static Money operator +(Money a, Money b)
    {
        if (a.Currency != b.Currency) throw new InvalidOperationException();
        return new Money(a.Amount + b.Amount, a.Currency);
    }
    public static bool operator ==(Money a, Money b) => a.Amount == b.Amount && a.Currency == b.Currency;
    public static bool operator !=(Money a, Money b) => !(a == b);
    // 必須成對多載 == !=、< >、<= >=
}

八、建構子與解構子

實例建構子

  • 可多載、鏈結呼叫 this(...)、呼叫基底 base(...)。
  • 無參數建構子若未顯式宣告,編譯器產生預設公用無參建構子(結構除外)。
  • static 建構子:型別初始化器,執行緒安全、僅執行一次,適合靜態欄位複雜初始化。

解構子 / Finalizer


~MyClass() { /* 釋放非託管資源 */ }
// 等價於
protected override void Finalize() { try { /*...*/ } finally { base.Finalize(); } }
  • 非決定性,由 GC 執行緒呼叫,順序不可預期。
  • 實作 IDisposable + Dispose() 模式(含 GC.SuppressFinalize(this))為釋放資源正規做法。

九、實務設計原則速查

  1. 單一職責 (SRP):一個類別只負責一件事。
  2. 開放封閉 (OCP):對擴充開放,對修改關閉(介面 + 策略模式)。
  3. 里氏替換 (LSP):衍生類別必須能替換基底類別不破壞行為。
  4. 介面隔離 (ISP):介面要小而精,避免胖介面。
  5. 依賴反轉 (DIP):高層模組依賴抽象,不依賴具體實作 (DI 容器)。
  6. 組合優於繼承:class Car { IEngine Engine; } 而非 class Car : Engine。
  7. 不可變性:readonly、init、record (C# 9+) 減少狀態 Bug。
  8. 封裝欄位:永遠 private,對外用屬性/方法。

十、C# 9+ Record 型別:不可變資料的新選擇


// 位置語法
public record Person(string Name, int Age, Address Address);
// 等價於:不可變、value-based Equals/GetHashCode、with-expression、deconstruction

var p1 = new Person("Alice", 30, new Address("Taipei"));
var p2 = p1 with { Age = 31 }; // 複製並修改
Console.WriteLine(p1 == p2);   // False (值比較)
資料傳輸物件 (DTO)、實體、值物件首選 record / record struct;行為豐富的領域模型仍用 class。

總結

精通類別與物件機制,不只是記語法,更要內化「封裝變化、依賴抽象、組合復用」的設計思維。善用 readonly/init/record 推進不可變風格,配合介面導向程式設計,即能構建經得起需求變更的高品質 C# 代碼庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved