在C#中,abstract(抽象)和virtual(虚拟)都是用于实现多态性的关键字,但它们的用法和特性有显著区别:

1. virtual 关键字

  • 用途:用于修饰方法、属性、索引器或事件,允许在派生类中通过override关键字重写
  • 特点
    • 必须有默认实现(方法体)
    • 派生类可以选择重写或不重写
    • 只能在非抽象类中使用
public class Animal
{
    // 虚拟方法,有默认实现
    public virtual void MakeSound()
    {
        Console.WriteLine("动物发出声音");
    }
}

public class Dog : Animal
{
    // 重写基类的虚拟方法
    public override void MakeSound()
    {
        Console.WriteLine("狗汪汪叫");
    }
}

2. abstract 关键字

  • 用途:用于修饰类、方法、属性、索引器或事件,定义必须由派生类实现的成员
  • 特点
    • 抽象方法没有实现(没有方法体),以分号结束
    • 包含抽象成员的类必须声明为抽象类
    • 派生类必须实现所有抽象成员(除非派生类也是抽象类)
    • 抽象类不能被实例化
// 抽象类
public abstract class Shape
{
    // 抽象方法,没有实现
    public abstract double CalculateArea();
}

public class Circle : Shape
{
    public double Radius { get; set; }
    
    // 必须实现基类的抽象方法
    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}

主要区别对比

特性 virtual abstract
实现 必须有实现 没有实现
所在类 非抽象类 必须在抽象类中
派生类要求 可选择重写 必须重写(除非派生类也是抽象类)
适用场景 提供默认行为,允许修改 只定义接口,不提供实现

使用建议

  • 当你希望提供一个默认实现,同时允许派生类修改时,使用virtual
  • 当你希望强制派生类提供自己的实现,而不提供默认行为时,使用abstract
  • 抽象类通常作为其他类的基类,定义共同的接口但不提供完整实现