为什么Object.GetType()不是虚方法?

19

来自 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()方法定义为虚方法是否合理?至少这样能够使它的行为表现得像虚方法一样。还有其他类似于GetType()方法的行为的.NET Framework方法吗?

5个回答

18

由于.Net框架不希望您覆盖GetType()方法并伪造类型,因此。

假设您可以覆盖该方法,除了返回实例的类型之外,您还想让它做什么呢?当您为每个类覆盖该方法以返回实例的类型时,难道不会违反DRY原则吗?


是的,你是对的。但你可以在派生类中重载这个公共方法)) - Arseny
2
@Arseny:那么它就不是在Object类型上定义的GetType()。 - this. __curious_geek
好的,虽然有例外。其中之一是动态代理。当您调用动态代理类或接口的GetType()时,将返回“ClassNameProxy”作为返回类型。在这种情况下,重写GetType()方法是有意义的。但是我理解您的观点,可以通过在类、接口或基类上添加特定方法(比如说GetImplentationType)来实现。 - Hellraiser
好的,看来我需要纠正一下自己。我尝试按照上面所写的做法去做。我创建了两个实现接口的类,并公开了一个GetImplementingType方法并对它们进行了动态代理。在每个实现中,该方法返回了typeof(ClassType)值。但是,当在运行时调用该方法时,它返回了NULL。现在我正在尝试使用抽象基类。 - Hellraiser

4

虽然不能覆盖object.GetType()方法,但可以使用"new"完全重载它,从而伪装成另一个已知类型。这很有趣,但是我还没有想出如何从头创建“Type”对象实例,因此下面的示例假装是另一种类型。

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

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

3
几乎所有使用 GetType 的东西都是 object 的实例,或者至少是一些他们控制或可以推理的基本类型。如果已经有了最派生类型的实例,则不需要在其上调用 GetType。关键是只要某人在 object 上使用 GetType,他们就可以确定这是系统的实现,而不是任何其他自定义定义。 - Servy

3

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
*/

3
如果 GetType() 是虚拟的,一个名为 HumanBeing 的类可以重写它并返回表示 Robot 的 Type 对象,这被称为欺骗,而防止这种情况发生是 CLR 的主要特性之一,称为类型安全。

0
修改Dr Snooze的答案,以便“从头开始创建“Type”对象的实例”:
public class NotAString
{
    public new Type GetType()
    {
        return typeof(string);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接