way net concatener concatenate concatenar best array c# string .net-4.0 concatenation

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 ...