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

C# 覆寫與隱藏基類方法差異深度解析:override vs new 關鍵字實戰

     編輯:關於C語言

核心差異:多型 vs 靜態繫結

關鍵字機制基類參考指向衍生物件時衍生類別參考指向衍生物件時
override虛擬方法多型(動態繫結)呼叫衍生類別實作呼叫衍生類別實作
new方法隱藏(靜態繫結)呼叫基類實作呼叫衍生類別實作

程式碼示範


// 基類
public class Customer {
    public virtual string GetFunnyString() {
        return "Plain ordinary customer. Kaark!";
    }
}

// 衍生類別:使用 override
public class Nevermore60Customer : Customer {
    public override string GetFunnyString() {
        return "Nevermore60.Nevermore!";
    }
}

// 衍生類別:使用 new(隱藏)
public class HiddenCustomer : Customer {
    public new string GetFunnyString() {
        return "Hidden version!";
    }
}

行為驗證


Customer c1 = new Nevermore60Customer();
Nevermore60Customer c2 = new Nevermore60Customer();

Console.WriteLine(c1.GetFunnyString()); // 輸出: Nevermore60.Nevermore!  (多型生效)
Console.WriteLine(c2.GetFunnyString()); // 輸出: Nevermore60.Nevermore!

// --- 隱藏版本 ---
Customer h1 = new HiddenCustomer();
HiddenCustomer h2 = new HiddenCustomer();

Console.WriteLine(h1.GetFunnyString()); // 輸出: Plain ordinary customer. Kaark!  (基類版本!)
Console.WriteLine(h2.GetFunnyString()); // 輸出: Hidden version!

IL 層面解析

  • override:衍生類別方法標記 `virtual final`,基類方法為 `virtual`。呼叫端發 `callvirt` 指令,執行期依物件實際型別分派。
  • new:衍生類別方法為非虛擬(預設 `non-virtual`),基類方法不變。呼叫端發 `call` 指令,編譯期依**宣告型別**繫結。

編譯器警告 CS0108

使用 `new` 隱藏繼承成員時,編譯器會發出警告:
'HiddenCustomer.GetFunnyString()' hides inherited member 'Customer.GetFunnyString()'. Use the new keyword if hiding was intended.
這提醒開發者確認是否為刻意隱藏,避免誤用。

最佳實踐指南

  1. 預設使用 override:符合里氏替換原則,保持多型一致性。
  2. 僅在必要時用 new:例如第三方庫基類非虛擬方法需同名擴展、或刻意中斷多型行為。
  3. 加上 sealed override:防止進一步衍生類別再次覆寫,鎖定行為。
  4. 文件化意圖:若用 `new`,在 XML 註解說明為何不使用 `override`。

進階:介面實作的隱式/顯式實作


public interface IGreeter { void Greet(); }

public class Base : IGreeter {
    public virtual void Greet() => Console.WriteLine("Base");
}

public class Derived : Base, IGreeter {
    public override void Greet() => Console.WriteLine("Derived Override");
    // 顯式介面實作(隱藏)
    void IGreeter.Greet() => Console.WriteLine("Explicit Interface");
}

顯式介面實作同樣屬於「隱藏」語意:透過 `Base` 或 `Derived` 參考呼叫 `Greet()` 走多型;轉型為 `IGreeter` 才呼叫顯式實作。

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