C#virtual关键字
这是为您整理的C# virtual 关键字笔记,采用清晰层级与表格对比,附带面试题与代码示例,可直接复制到任何Markdown编辑器(如Typora、Obsidian、GitHub等)中查看,排版整洁美观。
🧩 C# virtual 关键字 · 完整笔记
一句话总结:
virtual是开启多态重写的「钥匙」,没有它,override寸步难行;若想隐藏,new来明示。
📌 核心概念
| 概念 | 说明 |
|---|---|
virtual |
标记基类方法,允许派生类使用 override 重写,实现运行时多态。 |
override |
在派生类中重写 virtual 或 abstract 方法,基于实际类型调用。 |
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隐藏(或直接定义同名方法,但会有警告)。
笔记结束 · 祝学习愉快 🚀

浙公网安备 33010602011771号