2011-06-21 32 views
9

En la clase String hay un método IsInterned(). Nunca uso este método. Por favor, ayúdame a entender los mejores usos de este método.¿Cuál es el propósito de String.IsInterned?

+2

¿No está satisfecho con el documento oficial en msft? http://msdn.microsoft.com/en-us/library/system.string.isinterned.aspx – tzup

+5

@tzup: los documentos dicen qué hace la función, no cuándo la usaría. – Gabe

Respuesta

3

Un posible uso sería si desea bloquear el valor de la cadena.

En el siguiente:

string s = //get it from somewhere, e.g. a web request 
lock (s){ 
//do something 
} 

no es un problema, porque puede haber dos solicitudes diferentes para la misma cadena, pero ambos introduzca el código protegido. Esto se debe a que puede haber dos objetos de cadena diferentes que tengan el mismo valor.

Sin embargo, hay algo llamado grupo interno, que es una tabla que contiene una sola instancia de algunas cadenas (todos los literales están ahí, por ejemplo).

Se puede utilizar para hacer el trabajo de bloqueo:

string s = //get it from somewhere, e.g. a web request 
lock (string.Intern(s)){ 
//do something 
} 

Esta función podría devolver una referencia a una cadena en la piscina pasante, que tiene el mismo valor que s, por lo que es seguro para el bloqueo.

La función IsIntern simplemente comprueba si la referencia que está sosteniendo es una referencia a una cadena en el grupo interno.

+6

Nunca bloquees una cuerda. Las cadenas son ágiles en el dominio, es decir, la misma instancia de cadena puede ser accesible desde múltiples aplicaciones, especialmente cuando están internados. El resultado sería que un hilo puede estar esperando que se libere un bloqueo en un dominio de aplicación no relacionado ... efecto muy desagradable. – MaLio

+0

Bloquear en string.Intern combinará bloqueos! – usr

1

Los literales de cadena en C# están internados (es decir, están almacenados en un grupo interno) de modo que para cada aparición del literal solo hay una instancia. Si está creando su propio lenguaje (por ejemplo, algún sistema de script), puede usar IsInterned and Intern para generar el mismo .

2

Consulte el puesto de Eric, creo que este es el mejor en donde se explica Intern

+3

La cadena "IsInterned" no aparece en ese artículo. – usr

0

Tenga una mirada en this. Realmente hay un caso de uso en ese hilo.

7

Considere que el internamiento es una optimización; intercambia una disminución de algunas cualidades deseables para un aumento en otras. En particular, la interna tiene las siguientes buenas cualidades:

  1. La memoria no se desperdicia en cadenas duplicadas.
  2. La comparación de igualdad entre las cadenas que se conocen como internas es extremadamente rápida.
  3. La comparación de igualdad entre cadenas que se internan es mucho más rápida que si no se internan.
  4. Otras comparaciones obtienen un beneficio de rendimiento en algunos casos.

Tiene las siguientes malas cualidades:

  1. Las cadenas no son basura recogen con la frecuencia (en su caso), por lo que la memoria que podría ser recuperada se utiliza en cadenas que no se ven de nuevo, o para Un largo tiempo. (Practica todas tus cadenas y podrías terminar con un uso de memoria desagradable).

Como una optimización, lo usamos donde las buenas cualidades pesan más que las malas o las malas cualidades no se mantienen (si sabemos que la cadena estará presente durante la vida útil de la aplicación) de todos modos, o sé que se usará muchas veces, entonces la parte mala no se sostiene).

Y por la misma razón no lo usamos donde las malas cualidades superan a las buenas. (La mayoría de las veces).

IsInterned() se puede utilizar para encontrar un punto a mitad de camino.

Considere Tengo una propiedad de cadena Name:

public string Name { get; set; } 

Digamos que sé que es común a buscar objetos con un determinado Name, o para tratar de encontrar objetos con el mismo Name o de otra manera hacer mucho de las comparaciones de igualdad en él. O digamos que sé que habrá muchos otros objetos con el mismo Name. O ambos.

En estos casos podría considerar la internación:

private string _name; 
public string Name 
{ 
    get { return _name; } 
    set { _name = string.Intern(value); } 
} 

Por supuesto, si esto era una buena idea o no depende de las buenas y malas cualidades de internar mencionado anteriormente.

En los intervalos entre usar y no usar es la posibilidad:

private string _name; 
public string Name 
{ 
    get { return _name; } 
    set { _name = string.IsInterned(value) ?? value; } 
} 

Aquí si la cadena value ya está internado luego nosotros, los abajo-lados de la internación ya están en el trabajo y no sufrir más , entonces lo aprovechamos. Pero si value no está ya internado, simplemente lo usamos tal como es.

Esta es también una optimización, que se optimiza para un caso diferente. Solo se beneficia si es probable que un número razonable de los valores observados sea interceptado por algún otro código (o porque coinciden con literales en el ensamblado), de lo contrario, solo desperdicia tiempo haciendo búsquedas. Probablemente sea menos útil que Intern(), que a su vez es menos útil que simplemente usar las cuerdas e ignorar el internamiento, pero eso muestra un momento en que podría ser útil.

Cuestiones relacionadas