¿Por qué usar String.Format?

¿Por qué alguien usaría String.Format en C # y VB .NET en lugar de los operadores de concatenación ( & en VB, y + en C #)?

¿Cual es la diferencia principal? ¿Por qué todos están tan interesados ​​en usar String.Format ? Soy muy curioso.

Puedo ver una serie de razones:

Legibilidad

 string s = string.Format("Hey, {0} it is the {1}st day of {2}. I feel {3}!", _name, _day, _month, _feeling); 

vs:

 string s = "Hey," + _name + " it is the " + _day + "st day of " + _month + ". I feel " + feeling + "!"; 

Especificadores de formato (y esto incluye el hecho de que puede escribir formateadores personalizados)

 string s = string.Format("Invoice number: {0:0000}", _invoiceNum); 

vs:

 string s = "Invoice Number = " + ("0000" + _invoiceNum).Substr(..... /*can't even be bothered to type it*/) 

Persistencia de la plantilla de cadena

¿Qué ocurre si quiero almacenar plantillas de cadenas en la base de datos? Con formato de cadena:

 _id _translation 1 Welcome {0} to {1}. Today is {2}. 2 You have {0} products in your basket. 3 Thank-you for your order. Your {0} will arrive in {1} working days. 

vs:

 _id _translation 1 Welcome 2 to 3 . Today is 4 . 5 You have 6 products in your basket. 7 Someone 8 just shoot 9 the developer. 

Además de ser un poco más fácil de leer y agregar algunos operadores más, también es beneficioso si su aplicación se internacionaliza. Muchas veces las variables son números o palabras clave que estarán en un orden diferente para diferentes idiomas. Al utilizar String.Format, su código puede permanecer inalterado mientras que las diferentes cadenas irán a los archivos de recursos. Entonces, el código terminaría siendo

 String.Format(resource.GetString("MyResourceString"), str1, str2, str3); 

Mientras tus cadenas de recursos terminan siendo

Inglés: “blah blah {0} blah blah {1} blah {2}”

Ruso: “{0} blet blet blet {2} blet {1}”

Donde el ruso puede tener diferentes reglas sobre cómo se abordan las cosas, por lo que el orden es diferente o la estructura de la oración es diferente.

Primero, encuentro

 string s = String.Format( "Your order {0} will be delivered on {1:yyyy-MM-dd}. Your total cost is {2:C}.", orderNumber, orderDeliveryDate, orderCost ); 

mucho más fácil de leer, escribir y mantener que

 string s = "Your order " + orderNumber.ToString() + " will be delivered on " + orderDeliveryDate.ToString("yyyy-MM-dd") + "." + "Your total cost is " + orderCost.ToString("C") + "."; 

Mira cuánto más mantenible es el siguiente

 string s = String.Format( "Year = {0:yyyy}, Month = {0:MM}, Day = {0:dd}", date ); 

sobre la alternativa donde tendrías que repetir la date tres veces.

En segundo lugar, los especificadores de formato que ofrece String.Format brindan una gran flexibilidad sobre la salida de la cadena de una manera que es más fácil de leer, escribir y mantener que simplemente usar una antigua concatenación simple. Además, es más fácil tener preocupaciones de cultura con String.Format .

En tercer lugar, cuando el rendimiento sí importa, String.Format superará la concatenación. Detrás de escena utiliza un StringBuilder y evita el problema de Schlemiel the Painter .

Muchas rasones:

  1. String.Format () es muy poderoso. Puede usar indicadores de formato simple (como ancho fijo, moneda, longitud de caracteres, etc.) directamente en la cadena de formato. Incluso puede crear sus propios proveedores de formatos para cosas como expandir enumeraciones, asignar entradas específicas a salidas mucho más complicadas o localización.
  2. Puede hacer cosas potentes colocando cadenas de formato en los archivos de configuración.
  3. String.Format () suele ser más rápido, ya que utiliza un StringBuilder y una máquina de estado eficiente detrás de las escenas, mientras que la concatenación de cadenas en .Net es relativamente lenta. Para cadenas pequeñas, la diferencia es insignificante, pero puede ser notoria a medida que aumenta el tamaño de la cadena y el número de valores sustituidos.
  4. String.Format () es en realidad más familiar para muchos progtwigdores, especialmente los que provienen de fondos que usan variantes de la antigua printf() C printf() .

Finalmente, no olvides StringBuilder.AppendFormat() . String.Format () realmente usa este método detrás de escena, y ir directamente al StringBuilder puede darle un tipo de enfoque híbrido: use explícitamente .Append () (análogo a la concatenación) para algunas partes de una cadena grande, y úselo. AppendFormat () en otros.

String.Format agrega muchas opciones además de los operadores de concatenación, incluida la capacidad de especificar el formato específico de cada elemento agregado a la cadena.

Para obtener detalles sobre lo que es posible, recomiendo leer la sección en MSDN titulada Formato compuesto . Explica la ventaja de String.Format (así como xxx.WriteLine y otros métodos que admiten formato compuesto) sobre operadores de concatenación normales.

Hay cosas interesantes sobre los aspectos de rendimiento en esta pregunta

Sin embargo, yo personalmente aún recomendaría string.Format menos que el rendimiento sea crítico por razones de legibilidad.

 string.Format("{0}: {1}", key, value); 

Es más legible que

 key + ": " + value 

Por ejemplo. También proporciona una buena separación de preocupaciones. Significa que puedes tener

 string.Format(GetConfigValue("KeyValueFormat"), key, value); 

Y luego, cambiar el formato del valor de clave de “{0}: {1}” a “{0} – {1}” se convierte en un cambio de configuración en lugar de en un cambio de código.

string.Format también tiene un conjunto de disposiciones de formato integradas, enteros, formato de fecha, etc.

Una razón por la cual no es preferible escribir la cadena como 'string +"Value"+ string' se debe a la localización. En los casos en los que se produce la localización, queremos que la cadena localizada tenga el formato correcto, lo que podría ser muy diferente del idioma codificado.

Por ejemplo, tenemos que mostrar el siguiente error en diferentes idiomas:

 MessageBox.Show(String.Format(ErrorManager.GetError("PIDV001").Description, proposalvalue.ProposalSource) 

dónde

'ErrorCollector.GetError("ERR001").ErrorDescription' devuelve una cadena como "Your ID {0} is not valid" . Este mensaje debe estar localizado en muchos idiomas. En ese caso, no podemos usar + en C #. Necesitamos seguir a string.format.