2010-07-23 14 views
17

Esta semana he estado trabajando en algún código basado en la reflexión, y durante la prueba unitaria encontré una condición inesperada: los punteros son tipos de referencia. El código de C# typeof(int).MakePointerType().IsClass devuelve true.¿Por qué son tipos de referencia de punteros?

Comprobé en mi Estándar de CLI anotado recién llegado, y efectivamente, los punteros están claramente definidos como tipos de referencia.

Esto me sorprendió, viniendo de un fondo de C++. Acabo de asumir que los punteros serían tipos de valor.

¿Hay alguna razón en particular por la que los tipos de puntero sean tipos de referencia y no tipos de valores?

actualización (clarificación)

Cuando se habla de punteros y referencias, las cosas a menudo a confusión en cuanto a la "puntero" y "pointee". Así que aquí hay alguna aclaración.

Tipos pueden ser tipos de referencia o los tipos de valor, pero variables de son un poco diferentes. (Lo siento, no he tenido la oportunidad de leer a través de mi CLI estándar, por lo que la terminología y los conceptos estar equivocado - me corrija, por favor!)

Teniendo en cuenta este código (conceptos variables locales de los tipos de referencia):

var x = new MyClass(); 
var y = x; 

Las variables x y y no son en realidad hacen referencia a tipos, pero son referencias a un objeto que es un tipo de referencia (MyClass es un tipo de referencia). En otras palabras, x y y no son instancias del tipo de referencia; solo se refieren a una instancia de tipo de referencia.

Teniendo en cuenta este código (conceptos variables locales de los tipos de valor):

var x = 13; 
var y = x; 

Las variables x y y son los tipos de valor instancias (o al menos actuar como si fueran casos).

Así que llegamos a este código:

var i = 13; 
var x = &i; 
var y = x; 

Si el puntero tipo es un tipo referencia, entonces esto es como yo interpreto la declaración x = &i:

  1. Una instancia de tipo int* se crea, apuntando a i.
  2. Dado que los punteros son tipos de referencia, esta instancia se crea en el montón (suponiendo que todos los tipos de referencia se colocan en el montón, un detalle de implementación).
  3. x es una referencia a esta instancia de puntero.
  4. La instancia del puntero eventualmente se recolectará como basura, al igual que otros tipos de referencia.
  5. Cuando se ejecuta y = x, se copia la referencia.Tanto y como x se refieren a la misma instancia del objeto de puntero.

Quizás estoy completamente equivocado en esta interpretación.

Viniendo de experiencia en C++, tendría más sentido para mí para los punteros sean los tipos de valor, por lo que la declaración x = &i se acaba de asignar la dirección de i a la instancia del tipo de valor x y y = x copias que se ocupan de valor en y. No se creará ningún "objeto de puntero" en el montón.

+2

De los documentos de CLR en Type.IsClass - 'Obtiene un valor que indica si el tipo es una clase; es decir, no es un tipo de valor o interfaz '. Técnicamente, un tipo de puntero no hereda de 'System.Object', por lo que no es un objeto, tipo de valor o interfaz, sino que es una clase de acuerdo con los documentos. – thecoop

Respuesta

2

No he visto una respuesta completa, así que estoy cerrando esta pregunta por ahora.

Estoy obligado a concluir: punteros (por ejemplo, int *) are actually value types; el hecho de que su Type s devuelva true para IsClass es un error en la especificación. Sospecho que nadie se ha dado cuenta de esto porque obtener el tipo de un puntero es una operación muy rara.

+0

¿Ha visto los [documentos] (http://msdn.microsoft.com/en-us/library/y31yhkeb (v = vs.110) .aspx)? De acuerdo con esto: * En un contexto inseguro, un tipo puede ser un tipo de puntero, un tipo de valor o un tipo de referencia *. Entonces, ¿no puedes tratarlos como ningún tipo de valor ni tipo de referencia? – nawfal

+0

Eso tiene sentido. Pero no responde a mi pregunta: * ¿por qué los punteros son tipos de referencia (es decir, devuelven 'verdadero' de' IsClass')? * –

+0

Vea el gráfico para otra declaración contradictoria de [documentos] (http: // msdn. microsoft.com/en-IN/library/2hf02550(v=vs.90).aspx). Los punteros se enumeran en tipos de referencia. – nawfal

0

Son tipos de referencia porque no contienen el valor real del objeto de destino: al igual que las referencias, simplemente "apuntan" al objeto de destino.

+1

He actualizado la pregunta para que sea más clara en referencia * tipos * vs. referencia * variables *. –

-2

considerar:

MyClass x = new MyClass(); 

Aquí, miclase un tipo de referencia, y si uno mira a través de la reflexión, x se llamaría un tipo de referencia. Pero, bajo el capó, x es en realidad un puntero.

+1

Un tipo de puntero ('int *') es una entidad completamente diferente a una referencia de objeto normal – thecoop

+1

@thecoop una referencia es conceptualmente nada diferente de un puntero. Ambos contienen la dirección en memoria de algunos otros datos, ya sea un primitivo 'int' o un objeto' MyClass'. La principal diferencia es que las referencias son típicamente inmutables (las referencias mismas, no a qué se refieren). – corsiKa

3

typeof (int) .MakePointerType(). IsPointer

parece que hay una distinción.

+1

Derecha; es posible determinar si un tipo de referencia es un puntero o no. Mi pregunta es por qué los punteros son tipos de referencia y no de valores (vea la pregunta actualizada). –

+1

El CLR diferencia los tipos de punteros gestionados y no gestionados, consulte 12.1.1.1 de la Partición I en la especificación clr.Los punteros administrados pueden ser cambiados (movidos) por el GC. Creo que esta puede ser la razón por la cual son tipos de clase. – MaLio

+0

Véase también la sección 14.4 Partición II - Tipos especiales/Tipos de apuntador – MaLio

1

Esto es solo una teoría, pero ¿tendría algo que ver con el hecho de que debido al sistema de recolección de basura y la compactación de pila, los punteros deben ajustarse cuando los objetos se mueven en la memoria. Al hacer tipos de referencia de punteros administrados, se pueden volver a señalar de la misma manera que cualquier otra referencia, en lugar de tener que convertirlos en un caso especial.

actualización

Un excelente artículo de Wesner Moise: "Pointers UNDOCUMENTED".

En el artículo describe cómo se ajustan los punteros administrados durante la compactación de pila.

+0

Creo que los punteros solo pueden apuntar a objetos anclados - [ver ref MSDN] (http://msdn.microsoft.com/en-US/library/zcbcf4ta.aspx) . Aunque leeré ese artículo; ¡parece interesante! –

Cuestiones relacionadas