String.Format: cómo funciona y cómo implementar cadenas de formato personalizadas


79

Con String.Format()es posible formatear, por ejemplo, DateTimeobjetos de muchas formas diferentes. Cada vez que busco un formato deseado, necesito buscar en Internet. Casi siempre encuentro un ejemplo que puedo usar. Por ejemplo:

String.Format("{0:MM/dd/yyyy}", DateTime.Now);          // "09/05/2012"

Pero no tengo ni idea de cómo funciona y qué clases admiten estas cadenas adicionales "mágicas".

Entonces mis preguntas son:

  1. ¿Cómo String.Formatasigna la información adicional MM/dd/yyyya un resultado de cadena?
  2. ¿Todos los objetos de Microsoft admiten esta función?
    ¿Está esto documentado en alguna parte?
  3. ¿Es posible hacer algo como esto?
    String.Format("{0:MyCustomFormat}", new MyOwnClass())

Respuestas:


88

String.Formathace coincidir cada uno de los tokens dentro de la cadena ( {0}etc.) con el objeto correspondiente: http://msdn.microsoft.com/en-us/library/system.string.format.aspx

Se proporciona opcionalmente una cadena de formato:

{ index[,alignment][ : formatString] }

Si formatStringse proporciona, el objeto correspondiente debe implementar IFormattable y específicamente el ToStringmétodo que acepta formatStringy devuelve la cadena formateada correspondiente: http://msdn.microsoft.com/en-us/library/system.iformattable.tostring.aspx

También se IFormatProviderpuede usar un que se puede usar para capturar estándares / valores predeterminados de formato básico, etc. Ejemplos aquí y aquí .

Entonces las respuestas a sus preguntas en orden:

  1. Utiliza el método de la IFormattableinterfaz ToString()en el DateTimeobjeto y le pasa la MM/dd/yyyycadena de formato. Es esa implementación la que devuelve la cadena correcta.

  2. Cualquier objeto que implemente IFormattableadmite esta característica. ¡Incluso puedes escribir el tuyo!

  3. Sí, ver arriba.


11
+1 para vincular a la documentación . "Buscar en Internet" puede estar bien. Pero cuando necesite una comprensión más profunda, debe leer el manual.
MarkJ

Buena respuesta, pero ¿puede decirme dónde puedo encontrar para cada clase que implementa IFormattable, dónde puedo encontrar los formatStrings permitidos. Por ejemplo, DateTime admite (en la parte superior de mi cabeza) y M d h m sy más. Los tipos numéricos son compatibles Ccon la moneda, pero eso no es todo lo que sé al buscar alrededor y no al mirar la documentación de Microsoft.
hwcverwe

@hwcverwe: casi cualquier búsqueda de Google colocará la documentación de MSDN en o cerca de la parte superior de una búsqueda de cualquier objeto. No habrá una sola página que muestre el ToString (...) para cada objeto - hay potencialmente una cantidad "infinita" de ellos, porque por defecto todos los objetos implementan al menos ToString (), aunque no necesariamente ToString (formato).
Wonko the Sane


20

Según tengo entendido, necesitaría implementar IFormattable en su clase para respaldar esto. Eso luego tiene el método, ToString, que toma los parámetros que pasa a String.Format.

Aquí hay un ejemplo.

// Define other methods and classes here
public class Sample : IFormattable
{
     public string ToString(string format, IFormatProvider provider)
     {
         return String.Concat("Your custom format was ", format);
     }
}

String.Format("{0:MyCustomFormat}", new Sample())

5
  1. Consulte los documentos oficiales de MSDN, hay una lista completa de cadenas de formato DateTime aquí: http://msdn.microsoft.com/en-us/library/az4se3k1.aspx . De hecho, hay bastantes cadenas "mágicas".

  2. Hasta donde yo sé, no todos los tipos tienen un formato "interesante", pero todos los tipos son compatibles ToString(). Si necesita formatear un objeto incorporado, puede agregar un método de extensión para hacerlo, pero generalmente el formato se proporciona en cualquier lugar donde sea necesario (o para decirlo de otra manera, solo he escrito formateadores personalizados para mis propios tipos) .

  3. Sí, puede escribir el suyo propio y si tiene datos que se pueden formatear de diferentes maneras, probablemente debería escribir un formateador personalizado implementando IFormattable, nuevamente vea los documentos aquí: http://msdn.microsoft.com/en-us/ biblioteca / system.iformattable.aspx . Es bastante simple, simplemente verifica las cadenas proporcionadas y escribe tus datos en función de estas, no hay magia detrás de escena :-)


4

Debajo de las cubiertas, String.Format hace algo de la siguiente manera,

IFormattable formattable = objectToFormat as IFormattable;
if (formattable != null)
{
    formattable.ToString(objectToFormat);
}
else
{
    objectToFormat.ToString();
}

Para sus preguntas,

  1. ¿Cómo asigna String.Format la información adicional MM / dd / aaaa a un resultado de cadena?

    Como se especificó anteriormente, solo llama a IFormattable .ToString (formato de cadena, proveedor IFormatProvider). El proveedor suele ser algo que le dice cuál es la cultura de su sistema. A menudo es nulo porque la gente no lo pasa String.Format () como lo hizo en su caso.

  2. ¿Todos los objetos de Microsoft admiten esta función? ¿Está esto documentado en alguna parte?

    Cualquier cosa que implemente IFormattable lo hace.

  3. ¿Es posible hacer algo como esto? String.Format("{0:MyCustomFormat}, new MyOwnClass())

    Básicamente, si desea que su propio objeto haga algo con el formato proporcionado que implementa IFormattable.

Hay una gran cantidad de clases de apoyo y enumeradores para garantizar que las cadenas de formato sean muy similares. Más aquí .


0

Sí, es posible, se puede personalizar por completo. Mire este enlace de documentación sobre el formato personalizado de fecha y hora.

Si tiene su propio objeto, depende de usted anular el ToString()método y generar lo que crea que es la representación adecuada. Una vez que haga esto, puede usar String.Format("{0:MyCustomFormat}", new MyOwnClass())porque esto llama implícitamenteMyOwnClass.ToString()


-1 - El OP está preguntando por más que DateTimeformatear. Y solo un enlace no es una respuesta.
Oded

1
Muy duro. DateTime es uno de los aspectos y estaba ampliando mi respuesta mientras votaba negativamente.
Maciej

6
Expanda la respuesta y luego publique , y no recibirá una votación negativa.
Oded

0

La documentación de las fechas se puede encontrar aquí: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

Eso debería decirle exactamente qué significan todos los caracteres de formato de fecha como MM.

Si desea cambiar la forma en que se genera una cadena para una clase personalizada, puede anular el método ToString, así:

public class User
{
     public string Name { get; set; }
     public int Age { get; set; }

     public override string ToString()
     {
         return this.Name + " is " + this.Age + " years old.";
     }
}

y luego puede hacer algo como myUser.ToString()y obtener la salida que especificó.


0

Y para responder a su tercera pregunta: eso no es posible con esta sintaxis, pero puede proporcionar instancias de IFormatProvidery ICustomFormatterpara un tipo que no creó, o implementar IFormattabledentro de su tipo (aunque, básicamente, eso se extiende ToString).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.