2012-01-01 11 views
5

yo no entiendo:Interral string literales malentendido?

MSDN dice

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

En consecuencia, una instancia de una cadena literal con un valor particular sólo existe una vez en el sistema.

Por ejemplo, si asigna la misma cadena literal a varias variables , el tiempo de ejecución recupera la misma referencia a la cadena literal del grupo interno y la asigna a cada variable.

¿Este comportamiento es el predeterminado (sin interno)? o usando el método Intern?

  • Si es el valor predeterminado, entonces ¿por qué querré usar el pasante? (la instancia ya estará una vez ...)?

  • si no es por defecto: si escribo 1000 veces esta fila:

    Console.WriteLine ("lalala");

1) ¿obtendré 1000 apariciones de "lalala" en la memoria? (sin usar el interno ...)

2) ¿"lalala" eventualmente será Gc'ed?

3) ¿"lalala" ya está internificado? y si lo hace, ¿por qué tendré que "sacarlo" del grupo, y no solo escribir "lalala" nuevamente?

Un poco confundir.

Respuesta

9

Los literales de cadena se internan automáticamente (por lo tanto, si su código contiene "lalala" 1000 veces, solo existirá una instancia).

Tales cadenas no recibirán GC'd y cada vez que se haga referencia a ellas, la referencia será la interna.


string.Intern hay para cadenas que son no literales - dicen de entrada de usuario o leen desde un archivo o base de datos y que sabe se repetirá muy a menudo y, como tal, son dignas de internar durante toda la vida del proceso.

+0

entonces ¿por qué alguna vez querré usar 'string.intern (" lalala ")' si se obtiene automáticamente del grupo? Solo puedo usar "lalala" ... aclare ... :) toda. –

+0

@RoyiNamir - Se ha agregado algo de información sobre 'string.Intern'. Espero que aclare un poco. – Oded

+0

como siempre gracias. -la segunda parte me aclaro las cosas. –

5

La internación es algo que ocurre detrás de escena, por lo que como programador, nunca tendrá que preocuparse por ello. Por lo general, no tiene que poner nada en el grupo ni obtener nada de la agrupación. Como la recolección de basura: nunca tiene que invocarlo, o preocuparse de que pueda suceder, o preocuparse de que no ocurra. (Bueno, en el 99.999% de los casos. Y el 0.001% restante es cuando estás haciendo cosas muy raras.)

El compilador se encarga de internar todos los literales de cadena que están contenidos en tu archivo fuente, por lo que "lalala" será internado sin tener que hacer nada, o tener ningún control sobre el asunto. Y cada vez que se refiera a "lalala" en su programa, el compilador se asegurará de obtenerlo del grupo interno, nuevamente sin tener que hacer nada, ni tener ningún control sobre el asunto.

El grupo interno contiene un número más o menos fijo de cadenas, generalmente de un tamaño muy pequeño (solo una fracción del tamaño total de su .exe), por lo que no importa que nunca obtengan basura -recogido.


EDITAR

El propósito de cuerdas internar es mejorar en gran medida el tiempo de ejecución de ciertas operaciones de cadena como iguales(). El método Equals() de String primero comprueba si las cadenas son iguales por referencia, lo cual es extremadamente rápido; si las referencias son iguales, devuelve true inmediatamente; si las referencias no son iguales, y las cadenas están intercaladas, devuelve false inmediatamente, porque no pueden ser iguales, ya que todas las cadenas en el grupo interno son diferentes entre sí. Si ninguno de los anteriores es verdadero, entonces procede con una comparación de caracteres por cadena de caracteres. (En realidad, es incluso más complicado que eso, porque también verifica los códigos de las cadenas, pero vamos a mantener las cosas simples en esta discusión.)

Supongamos que está leyendo tokens desde un archivo en la cadena s, y usted tiene una sentencia switch de la siguiente forma:

switch(s) 
{ 
    case "cat": .... 
    case "dog": .... 
    case "tod": .... 
} 

el literales de cadena "gato", "perro", "tod" todos se han internado, pero que está comparando todas y cada una de ellas contra s, que no ha sido internado, por lo que no está cosechando los beneficios del grupo de pasantes. Si hace una interna s justo antes de la declaración de cambio, entonces las comparaciones que se harán mediante la instrucción de cambio serán mucho más rápidas.

Por supuesto, si hay alguna posibilidad de que su archivo contenga basura, entonces NO quiere hacer esto, porque cargar muchas cadenas aleatorias en el grupo interno seguramente matará el rendimiento de su programa, y ​​eventualmente se ha quedado sin memoria.

+0

'el compilador se asegura de obtenerlo del grupo interno' ... ¿así que cuándo quiero usar explícitamente string.intern ?? –

+0

@Oded ya ha respondido esto. Trataré también de dar un ejemplo dentro de mi respuesta. –

+0

Agregué un ejemplo. –