C#virtual关键字

这是为您整理的C# virtual 关键字笔记,采用清晰层级与表格对比,附带面试题与代码示例,可直接复制到任何Markdown编辑器(如Typora、Obsidian、GitHub等)中查看,排版整洁美观。


🧩 C# virtual 关键字 · 完整笔记

一句话总结virtual 是开启多态重写的「钥匙」,没有它,override 寸步难行;若想隐藏,new 来明示。


📌 核心概念

概念 说明
virtual 标记基类方法,允许派生类使用 override 重写,实现运行时多态。
override 在派生类中重写 virtualabstract 方法,基于实际类型调用。
new 在派生类中隐藏基类方法(不要求基类方法有 virtual),基于引用类型调用。
  • 没有 virtual(或 abstract)的方法,子类不能使用 override 重写,否则编译报错(CS0506)。
  • 子类可以使用 new 隐藏父类方法,但不产生多态行为。

🔸 代码示例

public class People
{
    public int ID { get; set; }
    public string Name { get; set; }

    // 普通方法(无 virtual)
    public void Study()
    {
        Console.WriteLine("People Study");
    }

    // 虚方法(允许重写)
    public virtual void StudyVirtual()
    {
        Console.WriteLine("People Study Virtual");
    }
}

public class Student : People
{
    // 隐藏父类普通方法(建议显式使用 new)
    public new void Study()
    {
        Console.WriteLine("Student Study (new)");
    }

    // 重写虚方法
    public override void StudyVirtual()
    {
        Console.WriteLine("Student Study Virtual (override)");
    }
}

🔹 调用差异

People p = new Student();
p.Study();          // 输出 "People Study"      (隐藏,基于引用类型)
p.StudyVirtual();   // 输出 "Student Study Virtual (override)" (多态,基于实际类型)

⚙️ 关键细节

  • virtual 方法可以有默认实现,子类可选择重写或直接继承。
  • 重写时,访问修饰符不能比基类更严格(如基类 protected,子类不能改为 private)。
  • 在重写方法中可使用 base.方法名() 调用基类实现。
  • 属性、索引器、事件也可标记为 virtual 并重写。
  • 静态方法不能标记为 virtual(无实例多态)。

🎯 面试题精选


1. 基类方法不写 virtual,子类能用 override 重写吗?

不能。 编译器会报错 CS0506:“无法重写继承的成员,因为它未标记为 virtual、abstract 或 override”。子类只能通过 new 隐藏该方法,但这不会实现多态。

2. virtual 和 abstract 的区别是什么?
  • virtual:方法有默认实现,子类可以重写(也可以不重写)。
  • abstract:方法没有实现(且只能在抽象类中),子类必须重写(除非子类也是抽象类)。
3. 使用 new 隐藏和 override 重写,在调用上有什么本质不同?

override 实现多态:调用时根据对象实际类型决定方法。
new 隐藏:调用时根据引用类型决定方法,不产生多态行为。

示例:基类引用指向子类对象时,隐藏方法执行基类版本,而重写方法执行子类版本。

4. 在重写的方法中,如何调用基类的实现?

使用 base.方法名()。例如:

public override void StudyVirtual()
{
    base.StudyVirtual();  // 调用基类逻辑
    Console.WriteLine("子类扩展逻辑");
}
5. 属性或索引器可以标记为 virtual 吗?

可以。例如:

public virtual string Name { get; set; }

子类可使用 override 重写 getter/setter 或两者。

6. 如果父类方法没有 virtual,子类又没加 new,会怎样?

编译器会给出警告(CS0108):“隐藏继承的成员。若要使当前成员重写该实现,请添加 override 关键字;否则添加 new 关键字”。程序仍能运行,但行为是隐藏(非多态),且代码意图不清晰,建议显式使用 new

---

📝 总结

场景 关键字 多态? 基类方法要求
派生类重写基类方法 override ✅ 是 virtual / abstract / override
派生类隐藏基类方法 new(可选) ❌ 否 无要求
  • 需要多态 → 基类加 virtual,子类用 override
  • 不需要多态 → 基类不加 virtual,子类用 new 隐藏(或直接定义同名方法,但会有警告)。

笔记结束 · 祝学习愉快 🚀

posted @ 2026-08-15 10:42  春煦景明  阅读(7)  评论(0)    收藏  举报