EDIT: En la respuesta a continuación me he referido a la piscina pasante como dominio de aplicación específica; Estoy bastante seguro de que eso es lo que he observado antes, pero los documentos de MSDN para String.Intern sugieren que hay un solo grupo interno para todo el proceso, lo que lo hace aún más importante.
Respuesta original
(Iba a añadir esto como un comentario, pero yo creo que es un punto lo suficientemente importante como para necesitar una respuesta adicional ...)
Como otros han explicado, cuerda internación se produce para todos los literales de cadena, pero no en cadenas "creados de forma dinámica" (por ejemplo, los que se leen desde una base de datos o archivo, o construido utilizando StringBuilder
o String.Format
.)
sin embargo, yo no sugeriría c alling String.Intern
para redondear el último punto: poblará el grupo interno durante la vida útil de su AppDomain
. En su lugar, use un grupo que sea local solo a su uso.Aquí está un ejemplo de dicho pool:
public class StringPool
{
private readonly Dictionary<string,string> contents =
new Dictionary<string,string>();
public string Add(string item)
{
string ret;
if (!contents.TryGetValue(item, out ret))
{
contents[item] = item;
ret = item;
}
return ret;
}
}
Usted sería entonces sólo tiene que utilizar algo como:
string data = pool.Add(ReadItemFromDatabase());
(Tenga en cuenta que la piscina no es seguro para subprocesos; el uso normal no lo necesitaría para serlo)
De esta manera puede tirar su grupo tan pronto como ya no lo necesite, en lugar de tener un número potencialmente grande de cadenas en la memoria para siempre. También podría hacerlo más inteligente, implementando un caché LRU o algo así si realmente quisiera.
EDITAR: Solo para aclarar por qué es mejor que usar String.Intern
... supongamos que lee un montón de cadenas de una base de datos o archivo de registro, los procesa y luego pasa a otra tarea. Si llama al String.Intern
en esas cadenas, serán nunca basura recolectada mientras su AppDomain
esté vivo, y posiblemente ni siquiera entonces. Si carga varios archivos de registro diferentes, acumulará cadenas gradualmente en su grupo interno hasta que termine o se quede sin memoria. En cambio, estoy sugiriendo un patrón de esta manera:
void ProcessLogFile(string file)
{
StringPool pool = new StringPool();
// Process the log file using strings in the pool
} // The pool can now be garbage collected
Aquí se obtiene el beneficio de las secuencias múltiples en el mismo archivo sólo una vez en la memoria existente (o, al menos, sólo para conseguir Gen0 pasado una vez), pero usted don' t contaminar un recurso "global" (el grupo interno).
Jon, ¿podrías detallar qué obtienes al hacer esto? Supongo que ahora tendrá una función de comparación de cadenas de mayor rendimiento para cadenas en la agrupación. O me estoy perdiendo el punto aquí? –
Editando la respuesta para explicar ... –
oh, ¿las cadenas internas existen para siempre? Eso no es tan bueno, jeje. Gracias por notar eso. – Svish