Como: definir e usar provedores de formatos numéricos personalizadosHow to: Define and Use Custom Numeric Format Providers

O .NET Framework oferece controle abrangente sobre a representação de cadeias de caracteres de valores numéricos.The .NET Framework gives you extensive control over the string representation of numeric values. Ele dá suporte aos seguintes recursos para personalizar o formato de valores numéricos:It supports the following features for customizing the format of numeric values:

  • Cadeias de caracteres de formato numérico padrão, que fornecem um conjunto predefinido de formatos para converter números para suas representações de cadeia de caracteres.Standard numeric format strings, which provide a predefined set of formats for converting numbers to their string representation. Você pode usá-las com qualquer método de formatação numérica, como Decimal.ToString(String), que tem um parâmetro format.You can use them with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. Para obter detalhes, confira Cadeias de caracteres de formato numérico padrão.For details, see Standard Numeric Format Strings.

  • Cadeias de caracteres de formato numérico personalizado, que fornecem um conjunto de símbolos que podem ser combinados para definir especificadores de formato numérico personalizado.Custom numeric format strings, which provide a set of symbols that can be combined to define custom numeric format specifiers. Elas também podem ser usadas com qualquer método de formatação numérica, como Decimal.ToString(String), que tem um parâmetro format.They can also be used with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. Para ver detalhes, confira Cadeias de caracteres de formato numérico personalizado.For details, see Custom Numeric Format Strings.

  • Os objetos CultureInfo ou NumberFormatInfo personalizados que definem os símbolos e padrões de formato usados para exibir as representações de cadeia de caracteres de valores numéricos.Custom CultureInfo or NumberFormatInfo objects, which define the symbols and format patterns used in displaying the string representations of numeric values. Você pode usá-las com qualquer método de formatação numérica, como ToString, que tem um parâmetro provider.You can use them with any numeric formatting method, such as ToString, that has a provider parameter. Normalmente, o parâmetro provider é usado para especificar a formatação específica à cultura.Typically, the provider parameter is used to specify culture-specific formatting.

Em alguns casos (como quando um aplicativo deve exibir um número de conta formatado, um número de identificação ou um código postal) essas três técnicas são inadequadas.In some cases (such as when an application must display a formatted account number, an identification number, or a postal code) these three techniques are inappropriate. O .NET Framework também permite que você defina um objeto de formatação que não é um objeto CultureInfo ou NumberFormatInfo para determinar como um valor numérico é formatado.The .NET Framework also enables you to define a formatting object that is neither a CultureInfo nor a NumberFormatInfo object to determine how a numeric value is formatted. Este tópico fornece informações passo a passo para implementar esse tipo de objeto, bem como um exemplo que formata números de telefone.This topic provides the step-by-step instructions for implementing such an object, and provides an example that formats telephone numbers.

Para definir um provedor de formato personalizadoTo define a custom format provider

  1. Defina uma classe que implementa as interfaces IFormatProvider e ICustomFormatter.Define a class that implements the IFormatProvider and ICustomFormatter interfaces.

  2. Implementar o método de IFormatProvider.GetFormat .Implement the IFormatProvider.GetFormat method. GetFormat é um método de retorno de chamada que o método de formatação (como o método String.Format(IFormatProvider, String, Object[])) invoca para recuperar o objeto que é o responsável por executar a formatação personalizada.GetFormat is a callback method that the formatting method (such as the String.Format(IFormatProvider, String, Object[]) method) invokes to retrieve the object that is actually responsible for performing custom formatting. Uma implementação típica de GetFormat faz o seguinte:A typical implementation of GetFormat does the following:

    1. Determina se o objeto Type passado como método de parâmetro representa uma interface ICustomFormatter.Determines whether the Type object passed as a method parameter represents an ICustomFormatter interface.

    2. Se o parâmetro representar a interface ICustomFormatter, GetFormat retorna um objeto que implementa a interface ICustomFormatter que é responsável por fornecer a formatação personalizada.If the parameter does represent the ICustomFormatter interface, GetFormat returns an object that implements the ICustomFormatter interface that is responsible for providing custom formatting. Normalmente, o objeto de formatação personalizado retorna a si próprio.Typically, the custom formatting object returns itself.

    3. Se o parâmetro não representar a interfaceICustomFormatter, GetFormat retorna null.If the parameter does not represent the ICustomFormatter interface, GetFormat returns null.

  3. Implementar o método de Format .Implement the Format method. Este método é chamado pelo método String.Format(IFormatProvider, String, Object[]) e é responsável por retornar a representação de cadeia de caracteres de um número.This method is called by the String.Format(IFormatProvider, String, Object[]) method and is responsible for returning the string representation of a number. Implementar o método normalmente envolve o seguinte:Implementing the method typically involves the following:

    1. Opcionalmente, verifique se o método é legitimamente destinado a fornecer serviços de formatação examinando o parâmetro provider.Optionally, make sure that the method is legitimately intended to provide formatting services by examining the provider parameter. Para formatar objetos que implementam IFormatProvider e ICustomFormatter, isso envolve testar o parâmetro provider para igualdade com o objeto de formatação atual.For formatting objects that implement both IFormatProvider and ICustomFormatter, this involves testing the provider parameter for equality with the current formatting object.

    2. Determine se o objeto de formatação deve dar suporte a especificadores de formato personalizado.Determine whether the formatting object should support custom format specifiers. (Por exemplo, um especificador de formato "N" pode indicar que um número de telefone dos EUA deve ser gerado no formato NANP e um "I" pode indicar a saída no formato E. 123 da Recomendação ITU-T.) Se especificadores de formato forem usados, o método deve tratar o especificador de formato específico.(For example, an "N" format specifier might indicate that a U.S. telephone number should be output in NANP format, and an "I" might indicate output in ITU-T Recommendation E.123 format.) If format specifiers are used, the method should handle the specific format specifier. Ele é passado para o método no parâmetro format.It is passed to the method in the format parameter. Se nenhum especificador estiver presente, o valor do parâmetro format será String.Empty.If no specifier is present, the value of the format parameter is String.Empty.

    3. Recupere o valor numérico passado para o método como o parâmetro arg.Retrieve the numeric value passed to the method as the arg parameter. Execute as manipulações que forem necessárias para convertê-lo em sua representação de cadeia de caracteres.Perform whatever manipulations are required to convert it to its string representation.

    4. Retorne a representação de cadeia de caracteres do parâmetro arg.Return the string representation of the arg parameter.

Para usar um objeto de formatação numérico personalizadoTo use a custom numeric formatting object

  1. Crie uma nova instância da classe de formatação personalizada.Create a new instance of the custom formatting class.

  2. Chame o método de formatação String.Format(IFormatProvider, String, Object[]) e passe para ele o objeto de formatação personalizado, o especificador de formatação (ou String.Empty, se um não for usado) e o valor numérico a ser formatado.Call the String.Format(IFormatProvider, String, Object[]) formatting method, passing it the custom formatting object, the formatting specifier (or String.Empty, if one is not used), and the numeric value to be formatted.

ExemploExample

O exemplo a seguir define um provedor de formato numérico personalizado chamado TelephoneFormatter, que converte um número que representa um número de telefone dos EUA para seu formato NANP ou E.123.The following example defines a custom numeric format provider named TelephoneFormatter that converts a number that represents a U.S. telephone number to its NANP or E.123 format. O método lida com dois especificadores de formato, "N" (que gera o formato NANP) e "I" (que gera o formato internacional E.123).The method handles two format specifiers, "N" (which outputs the NANP format) and "I" (which outputs the international E.123 format).

using System;
using System.Globalization;

public class TelephoneFormatter : IFormatProvider, ICustomFormatter
{
   public object GetFormat(Type formatType)
   {
      if (formatType == typeof(ICustomFormatter))
         return this;
      else
         return null;
   }               

   public string Format(string format, object arg, IFormatProvider formatProvider)
   {
      // Check whether this is an appropriate callback             
      if (! this.Equals(formatProvider))
         return null; 

      // Set default format specifier             
      if (string.IsNullOrEmpty(format)) 
         format = "N";

      string numericString = arg.ToString();
      
      if (format == "N")
      {
         if (numericString.Length <= 4)
            return numericString;
         else if (numericString.Length == 7)
            return numericString.Substring(0, 3) + "-" + numericString.Substring(3, 4); 
         else if (numericString.Length == 10)
               return "(" + numericString.Substring(0, 3) + ") " +
                      numericString.Substring(3, 3) + "-" + numericString.Substring(6);   
         else
            throw new FormatException( 
                      string.Format("'{0}' cannot be used to format {1}.", 
                                    format, arg.ToString()));
      }
      else if (format == "I")
      {
         if (numericString.Length < 10)
            throw new FormatException(string.Format("{0} does not have 10 digits.", arg.ToString()));
         else
            numericString = "+1 " + numericString.Substring(0, 3) + " " + numericString.Substring(3, 3) + " " + numericString.Substring(6);
      }
      else
      {
         throw new FormatException(string.Format("The {0} format specifier is invalid.", format));
      } 
      return numericString;  
   }
}

public class TestTelephoneFormatter
{
   public static void Main()
   {
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 0));
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 911));
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 8490216));
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 4257884748));
      
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 0));
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 911));
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 8490216));
      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));

      Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:I}", 4257884748));
   }
}
Public Class TelephoneFormatter : Implements IFormatProvider, ICustomFormatter
   Public Function GetFormat(formatType As Type) As Object _
                   Implements IFormatProvider.GetFormat
      If formatType Is GetType(ICustomFormatter) Then
         Return Me
      Else
         Return Nothing
      End If               
   End Function               

   Public Function Format(fmt As String, arg As Object, _
                          formatProvider As IFormatProvider) As String _
                   Implements ICustomFormatter.Format
      ' Check whether this is an appropriate callback             
      If Not Me.Equals(formatProvider) Then Return Nothing 

      ' Set default format specifier             
      If String.IsNullOrEmpty(fmt) Then fmt = "N"

      Dim numericString As String = arg.ToString
      
      If fmt = "N" Then
         Select Case numericString.Length
            Case <= 4 
               Return numericString
            Case 7
               Return Left(numericString, 3) & "-" & Mid(numericString, 4) 
            Case 10
               Return "(" & Left(numericString, 3) & ") " & _
                      Mid(numericString, 4, 3) & "-" & Mid(numericString, 7)   
            Case Else
               Throw New FormatException( _
                         String.Format("'{0}' cannot be used to format {1}.", _
                                       fmt, arg.ToString()))
         End Select
      ElseIf fmt = "I" Then
         If numericString.Length < 10 Then
            Throw New FormatException(String.Format("{0} does not have 10 digits.", arg.ToString()))
         Else
            numericString = "+1 " & Left(numericString, 3) & " " & Mid(numericString, 4, 3) & " " & Mid(numericString, 7)
         End If      
      Else
         Throw New FormatException(String.Format("The {0} format specifier is invalid.", fmt))
      End If 
      Return numericString  
   End Function
End Class

Public Module TestTelephoneFormatter
   Public Sub Main
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 0))
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 911))
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 8490216))
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 4257884748))
      
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 0))
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 911))
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 8490216))
      Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))

      Console.WriteLine(String.Format(New TelephoneFormatter, "{0:I}", 4257884748))
   End Sub
End Module

O provedor de formato numérico personalizado pode ser usado apenas com o método String.Format(IFormatProvider, String, Object[]).The custom numeric format provider can be used only with the String.Format(IFormatProvider, String, Object[]) method. As outras sobrecargas de métodos de formatação numérica (como ToString) que têm um parâmetro do tipo IFormatProvider passam para a implementação IFormatProvider.GetFormat um objeto Type que representa o tipo NumberFormatInfo.The other overloads of numeric formatting methods (such as ToString) that have a parameter of type IFormatProvider all pass the IFormatProvider.GetFormat implementation a Type object that represents the NumberFormatInfo type. Por sua vez, eles esperam que o método retorne um objeto NumberFormatInfo.In return, they expect the method to return a NumberFormatInfo object. Se isso não acontecer, o provedor de formato numérico personalizado será ignorado e o objeto NumberFormatInfo da cultura atual será usada em seu lugar.If it does not, the custom numeric format provider is ignored, and the NumberFormatInfo object for the current culture is used in its place. No exemplo, o método TelephoneFormatter.GetFormat trata da possibilidade de ele ser passado inadequadamente para um método de formatação numérico examinando o parâmetro do método e retornando null se ele representar um tipo diferente de ICustomFormatter.In the example, the TelephoneFormatter.GetFormat method handles the possibility that it may be inappropriately passed to a numeric formatting method by examining the method parameter and returning null if it represents a type other than ICustomFormatter.

Se um provedor de formato numérico personalizado der suporte a um conjunto de especificadores de formato, forneça um comportamento padrão se nenhum especificador de formato for fornecido no item de formato usado na chamada de método String.Format(IFormatProvider, String, Object[]).If a custom numeric format provider supports a set of format specifiers, make sure you provide a default behavior if no format specifier is supplied in the format item used in the String.Format(IFormatProvider, String, Object[]) method call. No exemplo, "N" é o especificador de formato padrão.In the example, "N" is the default format specifier. Isso permite que um número a ser convertido em um número de telefone formatado, fornecendo um especificador de formato explícito.This allows for a number to be converted to a formatted telephone number by providing an explicit format specifier. O exemplo a seguir ilustra essa chamada de método.The following example illustrates such a method call.

Console.WriteLine(String.Format(new TelephoneFormatter(), "{0:N}", 4257884748));
Console.WriteLine(String.Format(New TelephoneFormatter, "{0:N}", 4257884748))

Mas também permite que a conversão ocorra se nenhum especificador de formato estiver presente.But it also allows the conversion to occur if no format specifier is present. O exemplo a seguir ilustra essa chamada de método.The following example illustrates such a method call.

Console.WriteLine(String.Format(new TelephoneFormatter(), "{0}", 4257884748));
Console.WriteLine(String.Format(New TelephoneFormatter, "{0}", 4257884748))

Se nenhum especificador de formato padrão for definido, sua implementação do método ICustomFormatter.Format deve incluir código como o seguinte para que o .NET possa fornecer a formatação a que seu código não dá suporte.If no default format specifier is defined, your implementation of the ICustomFormatter.Format method should include code such as the following so that .NET can provide formatting that your code does not support.

if (arg is IFormattable) 
   s = ((IFormattable)arg).ToString(format, formatProvider);
else if (arg != null)    
   s = arg.ToString();
If TypeOf(arg) Is IFormattable Then 
   s = DirectCast(arg, IFormattable).ToString(fmt, formatProvider)
ElseIf arg IsNot Nothing Then    
   s = arg.ToString()
End If

No caso deste exemplo, o método que implementa ICustomFormatter.Format se destina a servir como um método de retorno de chamada para o método String.Format(IFormatProvider, String, Object[]).In the case of this example, the method that implements ICustomFormatter.Format is intended to serve as a callback method for the String.Format(IFormatProvider, String, Object[]) method. Portanto, ele examina o parâmetro formatProvider para determinar se ele contém uma referência ao objeto TelephoneFormatter atual.Therefore, it examines the formatProvider parameter to determine whether it contains a reference to the current TelephoneFormatter object. No entanto, o método também pode ser chamado diretamente do código.However, the method can also be called directly from code. Nesse caso, você pode usar o parâmetro formatProvider para fornecer um objeto CultureInfo ou NumberFormatInfo que fornece informações de formatação específicas da cultura.In that case, you can use the formatProvider parameter to provide a CultureInfo or NumberFormatInfo object that supplies culture-specific formatting information.

Consulte tambémSee also