ZetCode

C# override 修饰符

最后修改于 2023 年 7 月 5 日

在本文中,我们将展示如何在 C# 中使用 override 修饰符。

在 C# 中,需要使用 override 修饰符来扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现。

C# override 虚拟方法

Object 是 C# 类型系统的根。它支持所有类并为派生类提供底层服务。

Object.ToString 返回一个表示当前对象的字符串。该方法的默认实现返回对象类型的完全限定名。

public virtual string? ToString();

ToString 方法具有 virtual 修饰符。

通常的做法是重写 Object.ToString 方法,以提供我们自定义对象的人工可读的表示形式。

Program.cs
var u = new User("John Doe", "gardener");
Console.WriteLine(u);

class User
{
    public User(string name, string occupation)
    {
        this.Name = name;
        this.Occupation = occupation;
    }

    public string Name { get; set; }
    public string Occupation { get; set; }

    public override string ToString()
    {
        return $"{this.Name} is a {this.Occupation}";
    }
}

在该程序中,我们创建了自己的 Object.ToString 方法的实现。

var u = new User("John Doe", "gardener");
Console.WriteLine(u);

当我们把 user 实例传递给 Console.WriteLine 方法时,ToString 方法会被调用。

public override string ToString()
{
    return $"{this.Name} is a {this.Occupation}";
}

我们使用 override 关键字来重写该方法的默认实现,该方法被声明为 virtual

$ dotnet run
User { John Doe gardener }
User { Roger Roe driver }

C# override 抽象方法

抽象类为子类提供了一个通用的定义。抽象方法必须在子类中被重写。

Program.cs
var c = new Circle(12, 45, 22);

Console.WriteLine(c);
Console.WriteLine($"Area of circle: {c.Area()}");
Console.WriteLine(c.GetCoordinates());

abstract class Drawing
{
    protected int x = 0;
    protected int y = 0;

    public abstract double Area();

    public string GetCoordinates()
    {
        return $"x: {x}, y: {y}";
    }
}

class Circle : Drawing
{
    private int r;

    public Circle(int x, int y, int r)
    {
        this.x = x;
        this.y = y;
        this.r = r;
    }

    public override double Area()
    {
        return this.r * this.r * Math.PI;
    }

    public override string ToString()
    {
        return $"Circle at x: {x}, y: {x}, radius: {r}";
    }
}

我们有一个抽象的基类 Drawing。该类定义了两个成员字段,定义了一个方法,并声明了一个方法。

public abstract double Area();

Area 方法是抽象的,因此,它必须在具体的子类中被重写。

public override double Area()
{
    return this.r * this.r * Math.PI;
}

Circle 类中,我们重写了 Area 方法并提供了它的实现。

$ dotnet run
Circle at x: 12, y: 12, radius: 22
Area of circle: 1520.53084433746
x: 12, y: 45

C# override vs new

使用 new 关键字,我们可以显式地隐藏一个被继承的成员。 当我们隐藏一个继承的成员时,成员的派生版本会替换基类版本。 我们仍然可以通过向上转型到基类来访问原始方法。

override 修饰符修改原始方法(只有一个方法),而 new 修饰符创建一个隐藏原始方法的新方法(有两个方法)。

Program.cs
Base[] objs = { new Base(), new Derived(), new Base() };

Console.WriteLine("-------------------------");
Console.WriteLine("Info/override");

Derived d = new Derived();
d.Info();
((Base)d).Info();

Base b = new Base();
b.Info();

Console.WriteLine("------------");

foreach (Base obj in objs)
{
    obj.Info();
}

Console.WriteLine("-------------------------");
Console.WriteLine("Info2/new");

Derived d2 = new Derived();
d2.Info2();
((Base)d).Info2();

Base b2 = new Base();
b2.Info2();

Console.WriteLine("------------");

foreach (Base obj in objs)
{
    obj.Info2();
}

class Base
{
    public virtual void Info()
    {
        Console.WriteLine("Base class");
    }

    public virtual void Info2()
    {
        Console.WriteLine("Base class");
    }
}

class Derived : Base
{
    public override void Info()
    {
        Console.WriteLine("Derived class");
    }

    public new void Info2()
    {
        Console.WriteLine("Derived class");
    }
}

我们有一个 Base 类和一个 Derived 类。 有两个方法:InfoInfo2。 第一个在 Derived 中使用 override 关键字,第二个使用 new 关键字。

$ dotnet run
-------------------------
Info/override
Derived class
Derived class
Base class
------------
Base class
Derived class
Base class
-------------------------
Info2/new
Derived class
Base class
Base class
------------
Base class
Base class
Base class

来源

override 修饰符 - 语言参考

在本文中,我们介绍了 C# override 修饰符。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直撰写编程文章。 到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程