代码之家  ›  专栏  ›  技术社区  ›  Phate01

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

  •  2
  • Phate01  · 技术社区  · 6 年前

    这似乎是一个非常简单的问题,但很明显我遗漏了一些东西。 我做了一个测试:

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

    我本想找到“object”,但我找到了“A”。 我依靠这种行为来调用基 GetHashCode 在实施的特殊情况下 base.GetHashCode() 我期待着 object 要调用的实现。

    发生了什么?

    4 回复  |  直到 6 年前
        1
  •  2
  •   Alexei Levenkov    6 年前

    base. 符号更改被重写的方法 virtual 方法(如 GetHashCode 在您的样本中- base.GetHashCode() 电话 object.GetHashCode , this.GetHashCode() 电话 A.GetHashCode() ). 基础 也可以用于隐藏基类的方法,但本示例中的情况并非如此。

    自从 GetType 不是虚拟的,没有隐藏然后调用 this.GetType() base.GetType() 行为相同,调用 object.GetType 返回中指定的“当前实例的确切运行时类型” documentation

        2
  •  2
  •   Daniel P    6 年前

    GetType() 始终返回当前类型,即使已调用 base . 要获取基类型,可以执行以下操作:

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

    顺便提一下 base.GetHashCode() 按预期工作。如果你在 A 它将执行 object 实施

        3
  •  2
  •   InBetween    6 年前

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

    object.GetType() 在中实现 object 它将始终返回 运行时类型 它的实例被调用。

    现在,当您调用 Foo 来自任何未实现的给定类 Foo公司 而是从基类型(您的案例)继承它, base.Foo Foo公司 本质上是一样的,因为 Foo公司 基础Foo公司 .

    但是,如果类实现了它自己的 Foo公司 ,打赌它将重写虚拟方法 或隐藏非虚拟方法 调用的方法将不同。不要被其他说明你所看到的行为是由于 GetType 不是虚拟的,那不是真的。

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

    使命感 Foo公司 基础Foo公司 从内部 B 是一样的,从内部调用 C 不是;前者将返回 2 后者 1 .

        4
  •  -1
  •   CDove    6 年前

    Equalsk的评论和帖子( here for brevity )是你需要知道的,但我会更进一步,告诉你为什么要这样做。

    鉴于 class A 仅继承自 System.Object , 并给出 class B class C 是的子类 A类 :

    在B类或C类中 base.GetType().Name 将是A。您希望这样,因为它是在它们继承自A的子类中定义的。

    在A级,你还得A。你为什么不想 object ?

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

    public static void DoStuff(A input)
    {
    }
    

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

    想想 系统对象 作为祖先。如果有人问你来自哪里,你不会回答“美索不达米亚的进化”,你通常只会回答与你的存在相关的血统。这个 对象 类本质上是原始的软泥,所以您不会引用它,除非您试图告诉它应该接受作为参数传递的任何内容,或者不确定要处理的对象类型。

    最后一种情况的一个例子是:

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

    从理论上讲,管道中的一切 对象 . 相反,你可以通过你的“A”类,你想知道“A”,因为你通过了它。即使x属于 对象 .

    BaseType (一个属性)将返回一个类的基,如其他答案中所述。这不会让你 对象 ,但是,除非该类没有显式地从其他对象继承。