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

C# 方法與屬性覆寫規則完整解析:virtual、override、new、sealed 關鍵字互動

     編輯:關於C語言

核心規則速查表

基底成員衍生類別宣告結果編譯器訊息
virtualoverride**多型覆寫** (Polymorphic Override)無
virtualnew**隱藏** (Non-polymorphic Hiding)警告 CS0108 (建議加 new)
virtual(無關鍵字)**隱藏** (隱式 new)警告 CS0108
非 virtualoverride**編譯錯誤**錯誤 CS0506:無法覆寫非 virtual 成員
非 virtualnew**隱藏**無 (明確意圖)
非 virtual(無關鍵字)**隱藏**警告 CS0108

關鍵字語意

  • virtual:基底類別**允許**衍生類別覆寫。運行時依實際物件型別動態分派 (動態繫結)。
  • override:衍生類別**實作**覆寫,**必須**配合基底 virtual/abstract/override。
  • new:衍生類別**隱藏**基底同名成員,**靜態繫結** (依宣告型別呼叫)。不具多型性。
  • sealed override:覆寫並**封鎖**進一步覆寫 (終極實作)。
  • abstract:基底類別**強制**衍生類別實作 (隱含 virtual),基底不提供實作。

程式碼示範:覆寫 vs 隱藏的行為差異

using System;

public class Base
{
    public virtual void VirtualMethod() => Console.WriteLine("Base.VirtualMethod");
    public void NonVirtualMethod() => Console.WriteLine("Base.NonVirtualMethod");
}

public class Derived : Base
{
    public override void VirtualMethod() => Console.WriteLine("Derived.VirtualMethod (Override)");

    public new void NonVirtualMethod() => Console.WriteLine("Derived.NonVirtualMethod (New/Hide)");
}

public class Program
{
    public static void Main()
    {
        Derived d = new Derived();
        Base b = d; // 向上轉型

        d.VirtualMethod();  // Derived.VirtualMethod (Override)  ✅ 多型
        b.VirtualMethod();  // Derived.VirtualMethod (Override)  ✅ 多型

        d.NonVirtualMethod(); // Derived.NonVirtualMethod (New)    ✅ 靜態繫結看宣告型別
        b.NonVirtualMethod(); // Base.NonVirtualMethod             ✅ 靜態繫結看宣告型別
    }
}

屬性覆寫規則 (同方法)

public class Animal
{
    public virtual string Name { get; set; } = "Animal";
    public virtual int Legs => 4; // 唯讀屬性
}

public class Dog : Animal
{
    // 覆寫自動屬性:必須重寫 get/set 或僅 get
    public override string Name
    {
        get => base.Name; // 或自訂邏輯
        set => base.Name = value + " (Dog)";
    }

    // 覆寫唯讀屬性
    public override int Legs => 4; // 同樣值,但展示語法

    // 隱藏基底屬性 (非 virtual)
    public new string Color { get; set; } = "Brown";
}

常見陷阱與最佳實踐

1. 忘記 virtual 導致無法覆寫

// 基底類別庫發布者
public class LibraryBase
{
    public void DoWork() { } // ❌ 未標 virtual,第三方無法 override
}

// 第三方使用者
public class MyDerived : LibraryBase
{
    // public override void DoWork() { } // 編譯錯誤 CS0506
    public new void DoWork() { } // 只能隱藏,失去多型
}

**原則**:設計給繼承的類別,**預設將公共/受保護方法標為 virtual** (Java/C# 預設相反,C# 需顯式宣告)。

2. 隱藏破壞多型預期

List list = new() { new Base(), new Derived() };
foreach (var item in list)
{
    item.NonVirtualMethod(); // 全印 "Base.NonVirtualMethod" ❌ 非預期
}

3. new 濫用造成維護噩夢

  • 僅在**必須**改變介面簽章、或第三方基底不可修改時使用。
  • 永遠加上 new 關鍵字消除警告,明確表達意圖。
  • 文件註解說明為何隱藏而非覆寫。

4. 密封覆寫 sealed override

public class Base { public virtual void Save() { } }
public class Middle : Base { public sealed override void Save() { } } // 封鎖
public class Leaf : Middle { /* public override void Save() { } */ } // 編譯錯誤

總結決策樹

  1. 要不要多型?
    → 是 → 基底加 virtual,衍生加 override。
    → 否 → 基底不加 virtual,衍生若需同名用 new (並註解原因)。
  2. 要不要封鎖後續覆寫?
    → 加 sealed override。
  3. 基底是介面/抽象類別?
    → 成員隱含 virtual,衍生**必須** override (抽象) 或可選 override (介面預設實作)。

精準掌握 virtual/override/new/sealed 交互語意,是設計可擴充、行為可預測類別階層的基石。

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