2010-07-15 21 views
15

ejemplo de código tomado de MSDN¿por qué Object.GetType() no es virtual?

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

Por lo tanto sería lógico hacer GetType() virtual en menos funciona como virtual? ¿Alguien puede explicar eso? Y otra pregunta ¿Hay algún otro método en el marco NET que tenga un comportamiento similar a GetType?

Respuesta

16

porque .NET Framework no quiere que anule el método GetType() y spoof sobre el tipo.

supongamos que puede anular el método, qué otra cosa le gustaría que hiciera, aparte de devolver el tipo de la instancia. y cuando anula el método para que cada una de sus clases devuelva el tipo de instancia, ¿no violará DRY entonces?

+3

y razonablemente de manera! –

+0

sí. tienes razón. pero puede sobrecargar este método público en la clase derivada)) – Arseny

+2

@Arseny: Entonces no es lo mismo que GetType() como se define en el tipo de objeto. –

2

GetType devuelve el tipo real del objeto. Esto nos permite saber qué objeto realmente pasamos a 'nuestra' función. Muchos métodos del marco necesitan esto para determinar su propia funcionalidad, en la mayoría de los casos para obtener los Atributos de esta clase. Si el Framework perdería la posibilidad de determinar el tipo real de un objeto, el objeto también perdería este tipo.

Si te gusta conocer el tipo utilizado dentro de su ámbito de método - el tipo que declaró o fue recogido por el compilador - puede agregar una bastante simple método de extensión:

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

Si GetType() era virtual, una la clase llamada HumanBeing puede anularla y devolver un objeto Tipo que represente Robot que se denomina suplantación y evitar que esta sea una de las características principales de CLR llamada Tipo de seguridad.

2

Si bien es cierto que no puede anular el método object.GetType(), puede usar "new" para sobrecargarlo completamente, falsificando así otro tipo conocido. Esto es interesante, sin embargo, no he descubierto cómo crear una instancia del objeto "Tipo" desde cero, por lo que el siguiente ejemplo pretende ser de otro tipo.

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

Después de crear una instancia de este, (nueva NotAString()). GetType(), de hecho va a devolver el tipo de una cadena.

+1

Por casi todo lo que se ve en 'GetType' tiene una instancia de 'objeto', o al menos algún tipo de base que ellos controlan o pueden razonar. Si ya tiene una instancia del tipo más derivado, no es necesario llamar a 'GetType' en él. El punto es que mientras alguien use 'GetType' en un' objeto' pueden estar seguros de que es la implementación del sistema, no cualquier otra definición personalizada. – Servy

0

Modificación del Dr. answer Pausa, con el fin de "crear una instancia del 'tipo' objeto desde cero":

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