Diferencia entre usar String.Format y ToString

Hoy cuando he llegado al trabajo me he hecho una de esas preguntas que rápidamente me hacen abrir el VS tirar unas líneas de código y comprobar el IL a ver que ocurre.

La pregunta que me he hecho hoy es:

¿Que diferencia existe entre usar String.Format y ToString?

Para ello he hecho este programita:

   1:  using System;
   2:   
   3:  namespace PruebasBoxing
   4:  {
   5:      /// <summary>
   6:      /// Descripción breve de Test.
   7:      /// </summary>
   8:      public class Test
   9:      {
  10:          [STAThread]
  11:          static void Main(string[] args)
  12:          {
  13:              double d = 12.45;
  14:              string formato1 = String.Format("{0:C}", d);
  15:              string formato2 = d.ToString("C");
  16:          }
  17:      }
  18:  }

Y el ensamblado lo he abierto con ildasm:

   1:  .method private hidebysig static void  Main(string[] args) cil managed
   2:  {
   3:    .entrypoint
   4:    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
   5:    // Code size       41 (0x29)
   6:    .maxstack  2
   7:    .locals init ([0] float64 d,
   8:             [1] string formato1,
   9:             [2] string formato2)
  10:    IL_0000:  ldc.r8     12.449999999999999
  11:    IL_0009:  stloc.0
  12:    IL_000a:  ldstr      "{0:C}"
  13:    IL_000f:  ldloc.0
  14:    IL_0010:  box        [mscorlib]System.Double
  15:    IL_0015:  call       string [mscorlib]System.String::Format(string,
  16:                                                                object)
  17:    IL_001a:  stloc.1
  18:    IL_001b:  ldloca.s   d
  19:    IL_001d:  ldstr      "C"
  20:    IL_0022:  call       instance string [mscorlib]System.Double::ToString(string)
  21:    IL_0027:  stloc.2
  22:    IL_0028:  ret
  23:  } // end of method Test::Main

Si nos fijamos en la línea 14 se está haciendo un boxing del double con lo que se está creando un nuevo tipo referenciado que se pasa a la función String.Format que como vemos recibe un object, y como sabemos este boxing produce una sobrecarga que además hace que el GC sea necesario para limpiar esa referencia cuando deje de utilizarse, cosa que con ToString no ocurre.

Salu2.

Published 11/1/2007 9:25 por Luis Ruiz Pavón
Comparte este post:
http://geeks.ms/blogs/lruiz/archive/2007/01/11/diferencia-entre-usar-string-format-y-tostring.aspx

Comentarios

# re: Diferencia entre usar String.Format y ToString

Hola Luis,

Lo que indicas es cierto, pero no del todo correcto... el problema es que los tipos primitivos (int, double, etc etc etc) no son objetos y estan en el thread stack, sin referencias a objetos.

El metodo String.Format acepta parametros de tipo Object y por tanto, al ser objetos, requieren una referencia en la Managed Heap. La forma de conseguir esto es haciendo boxing del objeto (que hay que intentar evitar)

Sin embargo, lo que produce el boxing es la conversion del tipo double a string ... no por la conversión en si, sino por meterlo dentro de un Object (que es lo que String.Format necesita) ... sin embargo, si cambias la linea por esta:

string formato1 = String.Format("{0}", d.ToString());

la llamada a String.Format sigue siendo la misma, pero ya no se producira el Box, porque el objeto que devuelve ToString es de tipo Object.

Tengo un post inacabado sobre boxing, unboxing, tipos por valor, por referencia, thread stack y managed heap... era un poco largo y por eso no lo publique. Igual lo termino.

Thursday, January 11, 2007 11:50 AM por Miguel Jimenez

# re: Diferencia entre usar String.Format y ToString

Buenas Miguel, me gusta que la gente se anime y opine en los post, porque así se se pueden aprender muchas cosas.

En referencia a la línea de código que comentas he de decirte que al probarla me he encontrado con esto:

string formato1 = String.Format("{0:C}", d.ToString());

Salida: 12,45

string formato1 = String.Format("{0:C}", d);

Salida: 12,45 €

Era sólo una curiosidad.

Salu2 y gracias por tu comentario Miguel.

Thursday, January 11, 2007 12:02 PM por Luis Ruiz Pavón

# re: Diferencia entre usar String.Format y ToString

De nada... era solo por denotar que la culta no es del string.format, sino de como se le llama.

El format C sin un numero, no hace ni caso jejeje :) solo hay que buscar un tipo que herede object y que no haga el boxing y sea numerico... pongamos por ejemplo, el System.Double con la d en mayuscula. Digamos que la primitiva double, es una referencia la clase System.Double, float a System.Single, string a System.String, etc etc etc..

Esos ya son objetos, asi que no deberia hacer el boxing

Thursday, January 11, 2007 12:08 PM por Miguel Jimenez

# re: Diferencia entre usar String.Format y ToString

Miguel acabo de probar con System.Double:

Double d = 12.45;

string formato1 = String.Format("{0:C}", d);

resultado IL:

IL_0010:  box        [mscorlib]System.Double

System.Double es struct y es un tipo por valor, así que hace Boxing.

Salu2

Thursday, January 11, 2007 12:43 PM por Luis Ruiz Pavón

# re: Diferencia entre usar String.Format y ToString

cual es la diferrencia de usar String con 'S' mayuscula y string 's' letra minuscula

Thursday, January 18, 2007 9:58 PM por nick

# re: Diferencia entre usar String.Format y ToString

Es lo mismo porque si te das cuenta el compilador reemplaza string por System.String aunque yo siempre he oido que string es el dato primitivo y String es el evolvente del tipo primitivo string.

Que me corrija alguien si me equivoco.

Salu2

Friday, January 19, 2007 12:07 PM por Luis Ruiz Pavón

# re: Diferencia entre usar String.Format y ToString

Abundando en el tema de las diferencias entre String.Format y ToString hay un tipo de formato que puedo hacer con String.Format pero no consigo hacerlo con ToString:

string s = String.Format("{0,12:N4}", 123.456)

4 son los decimales y 12 es el ancho total alineándose a la derecha

¿Sabéis si se puede hacer lo mismo con ToString?

Saturday, February 10, 2007 2:23 AM por Juan