次の方法で共有


複合書式指定

.NET 複合書式設定機能は、オブジェクトの一覧と複合書式指定文字列を入力として受け取ります。 複合書式指定文字列は、固定テキストとインデックス付きプレースホルダー (書式項目と呼ばれます) で構成されます。 この書式指定項目は、リスト内のオブジェクトに対応します。 書式設定操作によって生成される結果の文字列は、元の固定テキストに文字列で表されたリスト内のオブジェクトが混合されて構成されます。

重要

複合書式指定文字列を使用する代わりに、使用している言語とそのバージョンでサポートされている場合は 、挿入文字列 を使用できます。 補間された文字列には、"補間された式" が含まれています。 各挿入式は式の値によって解かれ、文字列が割り当てられるとき、結果文字列に含まれます。 詳細については、「 文字列補間 (C# リファレンス) 」および「 挿入文字列 (Visual Basic リファレンス)」を参照してください

次のメソッドは、複合書式設定機能をサポートしています。

複合書式指定文字列

複合書式指定文字列とオブジェクト リストは、複合書式指定機能をサポートするメソッドの引数として使用されます。 複合書式指定文字列は、1 つ以上の書式指定項目と混在する固定テキストの 0 回以上の実行で構成されます。 固定テキストは任意の文字列であり、各書式項目はリスト内のオブジェクトまたはボックス化された構造に対応します。 各オブジェクトの文字列表現は、対応する書式指定項目を置き換えます。

次の Format コード フラグメントについて考えてみましょう。

string.Format("Name = {0}, hours = {1:hh}", "Fred", DateTime.Now);
String.Format("Name = {0}, hours = {1:hh}", "Fred", DateTime.Now)

固定テキストは Name = , hours = です。 書式指定項目は {0}で、インデックス 0 はオブジェクト nameに対応し、 {1:hh}は 1 のインデックスがオブジェクト DateTime.Nowに対応します。

書式指定項目の構文

各書式指定項目は、次の形式を使用し、次のコンポーネントで構成されます。

{index[,width][:formatString]}

対になった中括弧 ({}) が必要です。

インデックス コンポーネント

必須の index コンポーネント (パラメーター指定子とも呼ばれます) は、オブジェクトのリスト内の対応する項目を識別する 0 から始まる数値です。 つまり、パラメーター指定子が 0 されている書式指定項目は、リスト内の最初のオブジェクトを書式設定します。 パラメーター指定子が 1 されている書式指定項目は、リスト内の 2 番目のオブジェクトを書式設定します。 次の例には、10 未満の素数を表す 4 つのパラメーター指定子 (0 ~ 3) が含まれています。

string primes = string.Format("Four prime numbers: {0}, {1}, {2}, {3}",
                              2, 3, 5, 7);
Console.WriteLine(primes);

// The example displays the following output:
//      Four prime numbers: 2, 3, 5, 7
Dim primes As String = String.Format("Four prime numbers: {0}, {1}, {2}, {3}",
                                      2, 3, 5, 7)
Console.WriteLine(primes)

'The example displays the following output
'     Four prime numbers 2, 3, 5, 7

複数の書式指定項目は、同じパラメーター指定子を指定することで、オブジェクトの一覧で同じ要素を参照できます。 たとえば、次の例に示すように、 "0x{0:X} {0:E} {0:N}"などの複合書式指定文字列を指定することで、同じ数値を 16 進数、指数、数値形式で書式設定できます。

string multiple = string.Format("0x{0:X} {0:E} {0:N}",
                                Int64.MaxValue);
Console.WriteLine(multiple);

// The example displays the following output:
//      0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00
Dim multiple As String = String.Format("0x{0:X} {0:E} {0:N}",
                                       Int64.MaxValue)
Console.WriteLine(multiple)

'The example displays the following output
'     0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00

各書式項目は、リスト内の任意のオブジェクトを参照できます。 たとえば、3 つのオブジェクトがある場合は、 {1} {0} {2}などの複合書式指定文字列を指定して、2 番目、1 番目、3 番目のオブジェクトを書式設定できます。 書式項目によって参照されていないオブジェクトは無視されます。 パラメーター指定子がオブジェクトのリストの境界外にある項目を指定すると、実行時に FormatException がスローされます。

width コンポーネント

省略可能な width コンポーネントは、優先する書式設定されたフィールドの幅を示す符号付き整数です。 widthの値が書式設定された文字列の長さより小さい場合、widthは無視され、書式設定された文字列の長さがフィールドの幅として使用されます。 フィールド内の書式設定されたデータは、 width が正の場合は右揃えになり、 width が負の場合は左揃えになります。 パディングが必要な場合は、空白が使用されます。 widthが指定されている場合は、コンマが必要です。

次の例では、2 つの配列を定義します。1 つは従業員の名前を含み、もう 1 つは 2 週間にわたって勤務した時間を含みます。 複合書式指定文字列は、20 文字のフィールド内の名前を左揃えにし、5 文字のフィールドで時間を右揃えにします。 "N1" 標準書式指定文字列は、時間を 1 桁の小数部で書式設定します。

string[] names = { "Adam", "Bridgette", "Carla", "Daniel",
                   "Ebenezer", "Francine", "George" };
decimal[] hours = { 40, 6.667m, 40.39m, 82,
                    40.333m, 80, 16.75m };

Console.WriteLine("{0,-20} {1,5}\n", "Name", "Hours");

for (int counter = 0; counter < names.Length; counter++)
    Console.WriteLine("{0,-20} {1,5:N1}", names[counter], hours[counter]);

// The example displays the following output:
//      Name                 Hours
//      
//      Adam                  40.0
//      Bridgette              6.7
//      Carla                 40.4
//      Daniel                82.0
//      Ebenezer              40.3
//      Francine              80.0
//      George                16.8
Dim names As String() = {"Adam", "Bridgette", "Carla", "Daniel",
                         "Ebenezer", "Francine", "George"}

Dim hours As Decimal() = {40, 6.667D, 40.39D, 82,
                          40.333D, 80, 16.75D}

Console.WriteLine("{0,-20} {1,5}\n", "Name", "Hours")

For counter = 0 To names.Length - 1
    Console.WriteLine("{0,-20} {1,5:N1}", names(counter), hours(counter))
Next

'The example displays the following output
'     Name                 Hours
'     
'     Adam                  40.0
'     Bridgette              6.7
'     Carla                 40.4
'     Daniel                82.0
'     Ebenezer              40.3
'     Francine              80.0
'     George                16.8

文字列コンポーネントの書式設定

省略可能な formatString コンポーネントは、書式設定するオブジェクトの種類に適した書式指定文字列です。 以下を指定できます。

  • 対応するオブジェクトが数値の場合は、標準またはカスタムの数値書式指定文字列。
  • 対応するオブジェクトが DateTime オブジェクトの場合は、標準またはカスタムの日時書式指定文字列。
  • 対応するオブジェクトが列挙値の場合は、列挙 形式の文字列

formatStringが指定されていない場合は、数値、日付と時刻、または列挙型の一般 ("G") 書式指定子が使用されます。 formatStringが指定されている場合は、コロンが必要です。

次の表に、定義済みの書式指定文字列のセットをサポートする .NET クラス ライブラリ内の型またはカテゴリを示し、サポートされている書式指定文字列を一覧表示する記事へのリンクを示します。 文字列書式指定は、既存のすべての型に対して新しい書式指定文字列を定義し、アプリケーション定義型でサポートされる書式指定文字列のセットを定義できるようにする拡張可能なメカニズムです。

詳細については、 IFormattable および ICustomFormatter インターフェイスに関する記事を参照してください。

型または型のカテゴリ 参照先
日付と時刻の種類 (DateTimeDateTimeOffset) 標準の日時形式文字列

カスタム日時形式文字列
列挙型 ( System.Enumから派生したすべての型) 列挙型書式指定文字列
数値型 (BigIntegerByteDecimalDoubleInt16Int32Int64SByteSingleUInt16UInt32UInt64) 標準の数値書式指定文字列

カスタム数値形式文字列
Guid Guid.ToString(String)
TimeSpan 標準の時間間隔書式指定文字列

カスタム時間間隔書式指定文字列

エスケープ中かっこ ({})

左中かっこ ({) および右中かっこ (}) は、書式指定項目の開始および終了として解釈されます。 リテラルの左中かっこおよび右中かっこを表示するためには、エスケープ シーケンスを使用する必要があります。 左中かっこを 1 つ ({) 表示するには、左中かっこ 2 つ ({{) を固定テキストに指定します。また、右中かっこを 1 つ (}) 表示するには、右中かっこ 2 つ (}}) を指定します。

形式項目を含むエスケープされた中かっこは、.NET と .NET Framework では異なる方法で解析されます。

.NET

中かっこは書式項目の周囲でエスケープできます。 たとえば、書式指定項目 {{{0:D}}} があるとします。これは、左中かっこ、10 進数で表記された数値、右中かっこを表示することを意図しています。 書式項目は、次の方法で解釈されます。

  1. 最初の 2 つの左中かっこ ({{) がエスケープされ、左中かっこ 1 つが作成されます。
  2. 次の 3 文字 ({0:) は、書式項目の先頭として解釈されます。
  3. 次の文字 (D) は、10 進数の標準数値書式指定子として解釈されます。
  4. 次の中かっこ (}) は、書式項目の末尾として解釈されます。
  5. 最後の 2 つの中かっこはエスケープされ、1 つの閉じ中かっこが生成されます。
  6. 表示される最終的な結果は、リテラル文字列 ( {6324}) です。
int value = 6324;
string output = string.Format("{{{0:D}}}", value);

Console.WriteLine(output);
// The example displays the following output:
//       {6324}
Dim value As Integer = 6324
Dim output As String = String.Format("{{{0:D}}}", value)

Console.WriteLine(output)

'The example displays the following output
'      {6324}

.NET Framework

書式指定項目に使用されている中かっこは、指定されている順序に従って解釈されます。 入れ子になった中かっこを解釈する機能はサポートされていません。

エスケープされた中かっこの解釈によっては、予測しない結果になる場合があります。 たとえば、書式指定項目 {{{0:D}}} があるとします。これは、左中かっこ、10 進数で表記された数値、右中かっこを表示することを意図しています。 ただし、書式項目は次のように解釈されます。

  1. 最初の 2 つの左中かっこ ({{) がエスケープされ、左中かっこ 1 つが作成されます。
  2. 次の 3 文字 ({0:) は、書式項目の先頭として解釈されます。
  3. 次の文字 (D) は十進標準数値書式指定子として解釈されますが、次のエスケープされた2つの中かっこ (}}) は1つの中かっこを生成します。 結果の文字列 (D}) は標準の数値書式指定子ではないので、結果の文字列は、リテラル文字列 D}を表示することを意味するカスタム書式指定文字列として解釈されます。
  4. 最後の中かっこ (}) は、書式項目の末尾として解釈されます。
  5. 表示される最終的な結果は、リテラル文字列 ( {D}) です。 書式設定された数値は表示されません。
int value = 6324;
string output = string.Format("{{{0:D}}}",
                              value);
Console.WriteLine(output);

// The example displays the following output:
//       {D}
Dim value As Integer = 6324
Dim output As String = String.Format("{{{0:D}}}",
                                     value)
Console.WriteLine(output)

'The example displays the following output:
'      {D}

コードを、エスケープされた波括弧や書式指定項目を誤って解釈しないように記述する方法の一つは、波括弧と書式指定項目を個別に書式設定することです。 つまり、最初の書式指定操作では、リテラルの左中かっこを表示します。 次の操作では、書式指定項目の結果を表示し、最後の操作ではリテラルの右中かっこを表示します。 この方法の例を次に示します。

int value = 6324;
string output = string.Format("{0}{1:D}{2}",
                             "{", value, "}");
Console.WriteLine(output);

// The example displays the following output:
//       {6324}
Dim value As Integer = 6324
Dim output As String = String.Format("{0}{1:D}{2}",
                                     "{", value, "}")
Console.WriteLine(output)

'The example displays the following output:
'      {6324}

処理の順序

複合書式指定メソッドの呼び出しに値がnullされていないIFormatProvider引数が含まれている場合、ランタイムはそのIFormatProvider.GetFormat メソッドを呼び出して、ICustomFormatter実装を要求します。 メソッドが ICustomFormatter 実装を返すことができる場合は、複合書式指定メソッドの呼び出し中にキャッシュされます。

書式項目に対応するパラメーター リスト内の各値は、次のように文字列に変換されます。

  1. 書式設定する値が nullの場合は、空の文字列 String.Empty が返されます。

  2. ICustomFormatter実装が使用可能な場合、ランタイムはそのFormat メソッドを呼び出します。 ランタイムは、書式指定項目の formatString 値 (存在しない場合は null ) をメソッドに渡します。 ランタイムは、 IFormatProvider 実装もメソッドに渡します。 ICustomFormatter.Format メソッドの呼び出しでnullが返された場合、実行は次の手順に進みます。 それ以外の場合は、 ICustomFormatter.Format 呼び出しの結果が返されます。

  3. 値が IFormattable インターフェイスを実装する場合、インターフェイスの ToString(String, IFormatProvider) メソッドが呼び出されます。 書式項目に存在する場合は、 formatString 値がメソッドに渡されます。 それ以外の場合は、 null が渡されます。 IFormatProvider引数は次のように決定されます。

    • 数値の場合、null 以外のIFormatProvider引数を持つ複合書式指定メソッドが呼び出されると、ランタイムは IFormatProvider.GetFormat メソッドからNumberFormatInfo オブジェクトを要求します。 引数の値を指定できない場合、引数の値が null場合、または複合書式指定メソッドに IFormatProvider パラメーターがない場合は、現在のカルチャの NumberFormatInfo オブジェクトが使用されます。

    • 日付と時刻の値の場合、null 以外のIFormatProvider引数を持つ複合書式指定メソッドが呼び出されると、ランタイムはIFormatProvider.GetFormat メソッドからDateTimeFormatInfo オブジェクトを要求します。 次の状況では、現在のカルチャの DateTimeFormatInfo オブジェクトが代わりに使用されます。

    • 他の型のオブジェクトの場合、複合書式指定メソッドが IFormatProvider 引数を使用して呼び出された場合、その値は IFormattable.ToString 実装に直接渡されます。 それ以外の場合、 nullIFormattable.ToString 実装に渡されます。

  4. Object.ToString()をオーバーライドするか、基底クラスの動作を継承する、型のパラメーターなしのToString メソッドが呼び出されます。 この場合、書式設定項目が存在する場合、 formatString コンポーネントによって指定された書式指定文字列は無視されます。

アラインメントは、上記の手順が実行された後に適用されます。

コード例

次の例は、複合書式を使用して作成された文字列と、オブジェクトの ToString メソッドを使用して作成された文字列を示しています。 どちらの種類の書式設定でも、同等の結果が生成されます。

string formatString1 = string.Format("{0:dddd MMMM}", DateTime.Now);
string formatString2 = DateTime.Now.ToString("dddd MMMM");
Dim formatString1 As String = String.Format("{0:dddd MMMM}", DateTime.Now)
Dim formatString2 As String = DateTime.Now.ToString("dddd MMMM")

現在の日付が5月の木曜日であると仮定すると、前の例の両方の文字列の値は、米国の英語圏でThursday Mayです。

Console.WriteLine は、 String.Formatと同じ機能を公開します。 2 つのメソッドの唯一の違いは、String.Formatは結果を文字列として返し、Console.WriteLineConsole オブジェクトに関連付けられている出力ストリームに結果を書き込む点です。 次の例では、 Console.WriteLine メソッドを使用して、 myNumber の値を通貨値に書式設定します。

int myNumber = 100;
Console.WriteLine($"{myNumber:C}");

// The example displays the following output
// if en-US is the current culture:
//        $100.00
Dim myNumber As Integer = 100
Console.WriteLine("{0:C}", myNumber)

'The example displays the following output
'if en-US Is the current culture:
'       $100.00

次の例では、2 つの異なる方法で 1 つのオブジェクトを書式設定するなど、複数のオブジェクトの書式設定を示します。

string myName = "Fred";
Console.WriteLine(string.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",
                                myName, DateTime.Now));

// Depending on the current time, the example displays output like the following:
//        Name = Fred, hours = 11, minutes = 30
Dim myName As String = "Fred"
Console.WriteLine(String.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",
                                myName, DateTime.Now))
'Depending on the current time, the example displays output Like the following:
'       Name = Fred, hours = 11, minutes = 30

次の例では、書式設定で幅を使用する方法を示します。 書式設定された引数は、垂直方向のバー文字 (|) の間に配置され、結果の配置が強調表示されます。

string firstName = "Fred";
string lastName = "Opals";
int myNumber = 100;

string formatFirstName = string.Format("First Name = |{0,10}|", firstName);
string formatLastName = string.Format("Last Name =  |{0,10}|", lastName);
string formatPrice = string.Format("Price =      |{0,10:C}|", myNumber);
Console.WriteLine(formatFirstName);
Console.WriteLine(formatLastName);
Console.WriteLine(formatPrice);
Console.WriteLine();

formatFirstName = string.Format("First Name = |{0,-10}|", firstName);
formatLastName = string.Format("Last Name =  |{0,-10}|", lastName);
formatPrice = string.Format("Price =      |{0,-10:C}|", myNumber);
Console.WriteLine(formatFirstName);
Console.WriteLine(formatLastName);
Console.WriteLine(formatPrice);

// The example displays the following output on a system whose current
// culture is en-US:
//     First Name = |      Fred|
//     Last Name =  |     Opals|
//     Price =      |   $100.00|
//
//     First Name = |Fred      |
//     Last Name =  |Opals     |
//     Price =      |$100.00   |
Dim firstName As String = "Fred"
Dim lastName As String = "Opals"
Dim myNumber As Integer = 100

Dim formatFirstName As String = String.Format("First Name = |{0,10}|", firstName)
Dim formatLastName As String = String.Format("Last Name =  |{0,10}|", lastName)
Dim formatPrice As String = String.Format("Price =      |{0,10:C}|", myNumber)
Console.WriteLine(formatFirstName)
Console.WriteLine(formatLastName)
Console.WriteLine(formatPrice)
Console.WriteLine()

formatFirstName = String.Format("First Name = |{0,-10}|", firstName)
formatLastName = String.Format("Last Name =  |{0,-10}|", lastName)
formatPrice = String.Format("Price =      |{0,-10:C}|", myNumber)
Console.WriteLine(formatFirstName)
Console.WriteLine(formatLastName)
Console.WriteLine(formatPrice)

'The example displays the following output on a system whose current
'culture Is en-US:
'    First Name = |      Fred|
'    Last Name =  |     Opals|
'    Price =      |   $100.00|
'
'    First Name = |Fred      |
'    Last Name =  |Opals     |
'    Price =      |$100.00   |

こちらも参照ください