2010-02-01 7 views
10

He descubierto que si ejecuto las siguientes líneas de código.¿Por qué llamar a algunas funciones de la clase Object, en una instancia de tipo primitivo, necesita boxeo?

int i = 7; 
i.GetHashCode(); //where GetHashCode() is the derived 
       //function from System.Object 

Sin el boxeo está hecho, pero si llamo i.GetType() (otra función derivada de System.Object) en lugar de GetHashCode(), se requerirá un boxeo para llamar GetType(), ¿Por qué no es posible llamar GetType() en la instancia de tipo primitivo directamente , sin boxeo, mientras que es posible llamar al GetHashCode() sin boxeo?

+0

me sorprende que 'GetType' se llama en absoluto. Como C# está tipado estáticamente y una * variable de tipo de valor * no puede contener nada más que objetos del tipo de valor, el tipo es determinable en el tipo de compilación (es 'typeof (int)'). Entonces, ¿por qué emitir una llamada en tiempo de ejecución? –

+0

Correcto, pero la intención aquí es aclarar eso, por qué las cosas no funcionan como deberían. – waheed

Respuesta

8

La clave aquí es que GetType() no es virtual y no se puede anular. Como una estructura es efectivamente sealed, los métodos no pueden anularse más que la estructura, por lo que el tiempo de ejecución y el compilador pueden tratar los métodos de estructura que se han reemplazado como llamadas estáticas.

Si se escribe una estructura (raro) que debe reemplazar todos los métodos como ToString(), Equals(), GetHashCode() exactamente por esta razón. Si no lo hace, debe boxear. Sin embargo, GetType()no se puede anularse, por lo tanto, necesita el boxeo.

En realidad, esto lleva a algunos casos de borde impares con Nullable<T> y el boxeo, ya que un vacío Nullable<T> cajas a null, por lo que:

int i = obj.GetHashCode(); // fine 
Type t = obj.GetType(); // boom 
2

Creo que la razón es que GetHashCode se implementa en System.Int32 directamente, se llama a System.Int32 :: GetHashCode(). No es necesario marcar si llama a una función miembro conocida en un tipo de valor.

+0

¿Entonces las funciones que no están implementadas en System.Int32 directamente, como las de System.ValueType o System.Object no se pueden llamar directamente? – waheed

+0

Eso es lo que ildasm me ha mostrado hasta ahora ... Cuando llama a la función de clase base (como System.Object :: GetType() se necesita boxeo. Si llama a una función implementada en el objeto de valor, entonces no hay boxeo es nessecary ... – Arve

Cuestiones relacionadas