2010-01-21 12 views
11

que utilizan la reflexión a mirar en los campos internos de System.String y me encontré con tres campos:las partes internas de System.String

m_arrayLength 

m_stringLength 

m_firstChar 

No entiendo cómo funciona esto.

m_arrayLength es la longitud de una cierta matriz. ¿Dónde está esta matriz? Aparentemente no es un campo miembro de la clase de cadena.

m_stringLength tiene sentido. Es la longitud de la cadena.

m_firstChar es el primer personaje de la cadena.

Así que mi pregunta es ¿dónde están el resto de los caracteres de la cadena? ¿Dónde están almacenados los contenidos de la cadena si no están en la clase de cadena?

Respuesta

10

Gran parte de la implementación de System.String está en código nativo (C/C++) y no en código administrado (C#). Si usted toma un vistazo al código descompilada verá que la mayoría de los métodos de "interesantes" o "núcleo" están decoradas con este atributo:

[MethodImpl(MethodImplOptions.InternalCall)] 

Sólo algunas de las API ayudante/de conveniencia se implementan en C# .

Entonces, ¿dónde se almacenan los caracteres de la cadena? Es un secreto! En el fondo dentro de la implementación del código nativo central de CLR.

2

Pensaría de inmediato que m_firstChar es no primer carácter, más bien un puntero al primer carácter. Eso tendría mucho más sentido (aunque, como no conozco la fuente, no puedo estar seguro).

Tiene poco sentido almacenar el primer carácter de una cadena a menos que desee una operación s.substring(0,1) cegadoramente rápida :-) Hay una buena probabilidad de que los propios caracteres (que los tres campos aluden) se asignen por separado del objeto real .

12

La primera char proporciona acceso (a través de &m_firstChar) a una dirección en la memoria del primer carácter en el búfer. La longitud indica cuántos caracteres hay en el string, lo que hace que .Length sea eficiente (mejor que buscar un nul char). Tenga en cuenta que las cadenas se pueden sobredimensionar (especialmente si se creó con StringBuilder y algunos otros escenarios), por lo que a veces el búfer real es realmente más largo que la cadena. Entonces, es importante hacer un seguimiento de esto. StringBuilder, por ejemplo, en realidad muta una cadena dentro de su búfer, por lo que necesita saber cuánto puede agregar antes de tener que crear un búfer más grande (consulte AppendInPlace, por ejemplo).

+0

@Marc, creo que su descripción (sólo el primer bit) es un poco confuso. Si 'm_firstChar' es un' char', entonces su dirección no puede ser la ubicación de una cadena. Si, en cambio, es una dirección del primer carácter en una matriz de 'char's), no tiene sentido usar' & m_firstChar', que le daría la dirección del puntero, ¿no? A menos que C# sea muy diferente de sus hermanos, lo cual es una posibilidad. No sé mucho sobre eso. – paxdiablo

+0

@paxdiablo si miras el código descompilado verás que el primer carácter es el primer carácter real de la cadena en la memoria. Por lo tanto, obtener su dirección e indexación más allá de la dirección de memoria inicial será el resto de los caracteres. – Eilon

+0

¿Entonces m_firstChar es en realidad la matriz (que se degradaría a un puntero en C)? – paxdiablo

0

Respuesta correcta en la diferencia entre la cuerda y System.string está aquí: string vs System.String

No hay nada acerca implementaciones nativas

Cuestiones relacionadas