Почему Object.GetType() не является виртуальным?

образец кода, взятый из 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?

Ответы

Ответ 1

потому что .Net framework не хочет, чтобы вы переопределяли метод GetType() и spoof о типе.

Предположим, вы можете переопределить метод, что еще вы хотели бы сделать, кроме как вернуть тип экземпляра. и когда вы переопределите метод для каждого из ваших классов, чтобы вернуть тип экземпляра, не нарушите ли вы DRY тогда.

Ответ 2

GetType возвращает фактический тип объекта. Это позволяет нам узнать, какой объект мы действительно передали "нашей" функции. Многие методы структуры нуждаются в этом, чтобы определить свою собственную функциональность - в большинстве случаев получить Атрибуты этого класса. Если Framework потеряет возможность определить реальный тип объекта, объект также потеряет этот тип.

Если вам нравится знать тип, используемый в области вашего метода - тип, который вы объявили или был выбран компилятором, вы можете добавить довольно простой метод расширения:

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 может переопределить его и вернуть объект Type, представляющий Robot, который называется spoofing и предотвращает это, является одной из основных функций CLR, называемой Safety Type.

Ответ 4

Хотя верно, что вы не можете переопределить метод object.GetType(), вы можете использовать "новое", чтобы полностью перегрузить его, тем самым спуская еще один известный тип. Это интересно, однако, я не понял, как создать экземпляр объекта "Тип" с нуля, поэтому приведенный ниже пример делает вид, что он другой тип.

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

После создания экземпляра этого (new NotAString()) GetType(), действительно вернет тип для строки.

Ответ 5

Модификация Dr Snooze answer, чтобы "создать экземпляр объекта" Тип "с нуля":

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