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

深入掌握 C# 類別進階特性:方法遮蔽、屬性、索引子與事件

     編輯:關於C語言

5.2.3 方法遮蔽:當衍生類別遇上同名基類方法

繼承是物件導向的核心,但當基類庫更新、新增了與衍生類別同名的方法時,會發生什麼情況?C# 提供了 new 修飾詞來明確表達「遮蔽」意圖,避免編譯器警告 CS0114。

情境重現

假設你引用第三方庫的 BaseClass,並衍生出 DerivedClass 實作 TestMethod()。若未來基類也加入同名方法,若無 new 修飾詞,編譯器會警告:

'DerivedClass.TestMethod()' hides inherited member 'BaseClass.TestMethod()'. To make the current method override that implementation, add the override keyword. Otherwise add the new keyword.

正確做法:显式遮蔽

class BaseClass
{
    public void TestMethod()
    {
        Console.WriteLine("BaseClass::TestMethod");
    }
}

class DerivedClass : BaseClass
{
    new public void TestMethod()
    {
        Console.WriteLine("DerivedClass::TestMethod");
    }
}

加上 new 後,編譯器知道這是刻意遮蔽。但注意:若透過基類參考呼叫 ((BaseClass)derived).TestMethod(),仍會執行基類實作——這與 override 多型行為不同。

5.3 類別屬性:封裝資料存取的優雅方式

屬性提供 get/set 存取子,能隱藏內部儲存細節、驗證資料、實作唯讀或唯寫邏輯。

基本語法

public class House
{
    private int m_nSqFeet;  // 後端欄位

    public int SquareFeet
    {
        get { return m_nSqFeet; }
        set { m_nSqFeet = value; }  // value 為隱含參數
    }
}

使用時如同欄位般自然:

House myHouse = new House();
myHouse.SquareFeet = 250;  // 呼叫 set
Console.WriteLine(myHouse.SquareFeet);  // 呼叫 get

進階應用

  • 唯讀屬性:僅提供 get
  • 唯寫屬性:僅提供 set
  • 驗證邏輯:在 set 中檢查範圍、拒絕無效值
  • 延遲初始化:首次存取時才分配資源

5.4 索引子:像陣列一樣存取物件

索引子讓類別支援 obj[index] 語法,底層邏輯由 get/set 定義。

語法結構

public string this[int index]
{
    get { /* 回傳邏輯 */ }
    set { /* 設定邏輯 */ }
}

關鍵點:

  • 使用 this 關鍵字,無自訂名稱
  • 參數至少一個,支援 ref/out
  • 可多載:不同參數型別/數量定義多個索引子
  • 介面實作時可用 InterfaceName.this 區分

實戰範例:DNS 解析器

class ResolveDNS
{
    IPAddress[] m_arrIPs;

    public void Resolve(string host)
    {
        IPHostEntry entry = Dns.GetHostByName(host);
        m_arrIPs = entry.AddressList;
    }

    public IPAddress this[int index]
    {
        get { return m_arrIPs[index]; }
    }

    public int Count => m_arrIPs.Length;
}

// 使用方式
var resolver = new ResolveDNS();
resolver.Resolve("www.microsoft.com");
for (int i = 0; i < resolver.Count; i++)
    Console.WriteLine(resolver[i]);

編譯需參考 System.Net.dll:csc /r:System.Net.dll dnsresolve.cs

5.4 事件:鬆耦合的通知機制

事件讓類別在特定情況發生時通知訂閱者,基於委派實現,支援多播(多訂閱者)。

核心元素

  1. 委派宣告:定義事件處理函式簽章 delegate void EventHandler(string text);
  2. 事件宣告:public event EventHandler TextOut;
  3. 觸發邏輯:檢查非 null 後呼叫 TextOut("訊息");
  4. 訂閱/取消:+= / -= 操作子

完整範例

public delegate void EventHandler(string strText);

class EventSource
{
    public event EventHandler TextOut;

    public void TriggerEvent()
    {
        TextOut?.Invoke("Event triggered");  // C# 6.0 null 條件運算子
    }
}

class TestApp
{
    static void Main()
    {
        var src = new EventSource();
        src.TextOut += CatchEvent;  // 靜態方法訂閱
        src.TriggerEvent();

        src.TextOut -= CatchEvent;  // 取消訂閱
        src.TriggerEvent();

        var app = new TestApp();
        src.TextOut += app.InstanceCatch;  // 實例方法訂閱
        src.TriggerEvent();
    }

    static void CatchEvent(string text) => Console.WriteLine(text);
    void InstanceCatch(string text) => Console.WriteLine("Instance " + text);
}

事件廣泛應用於 ASP.NET、Windows Forms、WPF 等 UI 架構的按鈕點擊、資料繫結變更等場景。

5.5 修飾符總覽

分類修飾符說明
類別修飾符abstract不可實例化,衍生類必須實作所有抽象成員,不可與 sealed 共存
sealed密封類別,禁止繼承,.NET Framework 大量使用
成員修飾符abstract無實作,隱含 virtual,衍生類必須 override
const編譯期常數,不可參考變數
event宣告事件成員
extern外部實作(如 P/Invoke)
override覆寫 virtual/abstract 成員
readonly唯讀欄位,僅能在宣告或建構函式賦值
static屬於類別而非實例,適用欄位、方法、屬性、建構函式
virtual允許衍生類覆寫
存取修飾符public完全公開
protected類別本身與衍生類可存取
private僅類別內部可存取
internal同一組件內公開,跨組件為 private

存取修飾符實戰


internal class Triangle
{
    protected int m_a, m_b, m_c;  // 衍生類可存取

    public Triangle(int a, int b, int c) { ... }

    public virtual double Area() { ... }  // 可覆寫
}

internal class Prism : Triangle
{
    private int m_h;  // 僅本類可存取

    public Prism(int a, int b, int c, int h) : base(a, b, c) { ... }

    public override double Area() { ... }  // 覆寫並呼叫 base.Area()
}

internal 限制組件外不可見,protected 讓衍生類存取基類欄位,private 封裝衍生類自有欄位——良好的封裝層次規劃能降低維護成本。

5.6 本章小結

  • 建構函式/解構函式:物件生命週期的起點與終點,釋放非受控資源建議實作 IDisposable 模式
  • 方法參數:in(預設)、ref、out 三種傳遞模式
  • 多型與遮蔽:virtual/override 實現執行期多型;new 解決版本衝突
  • 屬性與索引子:封裝資料存取、提供陣列式介面
  • 事件與委派:發佈-訂閱模式,實現鬆耦合通知
  • 修飾符體系:類別、成員、存取三大類,精確控制可見性與繼承行為

掌握這些核心機制,才能設計出健壯、可擴充、易維護的 C# 類別庫。

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