为什么 'base' 对象的类型是我的具体类型?

Why is the type of 'base' object my concrete type?

这似乎是一个非常简单的问题,但显然我遗漏了什么。 我做了一个测试:

class A
{
    public override int GetHashCode()
    {
        Console.WriteLine(base.GetType().Name);
        return 0;
    }
}

我原以为会找到 'object',但我找到了 'A'。 我依靠这种行为来调用基础 GetHashCode 是具有实现的特殊情况,调用 base.GetHashCode() 并且我期望调用 object 实现。

怎么了?

base. 符号更改为重写的 virtual 方法调用的方法(如示例中的 GetHashCode - base.GetHashCode() 调用 object.GetHashCodethis.GetHashCode() 调用 A.GetHashCode())。 base.也可以用隐藏基数class'的方法,但在本例中不是这样。

因为 GetType 不是虚拟的并且没有隐藏然后调用 this.GetType()base.GetType() 行为相同并调用 object.GetType 其中 returns "The exact runtime type of the current instance" 在 documentation

中指定

GetType() 总是 returns 当前类型,即使在 base 上调用也是如此。要获取基本类型,您可以这样做:

class A
{
    public override int GetHashCode()
    {
        Console.WriteLine(this.GetType().BaseType.Name);
        return 0;
    }
}

顺便说一句 base.GetHashCode() 按预期工作。如果您在 A 内调用它,它将执行 object 实现。

Equalsk 的评论和 post (here for brevity) 是您需要了解的内容,但我会更进一步,告诉您为什么要这样。

鉴于 class A 仅继承自 System.Object, 鉴于 class Bclass Cclass A 的子 class:

在 class B 或 C 中,base.GetType().Name 将是 A。您预料到了这一点,因为它在从 A 继承的子class 中定义。

在classA中,你仍然得到A。你为什么不想要object

答案很简单。假设我写了一个这样的方法:

public static void DoStuff(A input)
{
}

我可以发送 DoStuff(input)input 是 classes A、B 或 C。这是因为它们的 base 类型是 A。这是可取的。我们不想隐含地(并且令人困惑地)从采用其导数的方法中排除 class A ;如果我们这样做了,我们希望 A 是一个不可实例化的接口。

System.Object 视为祖先。如果有人问你从哪里来,你不会回答 "Evolution in Mesopotamia",你通常只会说出与你的存在相关的血统。 object class 本质上是原始软泥,所以你不会引用它,除非你试图告诉它应该接受它作为参数传递的任何东西,或者不确定你将要传递的对象类型处理。

最后一个例子是这样的:

public void DoStuffAgain(object x)
{
        Messagebox.Show(x.GetType().Name);
}

理论上,管道中的所有内容都会 object。相反,您可能会将此传递给您的 "A" class,并且您想知道 "A" 因为这就是您传递给它的内容。即使 x 的类型为 object.

也是如此 如其他答案所述,

BaseType (a 属性) 将 return 作为 class 的基础。但是,这不会将您带到 object,除非 class 没有明确地从其他东西继承。

你在这里混淆了两个截然不同的东西。一个是调用什么方法实现,另一个是对象的运行时类型类型是什么。

object.GetType()object 中实现,它总是 return 它所调用实例的 运行时类型

现在,当你从任何给定的 class 调用方法 Foo 时,它没有实现 Foo 而是从基类型(你的情况)继承它,base.FooFoo 本质上是同一件事,因为唯一存在的 Foobase.Foo.

但是,如果 class 实现它自己的 Foo,我敢打赌它会覆盖虚拟方法 或隐藏非虚拟方法 调用的方法将是不同的。不要被其他答案弄糊涂了,其他答案指出您看到的行为是由于 GetType 不是虚拟的,这是不正确的。

class A { int Foo() => 1;}
class B { }
class C { new int Foo() => 2; }

B内部调用Foobase.Foo是一样的,从C内部调用则不同;前者会 return 2 后者 1.