書式指定文字列のカスタマイズ

.NET Framework では、組み込みの書式設定機構の拡張がサポートされているため、ユーザー定義の書式指定文字列を受け取る独自の ToString メソッドを作成したり、独自の Format メソッドを呼び出す書式プロバイダを作成したりして、型のカスタム書式指定を実行できます。独自の ToString メソッドを作成するには、IFormattable インターフェイスを実装します。独自の Format メソッドを作成するには、ICustomFormatter インターフェイスおよび IFormatProvider インターフェイスを実装します。

ここで説明する内容は、ユーザー定義型および既存の基本型へのカスタム書式指定文字列の追加に関するものだけですが、説明されている原則は任意の型に適用できます。

カスタム型のカスタム書式指定文字列の追加

独自のカスタム型を作成する場合は、IFormattable インターフェイスとこのインターフェイスの ToString メソッドを実装することによって、独自のカスタム書式指定文字列を処理するためのサポートを追加できます。つまり、カスタム型で認識される書式指定文字列を制御できます。カスタム型に ToString メソッドを追加するだけでなく、IFormattable インターフェイスも実装すると、ToString メソッドのユーザーは定義済みの呼び出し構文と戻り値の型を使用できるようになります。

IFormattable インターフェイスの ToString メソッドは、書式指定文字列パラメータと書式プロバイダ パラメータを受け取ります。書式指定文字列パラメータが空の文字列または null (Visual Basic では Nothing) である場合は、既定の書式設定を実行します。書式プロバイダが null である場合は、既定の書式プロバイダを使用します。

カスタム バージョンの ToString にカスタム書式指定文字列が渡された場合は、適切な書式設定を実行します。それ以外の場合は、適切な .NET Framework メソッドを呼び出して標準の書式設定を実行します。

次に示す例では、MyType カスタム型で IFormattable インターフェイスを実装します。MyType クラスの新しいインスタンスを作成し、インスタンスの ToString メソッドにカスタム書式指定文字列 "b" を渡した場合、Convert.ToString のオーバーロードはインスタンスの値を表す 2 進 (基数 2) 文字列形式を返します。"b" が渡されない場合は、インスタンスの値は独自の ToString メソッドによって書式設定されます。つまり、整数 myValueSystem.Int32.ToString メソッドによって書式設定されます。

Public Class MyType
    Implements IFormattable
    ' Assign a value for the class.
    Private myValue As Integer    
    
    ' Add a constructor.
    Public Sub New(value As Integer)
        myValue = value
    End Sub
    
    ' Write a custom Format method for the type.
    Public Overloads Function ToString(format As String, fp As IFormatProvider) As String _
    Implements IFormattable.ToString
    
        If format.Equals("b") Then
            Return Convert.ToString(myValue, 2)
        Else
            Return myValue.ToString(format, fp)
        End If
    End Function
End Class
public class MyType : IFormattable
{
    // Assign a value for the class.
    private int myValue;
    
    // Add a constructor.
    public MyType( int value )
    {
        myValue = value;
    }
    // Write a custom Format method for the type.
    public string ToString(string format, IFormatProvider fp)
    {
        if (format.Equals ("b"))
            {
            return Convert.ToString (myValue, 2);
            }
        else
            {
            return myValue.ToString(format, fp);
            }
    }
}

MyType クラスと書式指定文字列 "b" の使用方法を次の例に示します。

Dim mtype As New MyType(42)
Dim MyString As String = mtype.ToString("b", null)
Dim YourString As String = mtype.ToString("p", null)
' MyString has the value: "101010".
' YourString has the value: "42 %".
MyType mtype = new MyType(42);
String MyString = mtype.ToString("b", null);
String YourString = mtype.ToString("p", null);
// MyString has the value: "101010".
// YourString has the value: "42 %".

既存の型へのカスタム書式指定文字列の追加

既存の基本型の書式設定の方法を制御したり、書式設定用の追加コードを提供したりするには、ICustomFormatterIFormatProvider を実装する書式プロバイダ クラスを作成します。

基本型の ToString メソッドに書式プロバイダを渡すと、基本型では既定の書式プロバイダではなく、渡された書式プロバイダを使用して書式指定規則が定義されます。カスタム書式プロバイダを作成するには、次の手順に従ってください。

  1. IFormatProvider と ICustomFormatter のインターフェイスを実装し、GetFormatFormat をオーバーライドするクラスを定義します。

  2. IFormatProvider をパラメータとしてとるメソッド (String.Format など) へこのクラスを渡します。このようにクラスを渡された String.Format は、新しい書式プロバイダ クラスで定義されているカスタム書式指定スキームを認識します。

カスタム Format メソッドを追加するクラスを定義する例を次に示します。このカスタム Format メソッドは、整数のさまざまな基本値を作成するメソッドです。

Public Class MyFormat
    Implements IFormatProvider
    Implements ICustomFormatter
    
    ' String.Format calls this method to get an instance of an
    ' ICustomFormatter to handle the formatting.
    Public Function GetFormat(service As Type) As Object _
    Implements IFormatProvider.GetFormat
    
        If service.ToString() = GetType(ICustomFormatter).ToString() Then
            Return Me
        Else
            Return Nothing
        End If
    End Function
    
    ' After String.Format gets the ICustomFormatter, it calls this format
    ' method on each argument.
    Public Function Format(theformat As String, arg As Object, provider As IFormatProvider) As String _
    Implements ICustomFormatter.Format
    
        If theformat Is Nothing Then
            Return String.Format("{0}", arg)
        End If
        Dim i As Integer = theformat.Length
            ' If the object to be formatted supports the IFormattable
            ' interface, pass the format specifier to the 
            ' objects ToString method for formatting.
        If Not theformat.StartsWith("B") Then
            ' If the object to be formatted supports the IFormattable
            ' interface, pass the format specifier to the 
            ' objects ToString method for formatting.
            If TypeOf arg Is IFormattable Then
                return CType(arg, IFormattable).ToString(format, provider)
            End If
            ' If the object does not support IFormattable, 
            ' call the objects ToString method with no additional
            ' formatting. 
            ElseIf (arg Is Nothing) Then
                return arg.ToString()
            End If
        End If
        ' Uses the format string to
        ' form the output string.
        theformat = theformat.Trim(New Char() {"B"c})
        Dim b As Integer = Convert.ToInt32(theformat)
        Return Convert.ToString(CInt(arg), b)
    End Function
End Class
public class MyFormat : IFormatProvider, ICustomFormatter
{
    // String.Format calls this method to get an instance of an
    // ICustomFormatter to handle the formatting.
    public object GetFormat (Type service)
    {
        if (service == typeof (ICustomFormatter))
        {
            return this;
        }
        else
        {
            return null;
        }
    }
    // After String.Format gets the ICustomFormatter, it calls this format
    // method on each argument.
    public string Format (string format, object arg, IFormatProvider provider) 
    {
        if (format == null)
        {
            return String.Format ("{0}", arg);
        }
        // If the format is not a defined custom code,
        // use the formatting support in ToString.
        if (!format.StartsWith("B")) 
        {
            //If the object to be formatted supports the IFormattable
            //interface, pass the format specifier to the 
            //objects ToString method for formatting.
            if (arg is IFormattable) 
            {
                return ((IFormattable)arg).ToString(format, provider);
            } 
            //If the object does not support IFormattable, 
            //call the objects ToString method with no additional
            //formatting. 
            else if (arg != null) 
            {
                return arg.ToString();
            }
        }
        // Uses the format string to
        // form the output string.
        format = format.Trim (new char [] {'B'});
        int b = Convert.ToInt32 (format);
        return Convert.ToString ((int)arg, b);
    }
}

String.Format メソッドで MyFormat で定義されているカスタム Format メソッドを使用して、MyInt の base 16 表現を表示する例を次に示します。

Dim MyInt As Integer = 42
Dim MyString As String = String.Format (New MyFormat (), "{0} in the custom B16 format is {1:B16}", New Object () { MyInt, MyInt } )
' MyString has the value: "42 in custom B16 format is 2a".
int MyInt = 42;
string MyString = String.Format (new MyFormat (), "{0} in the custom B16 format is {1:B16}", new object [] { MyInt, MyInt } );
// MyString has the value: "42 in custom B16 format is 2a".

参照

関連項目

IFormattable Interface
IFormatProvider
ICustomFormatter

その他の技術情報

型の書式設定