为什么 '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.GetHashCode
、this.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 B
和 class C
是 class 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.Foo
或 Foo
本质上是同一件事,因为唯一存在的 Foo
是 base.Foo
.
但是,如果 class 实现它自己的 Foo
,我敢打赌它会覆盖虚拟方法 或隐藏非虚拟方法 调用的方法将是不同的。不要被其他答案弄糊涂了,其他答案指出您看到的行为是由于 GetType
不是虚拟的,这是不正确的。
class A { int Foo() => 1;}
class B { }
class C { new int Foo() => 2; }
从B
内部调用Foo
或base.Foo
是一样的,从C
内部调用则不同;前者会 return 2
后者 1
.
这似乎是一个非常简单的问题,但显然我遗漏了什么。 我做了一个测试:
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.GetHashCode
、this.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 B
和 class C
是 class 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.Foo
或 Foo
本质上是同一件事,因为唯一存在的 Foo
是 base.Foo
.
但是,如果 class 实现它自己的 Foo
,我敢打赌它会覆盖虚拟方法 或隐藏非虚拟方法 调用的方法将是不同的。不要被其他答案弄糊涂了,其他答案指出您看到的行为是由于 GetType
不是虚拟的,这是不正确的。
class A { int Foo() => 1;}
class B { }
class C { new int Foo() => 2; }
从B
内部调用Foo
或base.Foo
是一样的,从C
内部调用则不同;前者会 return 2
后者 1
.