【问题标题】:Why does this sometimes mean base?为什么这有时意味着基础?
【发布时间】:2026-02-02 00:15:01
【问题描述】:

给定

public class Animal
{
    public Animal()
    {
        Console.WriteLine("Animal constructor called");
    }
    public virtual void Speak()
    {
        Console.WriteLine("animal speaks");
    }
}

public class Dog: Animal
{
    public Dog()
    {
        Console.WriteLine("Dog constructor called");
        this.Speak();
    }
    public override void Speak()
    {
        Console.WriteLine("dog speaks");
  base.Speak();
    }
}

this.Speak() 呼叫Dog.Speak()。从狗中删除Speak(),然后突然this.Speak() 调用Animal.Speak()。为什么this 会这样?换句话说,为什么this 表示basethis

对我来说,明确调用base.Speak() 更有意义。特别是当 speak 不是虚拟的时,令人惊讶的是,当 virtual 被删除时,Speak() 仍然被调用。我从 OO 意义上理解 IS-A 关系,但我无法解决 C# 中的这个特定问题。当人们编写神级用户界面时(几乎每个企业都这样做),这变得特别烦人。当我应该查看“base”时,我正在“this”中寻找“Speak()”。

【问题讨论】:

标签: c#


【解决方案1】:

子类自动从其基类继承行为。如果除了从Animal 继承Dog 之外什么都不做,那么this.Speak()base.Speak() 都引用在Animal 中实现的Speak() 版本。

如果Dog 覆盖Speak(),则开始发生特殊情况。除非Speak()virtual,否则这是不可能的。 (virtual 关键字不控制继承,它控制覆盖。)

只有当Dog 覆盖Speak()base.Speak() 才会做一些特别的事情:在这种情况下,调用Speak()(或this.Speak())将执行Dog 的实现,因为它overrides @ 987654339@的实现。这就是base 有用的地方:它允许您通过指定要执行基类的实现而不是覆盖来绕过此行为。

这种风格的一个常见用途是在构造函数中。例如:

public class Animal
{
    private readonly string _name;
    public Animal() : this("Animal") { }
    protected Animal(string name) { _name = name; }
    public void Speak() { Console.WriteLine(_name + " speaks"); }
}

public class NamedAnimal : Animal
{
    public NamedAnimal(name) : base(name) { }
}

// usage:
(new Animal()).Speak();  // prints "Animal speaks"
(new NamedAnimal("Dog")).Speak();     // prints "Dog speaks"

在此示例中,NamedAnimal 无法访问 _name 字段,但它仍然可以通过调用基类的构造函数来间接设置它。但基类的签名与基类中的签名相同,因此必须使用base 指定。

对于非构造函数,它还有助于处理其他方式无法访问的行为。例如,如果Animal.Speak 是虚拟的,那么我们可以使用覆盖来附加行为而不是简单地替换它:

public class NamedAnimal : Animal
{
    public NamedAnimal(name) : base(name) { }
    public override Speak()
    {
        Console.Write("The animal named ");
        base.Speak();
    }
}

// usage:
(new NamedAnimal("Dog")).Speak();  // Writes "The animal named Dog speaks"

【讨论】:

    【解决方案2】:

    不是这样的。如果dog一个 speak 方法,那么它就是基本方法的一个override。如果不存在,则调用 dogInstance.Speak 将在 Dog 的任何基类中查找 Speak() 方法。

    【讨论】:

      【解决方案3】:

      这是 OO 的基本点之一。如果您不提供覆盖,则使用父方法。

      此外,即使您删除了virtual,也会调用Dog.Speak,因为您没有以多态方式访问this

      【讨论】:

        【解决方案4】:

        this 表示this,仅此而已。

        就在您的第一个示例中,您有一个 Speak(..) 函数的覆盖,所以 this 调用那个函数。

        在第二种情况下,相反,没有任何覆盖,因此它“爬上”派生树并选择第一个合适的函数。在你的情况下,一个是Animal 中的Speak(..)

        【讨论】:

          【解决方案5】:

          VB.Net 使用 MyClass 关键字来做到这一点(与 My 关键字相反,它相当于 C# 中的 this)。不幸的是,C# 中没有 MyClass 等效关键字。

          【讨论】: