【问题标题】:why Object.GetType() is not virtual?为什么 Object.GetType() 不是虚拟的?
【发布时间】:2011-03-16 06:19:46
【问题描述】:

取自 MSDN 的代码示例

public class Test {
public static void Main() {
  MyBaseClass myBase = new MyBaseClass();
  MyDerivedClass myDerived = new MyDerivedClass();
  object o = myDerived;
  MyBaseClass b = myDerived;

  Console.WriteLine("mybase: Type is {0}", myBase.GetType());
  Console.WriteLine("myDerived: Type is {0}", myDerived.GetType());
  Console.WriteLine("object o = myDerived: Type is {0}", o.GetType());
  Console.WriteLine("MyBaseClass b = myDerived: Type is {0}", b.GetType());   }}

/*
This code produces the following output.
mybase: Type is MyBaseClass
myDerived: Type is MyDerivedClass
object o = myDerived: Type is MyDerivedClass
MyBaseClass b = myDerived: Type is MyDerivedClass 
*/

那么让 GetType() 虚拟化是否合乎逻辑,至少它可以像虚拟一样工作?谁能解释一下? 和其他问题 NET 框架中是否还有其他具有类似 GetType 行为的方法?

【问题讨论】:

    标签: c# .net architecture


    【解决方案1】:

    修改贪睡博士的answer,以“从头开始创建“类型”对象的实例”:

    public class NotAString
    {
        public new Type GetType()
        {
            return typeof(string);
        }
    }
    

    【讨论】:

      【解决方案2】:

      虽然您不能覆盖 object.GetType() 方法,但您可以使用“new”完全重载它,从而欺骗另一种已知类型。这很有趣,但是我还没有弄清楚如何从头开始创建“Type”对象的实例,所以下面的示例假装是另一种类型。

      public class NotAString
      {
          private string m_RealString = string.Empty;
          public new Type GetType()
          {
              return m_RealString.GetType();
          }
      }
      

      创建此实例后,(new NotAString()).GetType() 确实会返回字符串的类型。

      【讨论】:

      • 几乎所有看到GetType 的东西都有object 的实例,或者至少是他们控制或可以推理的一些基本类型。如果您已经有一个最派生类型的实例,则无需在其上调用GetType。关键是只要有人在object 上使用GetType,他们就可以确定这是系统的实现,而不是任何其他自定义定义。
      【解决方案3】:

      如果 GetType() 是虚拟的,则名为 HumanBeing 的类可以覆盖它并返回一个表示 Robot 的 Type 对象,这称为欺骗,防止这是 CLR 的主要功能之一,称为 Type Safety。

      【讨论】:

        【解决方案4】:

        因为 .Net 框架不希望您重写 GetType() 方法和 spoof 关于类型。

        假设您可以覆盖该方法,除了返回实例的类型之外,您还希望它做什么。并且当您覆盖每个类的方法以返回实例的类型时,您不会违反 DRY。

        【讨论】:

        • 是的。你说得对。但是你可以在派生类中重载这个公共方法))
        • @Arseny:那么它与 Object 类型上定义的 GetType() 不一样。
        • 嗯,不过也有例外。其中之一是动态代理。当您调用动态代理类或接口的 GetType() 时,您将获得“ClassNameProxy”作为返回类型。在这里覆盖 GetType() 方法是有意义的。但是我明白你的意思,这可以通过在类、接口或基类上添加一个特定的方法(比如说 GetImplentationType)来完成。
        • 好吧,看来我必须纠正自己了。我试着做我上面写的。我创建了 2 个实现接口的类,公开一个 GetImplementingType 方法并动态代理它们。在每个实现中,该方法返回一个 typeof(ClassType) 值。好吧,在运行时调用该方法时,它返回 NULL。现在我正在尝试使用抽象基类。
        【解决方案5】:

        GetType 返回对象的实际类型。这使我们能够知道我们真正传递给“我们的”函数的对象是什么。框架的许多方法都需要这个来确定它们自己的功能——在大多数情况下是为了获取这个类的属性。 如果框架失去确定对象真实类型的可能性,对象也会失去这种类型

        如果您想知道在您的方法范围内使用的类型 - 您声明或由编译器选择的类型 - 您可以添加一个非常简单的扩展方法:

        public static Type GetCurrentType<T>(this T obj)
        {
            return typeof(T);
        }
        
        public static void Main()
        {
          MyBaseClass myBase = new MyBaseClass();
          MyDerivedClass myDerived = new MyDerivedClass();
          object o = myDerived;
          MyBaseClass b = myDerived;
        
          Console.WriteLine("mybase: Type is {0}", myBase.GetCurrentType());
          Console.WriteLine("myDerived: Type is {0}", myDerived.GetCurrentType());
          Console.WriteLine("object o = myDerived: Type is {0}", o.GetCurrentType());
          Console.WriteLine("MyBaseClass b = myDerived: Type is {0}", b.GetCurrentType());
        }
        
        /*
        This code produces the following output.
        mybase: Type is ValidatorTest.MyBaseClass
        myDerived: Type is ValidatorTest.MyDerivedClass
        object o = myDerived: Type is System.Object
        MyBaseClass b = myDerived: Type is ValidatorTest.MyBaseClass
        */
        

        【讨论】:

          猜你喜欢
          • 2020-04-13
          • 2011-10-29
          • 1970-01-01
          • 2015-11-12
          • 2013-04-08
          • 2018-12-19
          • 1970-01-01
          • 2014-03-31
          相关资源
          最近更新 更多