Procedimiento para definir y usar proveedores de formato numérico personalizadoHow to: Define and Use Custom Numeric Format Providers

.NET Framework ofrece un amplio control sobre la representación de cadena de valores numéricos.The .NET Framework gives you extensive control over the string representation of numeric values. Admite las siguientes características para personalizar el formato de los valores numéricos:It supports the following features for customizing the format of numeric values:

  • Cadenas con formato numérico estándar, que proporcionan un conjunto predefinido de formatos para convertir números en su representación de cadena.Standard numeric format strings, which provide a predefined set of formats for converting numbers to their string representation. Se pueden usar con cualquier método de formato numérico, como Decimal.ToString(String), que tiene un parámetro format.You can use them with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. Para obtener detalles, vea Cadenas con formato numérico estándar.For details, see Standard Numeric Format Strings.

  • Cadenas con formato numérico personalizado, que proporcionan un conjunto de símbolos que pueden combinarse 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. Se pueden usar también con cualquier método de formato numérico, como Decimal.ToString(String), que tiene un parámetro format.They can also be used with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. Para obtener detalles, consulte Cadenas con formato numérico personalizado.For details, see Custom Numeric Format Strings.

  • Objetos personalizados CultureInfo o NumberFormatInfo, que definen los símbolos y los modelos de formato que se usan para mostrar las representaciones de cadena 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. Se pueden usar con cualquier método de formato numérico, como ToString, que tiene un parámetro provider.You can use them with any numeric formatting method, such as ToString, that has a provider parameter. Normalmente, el parámetro provider se usa para especificar el formato específico de la referencia cultural.Typically, the provider parameter is used to specify culture-specific formatting.

En algunos casos (por ejemplo, cuando una aplicación debe mostrar un número de cuenta con formato, un número de identificación o un código postal) estas tres técnicas no resultan apropiadas.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. .NET Framework también permite definir un objeto de formato que no es ni un objeto CultureInfo ni NumberFormatInfo para determinar cómo se aplica formato a un valor numérico.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. En este tema se proporcionan instrucciones paso a paso para implementar este tipo de objeto y se ofrece un ejemplo que da formato a números de teléfono.This topic provides the step-by-step instructions for implementing such an object, and provides an example that formats telephone numbers.

Para definir un proveedor de formato personalizadoTo define a custom format provider

  1. Defina una clase que implementa las interfaces IFormatProvider y ICustomFormatter.Define a class that implements the IFormatProvider and ICustomFormatter interfaces.

  2. Implemente el método IFormatProvider.GetFormat.Implement the IFormatProvider.GetFormat method. GetFormat es un método de devolución de llamada que el método de formato (como el método String.Format(IFormatProvider, String, Object[])) invoca para recuperar el objeto realmente responsable del formato personalizado.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. Una implementación típica de GetFormat hace lo siguiente:A typical implementation of GetFormat does the following:

    1. Determina si el objeto Type pasado como un parámetro de método representa a una interfaz ICustomFormatter.Determines whether the Type object passed as a method parameter represents an ICustomFormatter interface.

    2. Si el parámetro representa a la interfaz ICustomFormatter, GetFormat devuelve un objeto que implementa la interfaz ICustomFormatter, que es responsable de proporcionar el formato personalizado.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, el objeto de formato personalizado se devuelve a sí mismo.Typically, the custom formatting object returns itself.

    3. Si el parámetro no representa la interfaz ICustomFormatter, GetFormat devuelve null.If the parameter does not represent the ICustomFormatter interface, GetFormat returns null.

  3. Implemente el método Format.Implement the Format method. Este método es invocado por el método String.Format(IFormatProvider, String, Object[]) y es responsable de devolver la representación de cadena de un 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. La implementación del método normalmente implica lo siguiente:Implementing the method typically involves the following:

    1. Opcionalmente, asegúrese de que el método se haya diseñado para proporcionar servicios de formato al examinar el parámetro provider.Optionally, make sure that the method is legitimately intended to provide formatting services by examining the provider parameter. En el caso de los objetos de formato que implementan IFormatProvider y ICustomFormatter, esto implica probar la igualdad del parámetro provider y el objeto de formato actual.For formatting objects that implement both IFormatProvider and ICustomFormatter, this involves testing the provider parameter for equality with the current formatting object.

    2. Determine si el objeto de formato debe admitir especificadores de formato personalizado.Determine whether the formatting object should support custom format specifiers. (Por ejemplo, un especificador de formato "N" podría indicar que debe generarse un número de teléfono de los Estados Unidos en formato NANP, mientras que una "I" podría indicar la salida en el formato de la recomendación E.123 de ITU-T). Si se usan especificadores de formato, el método debe controlar el 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. Se pasa al método en el parámetro format.It is passed to the method in the format parameter. Si no hay ningún especificador, el valor del parámetro format es String.Empty.If no specifier is present, the value of the format parameter is String.Empty.

    3. Recupere el valor numérico pasado al método como parámetro arg.Retrieve the numeric value passed to the method as the arg parameter. Realice todas las manipulaciones necesarias para convertirlo en su representación de cadena.Perform whatever manipulations are required to convert it to its string representation.

    4. Devuelva la representación de cadena del parámetro arg.Return the string representation of the arg parameter.

Para usar un objeto de formato numérico personalizadoTo use a custom numeric formatting object

  1. Cree una nueva instancia de la clase de formato personalizado.Create a new instance of the custom formatting class.

  2. Llame al método de formato String.Format(IFormatProvider, String, Object[]) y pásele el objeto de formato personalizado, el especificador de formato (o String.Empty si no se usa ninguno) y el valor numérico al que se va a dar formato.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.

EjemploExample

En el ejemplo siguiente se define un proveedor de formato numérico personalizado denominado TelephoneFormatter que convierte un número que representa un número de teléfono de los Estados Unidos en su formato NANP o 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. El método controla dos especificadores de formato, "N" (que genera el formato NANP) e "I" (que genera el formato E.123 internacional).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

El proveedor de formato numérico personalizado puede utilizarse solo con el método String.Format(IFormatProvider, String, Object[]).The custom numeric format provider can be used only with the String.Format(IFormatProvider, String, Object[]) method. Las demás sobrecargas de métodos de formato numérico (como ToString) que tienen un parámetro de tipo IFormatProvider pasan a la implementación de IFormatProvider.GetFormat un objeto Type que representa al 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. A cambio, esperan que el método devuelva un objeto NumberFormatInfo.In return, they expect the method to return a NumberFormatInfo object. Si no es así, se omite el proveedor de formato numérico personalizado y se usa el objeto NumberFormatInfo de la referencia cultural actual en su 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. En el ejemplo, el método TelephoneFormatter.GetFormat controla la posibilidad de que se pueda pasar incorrectamente a un método de formato numérico al examinar el parámetro de método y devolver null si representa a un tipo distinto 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.

Si un proveedor de formato numérico personalizado admite un conjunto de especificadores de formato, asegúrese de proporcionar un comportamiento predeterminado si no se proporciona ningún especificador de formato en el elemento de formato usado en la llamada al 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. En el ejemplo, "N" es el especificador de formato predeterminado.In the example, "N" is the default format specifier. Esto permite convertir un número en un número de teléfono con formato al proporcionar un especificador de formato explícito.This allows for a number to be converted to a formatted telephone number by providing an explicit format specifier. En el ejemplo siguiente se muestra una llamada al método así.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))

Pero también permite que se produzca la conversión si no hay ningún especificador de formato.But it also allows the conversion to occur if no format specifier is present. En el ejemplo siguiente se muestra una llamada al método así.The following example illustrates such a method call.

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

Si no se ha definido ningún especificador de formato predeterminado, la implementación del método ICustomFormatter.Format debe incluir código como el siguiente para que .NET pueda proporcionar formato no admitido por el código.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

En el caso de este ejemplo, el método que implementa ICustomFormatter.Format está diseñado para que actúe como un método de devolución de llamada para el 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. Por lo tanto, examina el parámetro formatProvider para determinar si contiene una referencia al objeto TelephoneFormatter actual.Therefore, it examines the formatProvider parameter to determine whether it contains a reference to the current TelephoneFormatter object. Pero también se puede llamar al método directamente desde el código.However, the method can also be called directly from code. En ese caso, puede usar el parámetro formatProvider para proporcionar un objeto CultureInfo o NumberFormatInfo que aporte información de formato específica de la referencia cultural.In that case, you can use the formatProvider parameter to provide a CultureInfo or NumberFormatInfo object that supplies culture-specific formatting information.

Vea tambiénSee also