¿Debo usar .ToString () al concatenar cadenas y variables enteras en C #?

19
int a = 1;
int b = 2;
int sum = a + b;
string expression = "Expression: " + a + " + " + b + " = " + sum;
Console.WriteLine(expression); //displays Expression 1 + 2 = 3

¿Debo usar:

string expression = "Expression: " + a + " + " + b + " = " + sum;

o

string expression = "Expression: " + a.ToString() + " + " + b.ToString() + " = " + result.ToString();

¿Se recomienda usar ToString()al concatenar stringy int?

Akainu
fuente
66
En a + "" + b + ""o "" + a + b + "", no importa: todo es concatenación de cadenas. En a + b + ""sí importa: ay bse agregan primero.
Tim S.
44
Nota al margen: en VB.NET, esta ambigüedad se evita al tener un operador de concatenación de cadenas explícito : "Expression: " + aarrojará un error de tiempo de compilación (con Option Strict On), "Expression: " & arealizará la concatenación de cadenas.
Heinzi
El primer código dará como resultado el boxeo (int a Int32), el segundo no. El segundo es obviamente más rápido.
Alfabetos aleatorios

Respuestas:

33

ToString uso

No, no deberías usar ToStringaquí.

La concatenación de cadenas transforma automáticamente las no cadenas en cadenas, lo que significa que sus dos variantes son casi idénticas:

Cuando uno o ambos operandos son de tipo cadena, los operadores de suma predefinidos concatenan la representación de cadena de los operandos.

Fuente: Especificación del lenguaje C #: operador de adición, MSDN .

Por otro lado, el primero (sin ToString):

  • Es más corto de escribir,
  • Es más corto de leer,
  • Es más fácil de mantener y:
  • muestra exactamente la intención del autor: concatenar cadenas.

Así que prefiere el primero.

Bajo el capó

Lo que también es interesante es ver qué sucede debajo del capó. Una de las formas de verlo es mirar el código IL dentro de LINQPad. Este programa:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = a + b;
    Console.WriteLine(c);
}

se traduce a la siguiente IL:

IL_0001:  ldc.i4.3    
IL_0002:  stloc.0     // a
IL_0003:  ldstr       " Hello"
IL_0008:  stloc.1     // b
IL_0009:  ldloc.0     // a
IL_000A:  box         System.Int32
IL_000F:  ldloc.1     // b
IL_0010:  call        System.String.Concat
IL_0015:  stloc.2     // c
IL_0016:  ldloc.2     // c
IL_0017:  call        System.Console.WriteLine

¿Ves eso System.String.Concat? Eso significa que el código original también se puede escribir así, lo que se traduce exactamente en el mismo IL:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = string.Concat(a, b); // This is the line which was changed.
    Console.WriteLine(c);
}

Cuando lea la documentación destring.Concat(object[]) , puede aprender que:

El método concatena cada objeto en argumentos llamando al ToStringmétodo sin parámetros de ese objeto; no agrega ningún delimitador.

Esto significa que ToStringes redundante. También:

String.Empty se usa en lugar de cualquier objeto nulo en la matriz.

Lo que maneja muy bien el caso donde algunos de los operandos son nulos (vea la nota al pie 1).

Mientras que en el último ejemplo, se tradujo la concatenación string.Concat, también se deben resaltar las optimizaciones del compilador:

var a = "Hello " + "World";

se traduce en:

ldstr       "Hello World"
stloc.0

Por otra parte:

var a = string.Concat("Hello ", "World");

se traduce en:

ldstr       "Hello "
ldstr       "World"
call        System.String.Concat
stloc.0

Otras alternativas

Por supuesto, hay otras formas de concatenar representaciones en cadena de objetos en C #.

  1. StringBuilderse usa cuando necesita realizar muchas operaciones de concatenación y ayuda a reducir la cantidad de cadenas intermedias creadas. Decidir si debe usar una StringBuilderconcatenación común o no puede ser fácil. Use un generador de perfiles o busque respuestas relevantes en Stack Overflow.

    El uso StringBuildertiene el inconveniente principal de hacer que el código sea difícil de leer y mantener. Para casos simples como el de su pregunta, StringBuilderno solo es perjudicial para la legibilidad del código, sino que también es inútil en términos de rendimiento.

  2. string.Join debe usarse cuando necesite agregar delimitadores.

    Obviamente, nunca lo use string.Joincon un delimitador vacío para concatenar cadenas.

  3. string.Formatse puede usar cuando se prefiere la plantilla de cadenas a la concatenación de cadenas. Uno de los casos en los que puede preferir eso es cuando el mensaje puede estar localizado, como lo sugiere la respuesta de kunthet.

    El uso string.Formattiene varios inconvenientes que lo hacen inadecuado para casos simples como el suyo:

    • Con marcadores de posición simples "{0}", a menudo no está claro qué parámetro va a dónde. Es frecuente invertir por error los parámetros u olvidar uno. Afortunadamente, C # 6 finalmente introduce la interpolación de cadenas que resuelve este problema.

    • El rendimiento del tiempo de ejecución puede degradarse. Por supuesto, no asumas string.Formatque siempre es más lento. Si el rendimiento es importante, mida dos enfoques y determine cuál es más rápido en función de sus resultados reales en lugar de suposiciones.

    • El código es un poco más largo de escribir, más largo de leer y más difícil de mantener, aunque esto es extremadamente menor y no debería molestarlo demasiado.


¹ La diferencia aparece cuando uno de los objetos es null. Sin ToString, a nullse reemplaza por una cadena vacía. Con ToString, NullReferenceExceptionse arroja un.

Arseni Mourzenko
fuente
1
Por exactamente esta razón (comportamiento impredecible), concatenar cadenas con el +se considera una mala práctica en la mayoría de los idiomas. En este caso lo usaría string.Concat, en muchos casos string.Formates mejor. Ciertamente no es Pythonic para usar +, y dado que PEP 3101 también %se desaconseja a favor str.format.
Arda Xi
2
¿Está sustituyendo una cadena vacía por nullrealmente "manejarlo bien"? Bueno, no es tan malo como "en la reanudación de error siguiente" ...
Deduplicator
Debajo del capó, si concatena sin llamar a .ToString (), el boxeo ocurrirá ..., y Concat(object[])se usará en lugar de Concat(string[]). Por "string " + ilo tanto, en realidad no es idéntico a"string " + i.ToString()
Alphabets aleatorios
@RandomAlphabets: punto válido. Sin embargo, la diferencia es simplemente la ubicación de ToString(): el código de OP en un caso, System.String.Concatla implementación de en el otro caso. Entonces, la respuesta sigue siendo válida: no escriba el código que no tiene ningún beneficio.
Arseni Mourzenko
15

En su lugar, debe usar formateador de cadenas. Es más fácil formatear su número en representación de cadena o localización. p.ej:

string expression = string.Format("Expression: {0} + {1} = {2}", a, b, sum);

Más información sobre MSDN .

Sin embargo, el formateador de cadenas es menos legible (y quizás también de rendimiento) que la concatenación de cadenas.

Kunthet
fuente
66
¿Le gustaría explicar por qué esta opción es mejor?
Ingeniero mundial
@WorldEngineer: Actualicé la explicación.
kunthet
12
No sé sobre todos los demás, pero en realidad me parece más legible. Quizás porque crecí con C, donde s [n] printf es la única opción realista para este tipo de código.
Jules
2
Pero de esta manera da tres fuentes de errores en lugar de uno. Cuando agrega algo a la cadena, 1) tiene que cambiar la cadena de formato, 2) no debe olvidar agregar un nuevo parámetro en la lista, 3) intente elegir el lugar correcto en la lista donde se debe colocar el nuevo parámetro.
Ruslan
2
Solo quiero intervenir y hacerle saber acerca de la próxima función de interpolación de cadenas en C # 6. Escribirá "Expresión: \ {a} + \ {b} = \ {sum}" para obtener el mismo resultado. codeproject.com/Articles/846566/…
cwap
-2

Si usa +concatenación, en sí mismo usa el String.Concatmétodo. La cadena en sí no expone un operador +.

por ejemplo:

int i = 10;
string str = "hello" + i;

se compila en:

int i = 10;
object o1 = "hello";
object o2 = i; // Note boxing
string str = string.Concat(o1, o2);

Si llama directamente ToString, evitará el boxeo y llamará a la Concat(string, string)sobrecarga. Por lo tanto, la ToStringllamada será un poco más eficiente, aunque no lo suficientemente significativa. Será mejor que sigas con el ejemplo que crees que es más legible.

sohaiby
fuente
2
esto parece simplemente repetir los puntos hechos y explicados en la respuesta anterior : "La concatenación de cadenas transforma automáticamente las no cadenas en cadenas ..."
mosquito