A Interface IFormattable: O Coração da Formatação em C
Você já se perguntou como é possível formatar um número como moeda (meuDecimal:C
) ou uma data em um formato específico (minhaData:dd/MM/yyyy
)? A "mágica" por trás disso é a interface IFormattable
.
O que é IFormattable?
IFormattable
é uma interface fundamental no .NET que fornece um mecanismo para formatar o valor de um objeto em uma representação de string personalizada. Qualquer tipo que implementa esta interface pode ser formatado usando:
- Strings de formato: Códigos como "C" (moeda), "P" (percentual), "N2" (número com 2 casas decimais), "yyyy-MM-dd" (data), etc.
- Provedores de formato: Objetos que fornecem informações de formatação específicas de uma cultura (como
CultureInfo
), definindo se o separador decimal é.
ou,
, qual o símbolo da moeda, etc.
A Assinatura da Interface
A interface IFormattable
é surpreendentemente simples. Ela define apenas um método:
string ToString(string format, IFormatProvider formatProvider);
format
: Uma string que especifica o formato desejado. Se fornull
ou vazia, o formato geral (padrão) do tipo deve ser usado.formatProvider
: Um objeto que fornece informações de formatação cultural. Geralmente, é uma instância deCultureInfo
.
Quando você escreve valor.ToString("C")
ou usa a interpolação {valor:C}
, o compilador, nos bastidores, chama uma versão de ToString
que eventualmente usa a cultura atual como formatProvider
.
Exemplo Prático: Criando um Tipo Formatável
Vamos ver como funciona criando nossa própria classe que implementa IFormattable
. Criaremos uma classe Temperature
que pode ser exibida em Celsius, Fahrenheit ou Kelvin.
using System;
using System.Globalization;
public class Temperature : IFormattable
{
private decimal temp;
public Temperature(decimal temperature)
{
this.temp = temperature;
}
// Método da interface IFormattable
public string ToString(string format, IFormatProvider formatProvider)
{
// Se nenhum formato for fornecido, use 'C' (Celsius) como padrão.
if (string.IsNullOrEmpty(format)) format = "C";
// Usa o formatProvider padrão se nenhum for fornecido.
if (formatProvider == null) formatProvider = CultureInfo.CurrentCulture;
switch (format.ToUpperInvariant())
{
case "C": // Celsius
return temp.ToString("F2", formatProvider) + " °C";
case "F": // Fahrenheit
return ((temp * 9 / 5) + 32).ToString("F2", formatProvider) + " °F";
case "K": // Kelvin
return (temp + 273.15m).ToString("F2", formatProvider) + " K";
default:
throw new FormatException($"O formato '{format}' não é suportado.");
}
}
// Sobrescrevendo o ToString() padrão para um comportamento simples
public override string ToString()
{
return this.ToString("C", CultureInfo.CurrentCulture);
}
}
Como Usar
var temp = new Temperature(25.123m);
Console.WriteLine($"Temperatura Padrão: {temp}"); // Usa o ToString() padrão
Console.WriteLine($"Temperatura em Fahrenheit: {temp:F}"); // Usa o IFormattable
Console.WriteLine($"Temperatura em Kelvin: {temp:K}"); // Usa o IFormattable
Conclusão
A interface IFormattable
é o pilar que permite a formatação rica e flexível em .NET. Todos os tipos que você já formatou (int
, double
, decimal
, DateTime
, DateTimeOffset
, Guid
, Enum
, etc.) implementam esta interface.
Entendê-la ajuda a desmistificar como a formatação funciona e abre a porta para criar seus próprios tipos de dados que se integram perfeitamente ao sistema de formatação do C#.