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

C# 虛擬方法完整解析:virtual、override、new、多型行為與編譯期vs執行期綁定

     編輯:關於C語言

前言

virtual 與 override 是 C# 實現執行期多型的核心關鍵字。本文詳細解析虛擬方法語法規則、與非虛擬方法行為差異、new 隱藏 vs override 覆寫、編譯期靜態綁定 vs 執行期動態綁定。

一、虛擬方法語法規則

  • 基類方法加 virtual 修飾符
  • 衍生類用 override 覆寫
  • 限制:virtual 不能與 static、abstract、override 共存
  • 限制:override 不能與 new、static、virtual 共存
  • 存取修飾符必須一致(或更寬鬆)

二、虛擬 vs 非虛擬:核心行為差異

三、程式碼範例:虛擬與非虛擬並存

using System;

class A
{
    public void F() { Console.WriteLine("A.F"); }           // 非虛擬
    public virtual void G() { Console.WriteLine("A.G"); }   // 虛擬
}

class B : A
{
    public new void F() { Console.WriteLine("B.F"); }       // 隱藏基類 F
    public override void G() { Console.WriteLine("B.G"); }  // 覆寫基類 G
}

class Test
{
    static void Main()
    {
        B b = new B();
        A a = b; // 基類參考指向衍生類實例
        
        a.F(); // 輸出:A.F (靜態綁定,a 編譯期型別為 A)
        b.F(); // 輸出:B.F (靜態綁定,b 編譯期型別為 B)
        a.G(); // 輸出:B.G (動態綁定,實際型別為 B)
        b.G(); // 輸出:B.G (動態綁定)
    }
}

輸出結果

A.F
B.F
B.G
B.G

關鍵解析

  • a.F():編譯期型別 A,非虛擬方法 → 靜態綁定 A.F
  • b.F():編譯期型別 B,new 隱藏 → 靜態綁定 B.F
  • a.G():編譯期型別 A,但 執行期型別為 B,虛擬方法 → 動態綁定 B.G
  • 這就是多型:相同呼叫語法,依實際物件型別執行不同實作

四、new 隱藏 vs override 覆寫:深度比較

特性非虛擬方法虛擬方法
呼叫綁定時機編譯期(靜態綁定)執行期(動態綁定)
衍生類改變行為用 new 隱藏用 override 覆寫
透過基類參考呼叫永遠呼叫基類實作呼叫衍生類實際型別的實作
效能略快(直接呼叫)虛擬表查找(極微小開銷)

五、編譯期 vs 執行期綁定圖解


// 編譯期:靜態型別決定
A a = new B();  // a 的靜態型別 = A,動態型別 = B

// 非虛擬:編譯期綁定
a.F(); // 看靜態型別 A → A.F

// 虛擬:執行期綁定
a.G(); // 看動態型別 B → B.G (透過虛擬表 vtable 查找)

虛擬表機制簡述

  1. 每個含虛擬方法的類別有一個 虛擬方法表
  2. 表中儲存各虛擬方法的實際進入點位址
  3. 每個實例物件內部包含指向其類別虛擬表的指標(__vptr)
  4. 呼叫虛擬方法時:obj->vptr[vtable_index] 間接跳轉

六、最佳實務建議

  • 預設非虛擬:除非明確設計為可擴充,否則不加 virtual
  • 覆寫必加 override:編譯器驗證簽章一致,防止拼錯
  • 刻意隱藏加 new:消除警告,明確語意
  • 密封類別用 sealed:禁止繼承,間接禁止覆寫
  • 密封方法用 sealed override:允許繼承類別但禁止進一步覆寫該方法

七、總結

虛擬方法是 C# 執行期多型的基石:

  • virtual 宣告「此方法可被覆寫」
  • override 實作「衍生類的具體行為」
  • 動態綁定:透過基類參考呼叫虛擬方法,實際執行衍生類實作
  • new 僅是編譯期隱藏,不具多型能力

理解靜態型別 vs 動態型別、編譯期綁定 vs 執行期綁定,是掌握 C# 物件導向精髓的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性new 隱藏override 覆寫
基類方法需求無需 virtual必須 virtual/abstract/override
多型行為無(靜態綁定)有(動態綁定)
基類參考呼叫呼叫基類方法呼叫衍生類方法
編譯器警告若未加 new 會警告 CS0108無警告(正確覆寫)
適用場景非虛擬方法、第三方庫、刻意中斷多型設計為可擴充的虛擬方法