concatener - concatenate string c# net
String.Concat código ineficiente? (6)
Estaba investigando String.Concat: (Reflector)
muy extraño :
tienen la matriz de valores,
Ellos crean un NUEVO ARRAY para que luego lo envíen a ConcatArray
.
Pregunta:
¿Por qué crearon una nueva matriz? Tenían values
desde el primer lugar ...
editar
código:
public static string Concat(params string[] values)
{
if (values == null)
{
throw new ArgumentNullException("values");
}
int totalLength = 0;
string[] strArray = new string[values.Length];
for (int i = 0; i < values.Length; i++)
{
string str = values[i];
strArray[i] = (str == null) ? Empty : str;
totalLength += strArray[i].Length;
if (totalLength < 0)
{
throw new OutOfMemoryException();
}
}
return ConcatArray(strArray, totalLength);
}
¿Por qué crearon una nueva matriz?
Puedo confirmar la conjetura de Jon; Tengo el código fuente original delante de mí. Los comentarios indican que el motivo de la copia se debe a que una persona tonta podría estar mutando la matriz que se pasó en otro hilo . ¿Qué podría pasar entonces? El cálculo de la longitud podría decir que habrá cien bytes de datos de cadena en el resultado, pero en el momento en que se realice la copia, podría haber un millón de bytes de datos de cadena en la matriz.
Eso sería malo. El problema se evita fácilmente haciendo una copia.
Ineficiente
No, no importa. La creación y copia de la matriz es muy rápida en relación con la concatenación, solo está copiando referencias.
Parece que lo hacen para convertir cadenas null
en la matriz de entrada en String.Empty
(no pueden hacer esto en values
porque sería modificar la entrada que es un no) y detectar concatentaciones que se desbordarían antes haciendo la concatenación (para eso está la prueba if(totalLength < 0)
). Además, pueden usar totalLength
para asignar la memoria para la cadena concatenada por adelantado, que es más eficiente.
Bueno, en primer lugar, significa que se puede confiar en que los contenidos de la nueva matriz no son nulos ... e invariables.
Sin esa copia, otro hilo podría modificar la matriz original durante la llamada a ConcatArray
, lo que presumiblemente podría generar una excepción o incluso desencadenar un error de seguridad. Con la copia, la matriz de entrada se puede cambiar en cualquier momento; cada elemento se leerá exactamente una vez, por lo que no puede haber inconsistencia. (El resultado puede ser una mezcla de elementos antiguos y nuevos, pero no terminarás con daños en la memoria).
Supongamos que se confía en que ConcatArray
realiza una copia masiva de las cadenas en la matriz que se pasa, sin verificar el desbordamiento del búfer. Luego, si cambia la matriz de entrada en el momento justo, podría terminar escribiendo fuera de la memoria asignada. Maldad. Con esta copia defensiva, el sistema puede estar seguro de que la longitud total es realmente la longitud total.
1 Bueno, a menos que se use la reflexión para cambiar el contenido de una cadena. Pero eso no se puede hacer sin permisos bastante altos, mientras que cambiar los contenidos de una matriz es fácil.
Crearon una nueva matriz para normalizar las entradas null
en String.Empty
. Esto no se podría hacer en la matriz de values
provista porque entonces estarían modificando la entrada.
Probablemente para asegurarse de que no cambie durante la vida útil del método. Lo que llevaría a que totalLength
no se ajuste al contenido de la matriz.
Sospecho que ConcatArray
utiliza algunas copias de memoria no seguras, y no vuelve a verificar la Length
la cadena s. Uno podría reescribirlo para evitar la asignación, pero una asignación adicional pequeña y de corta duración es bastante barata.
por lo que puedo ver, hacen un poco de trabajo con esto, supongo que no quieres mutar el original ... recuerda que quieres que tus cuerdas sean inmutables para la función Concat, por supuesto, no cambies una referencia de parámetro si no se indica ...