方法: カスタム数値書式プロバイダーを定義して使用するHow to: Define and Use Custom Numeric Format Providers

.NET Framework では、数値の文字列形式を広範囲に制御できます。The .NET Framework gives you extensive control over the string representation of numeric values. 数値の書式をカスタマイズするため、次の機能をサポートしています。It supports the following features for customizing the format of numeric values:

  • 標準の数値書式指定文字列: 数値をその文字列形式に変換するための定義済みの書式セットを提供します。Standard numeric format strings, which provide a predefined set of formats for converting numbers to their string representation. これらは、format パラメーターを持つ Decimal.ToString(String) などの数値書式指定メソッドと共に使用できます。You can use them with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. 詳細については、「標準の数値書式指定文字列」を参照してください。For details, see Standard Numeric Format Strings.

  • カスタム数値書式指定文字列: カスタム数値書式指定子を定義するために結合できる記号のセットを提供します。Custom numeric format strings, which provide a set of symbols that can be combined to define custom numeric format specifiers. これらは、format パラメーターを持つ Decimal.ToString(String) などの任意の数値書式指定メソッドでも使用できます。They can also be used with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. 詳細については、「カスタム数値書式指定文字列」を参照してください。For details, see Custom Numeric Format Strings.

  • カスタムの CultureInfo オブジェクトまたは NumberFormatInfo オブジェクト: 記号を定義し、数値の文字列形式を表示するために使用されるパターンの書式を設定します。Custom CultureInfo or NumberFormatInfo objects, which define the symbols and format patterns used in displaying the string representations of numeric values. これらは、provider パラメーターを持つ ToString などの数値書式指定メソッドと共に使用できます。You can use them with any numeric formatting method, such as ToString, that has a provider parameter. 通常、provider パラメーターは、カルチャに固有の書式を指定するために使用されます。Typically, the provider parameter is used to specify culture-specific formatting.

一部の例には (アプリケーションで書式設定されたアカウント番号や ID 番号、郵便番号を表示する必要がある場合など)、これら 3 つの方法は適していません。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 では、CultureInfo オブジェクトでも NumberFormatInfo オブジェクトでもない書式設定オブジェクトを定義して、数値を書式設定する方法を決定することもできます。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. このトピックでは、このようなオブジェクトを実装するため、詳細な手順を説明し、電話番号の書式を設定する例について説明します。This topic provides the step-by-step instructions for implementing such an object, and provides an example that formats telephone numbers.

カスタム書式プロバイダーを定義するにはTo define a custom format provider

  1. IFormatProvider および ICustomFormatterインターフェイスを実装するクラスを定義します。Define a class that implements the IFormatProvider and ICustomFormatter interfaces.

  2. IFormatProvider.GetFormat メソッドを実装します。Implement the IFormatProvider.GetFormat method. GetFormat は、書式指定メソッド (String.Format(IFormatProvider, String, Object[]) メソッドなど) が実際にカスタム書式設定の実行を担当するオブジェクトを取得するために呼び出すコールバック メソッドです。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. GetFormat の一般的な実装では、次が実行されます。A typical implementation of GetFormat does the following:

    1. メソッド パラメーターとして渡される Type オブジェクトが ICustomFormatter インターフェイスを表すかどうかを決定します。Determines whether the Type object passed as a method parameter represents an ICustomFormatter interface.

    2. パラメーターが ICustomFormatter インターフェイスを表す場合、GetFormat はカスタム書式設定の提供を担当する ICustomFormatter インターフェイスを実装するオブジェクトを返します。If the parameter does represent the ICustomFormatter interface, GetFormat returns an object that implements the ICustomFormatter interface that is responsible for providing custom formatting. 通常、カスタム書式指定オブジェクトは、それ自体を返します。Typically, the custom formatting object returns itself.

    3. パラメーターが ICustomFormatter インターフェイスを表していない場合、GetFormat は、null を返します。If the parameter does not represent the ICustomFormatter interface, GetFormat returns null.

  3. Format メソッドを実装します。Implement the Format method. このメソッドは、String.Format(IFormatProvider, String, Object[]) メソッドによって呼び出され、数値の文字列形式を返します。This method is called by the String.Format(IFormatProvider, String, Object[]) method and is responsible for returning the string representation of a number. メソッドの実装には通常、次の作業を行います。Implementing the method typically involves the following:

    1. 必要に応じて、provider パラメーターを調べることで、メソッドが書式指定サービスを提供する正当なものであることを確認します。Optionally, make sure that the method is legitimately intended to provide formatting services by examining the provider parameter. IFormatProviderICustomFormatter の両方を実装する書式設定オブジェクトの場合、現在の書式設定オブジェクトと等しいことを確認するため、provider パラメーターをテストする必要があります。For formatting objects that implement both IFormatProvider and ICustomFormatter, this involves testing the provider parameter for equality with the current formatting object.

    2. 書式指定オブジェクトが、カスタム書式指定子をサポートするかどうかを決定しますDetermine whether the formatting object should support custom format specifiers. (たとえば、"N" 書式指定子は、米国の電話番号を NANP 形式で出力することを示し、"I" はITU-T 推奨 E.123 形式での出力を示すことができます)。書式指定子を使用している場合、メソッドが特定の書式指定子を処理する必要があります。(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. これが format パラメーターのメソッドに渡されます。It is passed to the method in the format parameter. 指定子がない場合、format パラメーターの値は String.Empty です。If no specifier is present, the value of the format parameter is String.Empty.

    3. arg パラメーターとしてメソッドに渡される数値を取得します。Retrieve the numeric value passed to the method as the arg parameter. 文字列形式に変換するために必要な操作を実行します。Perform whatever manipulations are required to convert it to its string representation.

    4. arg パラメーターの文字列表現を返します。Return the string representation of the arg parameter.

カスタム数値書式設定オブジェクトを使用するにはTo use a custom numeric formatting object

  1. カスタム書式指定クラスの新しいインスタンスを作成します。Create a new instance of the custom formatting class.

  2. それをカスタム書式指定オブジェクト、書式指定子 (使用されていない場合は String.Empty)、および書式設定する数値に渡す、String.Format(IFormatProvider, String, Object[]) 書式指定メソッドを呼び出します。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.

Example

次の例では、米国の電話番号を表す数値を NANP または E.123 形式に変換する、TelephoneFormatter という名前のカスタム数値書式プロバイダーを定義します。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. このメソッドは、"N" (NANP 形式を出力) と "I" (国際 E.123 形式を出力) の 2 つの書式指定子を処理します。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

カスタム数値書式プロバイダーは、String.Format(IFormatProvider, String, Object[]) メソッドのみで使用できます。The custom numeric format provider can be used only with the String.Format(IFormatProvider, String, Object[]) method. IFormatProvider 型のパラメーターがある数値書式指定メソッド (ToString など) の他のオーバーロードはすべて、NumberFormatInfo 型を表す Type オブジェクトの IFormatProvider.GetFormat 実装を渡します。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. 代わりに、これらはメソッドが NumberFormatInfo オブジェクトを返すことを期待します。In return, they expect the method to return a NumberFormatInfo object. そうでない場合、カスタム数値書式プロバイダーは無視され、現在のカルチャの NumberFormatInfo オブジェクトがその代わりに使用されます。If it does not, the custom numeric format provider is ignored, and the NumberFormatInfo object for the current culture is used in its place. この例では、メソッド パラメーターを検査し、ICustomFormatter 以外の型を表す場合には null を返すことで、TelephoneFormatter.GetFormat メソッドはそれが書式指定メソッドに不適切に渡される可能性を処理します。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.

カスタム数値書式プロバイダーが一連の書式指定子をサポートしている場合、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. 例では、"N" が既定の書式指定子です。In the example, "N" is the default format specifier. これにより、明示的な書式指定子を提供することによって、数値を書式設定された電話番号に変換できます。This allows for a number to be converted to a formatted telephone number by providing an explicit format specifier. このようなメソッドの呼び出しの例を次に示します。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))

ただし、書式指定子が存在しない場合に、変換を行うようにすることもできます。But it also allows the conversion to occur if no format specifier is present. このようなメソッドの呼び出しの例を次に示します。The following example illustrates such a method call.

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

既定の書式指定子が定義されていない場合、ICustomFormatter.Format メソッドの実装には、使用しているコードでサポートされていない書式設定を .NET が提供できるように、次のようなコードを含める必要があります。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

この例の場合、ICustomFormatter.Format を実装するメソッドは、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. そのため、formatProvider パラメーターを調べ、現在の TelephoneFormatter オブジェクトへの参照が含まれるかどうかを判断します。Therefore, it examines the formatProvider parameter to determine whether it contains a reference to the current TelephoneFormatter object. ただし、メソッドはコードから直接呼び出すこともできます。However, the method can also be called directly from code. その場合は、formatProvider パラメーターを使用して、カルチャに固有の書式情報を提供する CultureInfo オブジェクトまたは NumberFormatInfo オブジェクトを提供することができます。In that case, you can use the formatProvider parameter to provide a CultureInfo or NumberFormatInfo object that supplies culture-specific formatting information.

関連項目See also