Почему 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);
}
}