書式指定文字列のカスタマイズ
更新 : 2007 年 11 月
.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 メソッドによって書式設定されます。つまり、整数 myValue は System.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", Nothing)
Dim yourString As String = mtype.ToString("d", Nothing)
Console.WriteLine(myString)
Console.WriteLine(yourString)
' The example produces the following output:
' 101010
' 42
MyType mtype = new MyType(42);
String myString = mtype.ToString("b", null);
String yourString = mtype.ToString("d", null);
Console.WriteLine(myString);
Console.WriteLine(yourString);
// The example produces the following output:
// 101010
// 42
既存の型へのカスタム書式指定文字列の追加
既存の基本型の書式設定の方法を制御したり、書式設定用の追加コードを提供したりするには、ICustomFormatter と IFormatProvider を実装する書式プロバイダ クラスを作成します。
基本型の ToString メソッドに書式プロバイダを渡すと、基本型では既定の書式プロバイダではなく、渡された書式プロバイダを使用して書式指定規則が定義されます。カスタム書式プロバイダを作成するには、次の手順に従ってください。
これら 2 つのインターフェイスを実装して GetFormat および Format をオーバーライドするクラスを定義します。
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(theformat, provider)
' 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);
}
}
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})
Console.WriteLine(myString)
' The example displays the following output:
' 42 in the 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});
Console.WriteLine(myString);
// The example displays the following output:
// 42 in custom B16 format is 2a