2012-01-11 10 views
7

La diferencia entre los tipos de referencia y los tipos de valores suele ser confusa para los principiantes debido a que no comprenden qué tipo de valor tiene realmente una variable. Sabemos que:Tipos de referencia: ¿podemos ver la referencia real?

  • tipos de valor almacenan los real valor
  • Tipos de referencia única tienda de la referenciaal objeto

¿Es posible inspeccionar cada tipo de variable para cualquiera ver el valor, o la referencia real en sí misma? ¿La referencia está almacenada como algún tipo de valor codificado? Sé que las referencias se pueden pasar por valor, así que asumo que sí.

Creo que esto ayudaría a los recién llegados con su comprensión, y sería muy interesante de explorar.

+1

Lo único que vería es una dirección, un número aparentemente aleatorio. ¿Por qué querrías ver esto? – Dykam

+3

Para cimentar la idea de que dentro de la variable no es el objeto que establecen, sino una dirección. ¿Cómo accederíamos a esto? –

+1

http://stackoverflow.com/questions/1978232/how-can-i-display-the-actual-value-of-a-reference-in-c-sharp –

Respuesta

10

¿Es posible inspeccionar cada tipo de variable para ver el valor o la referencia real en sí?

Solo para aclarar, el valor de una variable de tipo de referenciaes una referencia. La referencia es el valor.

Una referencia es un tipo de valor, al igual que un int es un tipo de valor. A diferencia de un int, una referencia es un valor que solo puede ser copiado y desreferenciado; no puede observar su valor directamente en C#, porque su valor es un detalle de implementación del recolector de basura.

¿La referencia está almacenada como algún tipo de valor codificado?

Sí, exactamente. En la práctica, una referencia es un entero de 32 o 64 bits (dependiendo de si se encuentra en un proceso de 32 o 64 bits) que es un puntero a alguna estructura conocida por el recolector de basura como asociada a los datos del objeto referido .

Si desea ver las referencias directamente, la herramienta para hacerlo es el depurador. Cargue su código C# en el depurador, compílelo, ejecútelo, acceda a un punto de interrupción y observe el estado de la pila y los registros. Con un poco de inteligencia, debería ser capaz de averiguar qué ubicaciones de pila y registros corresponden a qué variables locales. Las ubicaciones correspondientes a las variables locales del tipo de valor contendrán los valores; los de tipo de referencia contendrán valores que parecen punteros. Si examina esos punteros en la ventana de memoria, entonces observará las estructuras mantenidas por el recolector de basura que describen el contenido del objeto.

+3

Creo que es importante tener en cuenta que, si bien las implementaciones de .NET existentes pueden almacenar direcciones (de registros de información del objeto) en variables de referencia, no hay garantía de que las versiones futuras lo hagan. Sería posible, por ejemplo, que algunos bits de una variable de referencia fueran un índice que seleccionara uno de un número de montones, mientras que otros bits fueran un índice dentro de ese montón. Si bien tal sistema podría ser ineficiente con los procesadores existentes, el diseño de futuros procesadores en torno a dicho modelo podría permitir una utilización más eficiente de la memoria caché. El código .net existente no debería preocuparse por tales detalles. – supercat

+0

@supercat: Absolutamente. De hecho, las referencias podrían implementarse como identificadores totalmente opacos que solo son significativos en la medida en que indexan en alguna tabla propiedad del recolector de basura; no hay ninguna razón por la cual * cualquier * bit en una referencia necesite tener un significado particular. Como sucede, en las implementaciones de hoy en día cada bit de una referencia * es * significativo, ya que se puede interpretar como un puntero. Pero eso está sujeto a cambios en cualquier momento. –

+0

Por curiosidad, aunque las CPU existentes probablemente no permitan que estas cosas sean muy eficientes, me pregunto si valdría la pena en las futuras CPU tener un montón de objetos pequeños para objetos cuya información es de 8 (quizás 16) bytes o menos , donde cada ranura en la tabla de objetos contendría los datos reales del objeto en lugar de un puntero al mismo. En las CPU existentes, uno necesitaría instrucciones adicionales para cada acceso de montón para determinar a qué montón pertenecía cualquier referencia dada, pero si había una instrucción "obtener dirección de objeto" que utilizaba un poco en la referencia para seleccionar direccionamiento simple o doble ... – supercat

1

Puede hacer esto con un objeto fijado con bastante facilidad;

GCHandle gch=GCHandle.Alloc(data, GCHandleType.Pinned); 
IntPtr AddressInMemory=gch.AddrOfPinnedObject(); 
+0

Esto no funcionará para [tipos no blittable] (http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx), como casi todas las clases. – svick

+0

Me corrigen. Parece que la única vez que necesité esto fue con primitivos. –

1

Puede hacerlo con unsafe código:

unsafe 
    static void Main(string[] args) 
    { 
     string s = "Hello"; 

     fixed (char* pc = s) 
     {     
      IntPtr p = (IntPtr)pc; 
      Console.WriteLine(p); // here is your meaningless address 
     }    
    } 
+0

Esto hace una copia fija de s, entonces ¿por qué no pin s directamente? –

+0

No vamos a usar 's' para nada. –

+0

@EugenRieck ¿Tiene una fuente para esa declaración? No veo copiando aquí. – CodesInChaos

5

Este es probablemente uno de Jon Skeet, pero puede ser que tenga un ángulo diferente en él:

No se preocupe demasiado sobre cómo estas cosas se representan en la memoria. A menos que hayas leído toda la especificación del lenguaje, ¿quién lo hace de todos modos? - Realmente no necesitas saber. De Verdad. No se moleste en memorizar qué datos se almacenan donde, lo más probable es que esto sea específico de la implementación.

En cambio, piense en términos de semántica, p. Ej. que un tipo de valor pasado a una función es copiado, mientras que un tipo de referencia es con referencia. Cosas como esas.

Realmente no desea saber qué contiene una declaración de un tipo. Créame. Lo que quiere saber es cómo se comporta.

+2

+1 Aquí es donde Eric Lippert [dice] (http://blogs.msdn.com/b/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx) lo mismo.Las direcciones son un detalle de implementación, la especificación de idioma no menciona las direcciones al especificar referencias. Aprenda cómo se comportan y no cómo funcionan. – MarkJ

+2

Si bien estoy de acuerdo con su afirmación, no creo que sea el objetivo de la pregunta. Creo que le gustaría saber cómo hacerlo, no sus opiniones sobre por qué no es importante. Resaltar cómo funciona la funcionalidad compleja puede hacerte un mejor ingeniero, incluso si no encuentras un uso instantáneo de ese conocimiento. –

+0

Aunque doy las gracias y estoy de acuerdo con su respuesta, no aborda el tema de mi pregunta. Me gustaría simplemente acceder a la dirección ** solo para demostrar que está allí ** sin ninguna otra razón. Estoy de acuerdo con @ AdamG.Carstensen. –

Cuestiones relacionadas