トラック
/
C#
C#
/
シラバス
/
文字列の書式設定
文字

文字列の書式設定 の C#

13個の演習

文字列の書式設定について

C#/.NETで文字列を書式設定する仕組みは多種多様です。オブジェクトを単純に連結する方法から、オーバーライドされたobject.ToString()メソッドの呼び出し、さらにはICustomFormatterの使用(この演習では扱いません)まであります。

文字列を書式設定する最も一般的な仕組みは、文字列補間とString.Format()の2つです。StringBuilderクラス(相互参照は追って追加予定)も、複数行にわたるような複雑な文字列を組み立てるのに使えます。

ToString()を使う

すべてのクラスと構造体が継承するSystem.Object()には、ToString()メソッドがあります。たとえばnew DateTime(2019, 5, 23).ToString()は「05/23/2019 00:00:00」と表示します(USカルチャーのスレッドの場合。下記を参照)。文字列連結のように、この既定のToString()メソッドが暗黙的に呼び出される状況もあり、"" + new DateTime(2019, 5, 23)も同じ結果になります。

既定のToString()メソッドに加えて、書式設定が関わる型には、書式文字列や書式プロバイダーを受け取るオーバーロードがあります。特にBCL(基本クラスライブラリ)では、数値、日付、列挙型、GUIDがこれに当たります。

複合書式設定

String.Format()は、固定テキストとプレースホルダー(ドキュメントでは_書式項目_と呼ばれます)から成る文字列(ドキュメントでは_複合書式_と呼ばれます)と、可変個の引数を受け取ります。戻り値は、各_書式項目_を対応する引数で解決し、解決された値を固定テキストと組み合わせます。

string.Format("I had {0} bitcoins on {1}, the day I forgot my password.", 55.5, new DateTime(2010, 2, 25))
// => "I had 55.5 bitcoins on 2/25/2010 00:00:00, the day I forgot my password." - US settings

書式がテンプレートのように複数の式で使われる場合や、[逐語的文字列][verbatim-strings]を使う場合のように、書式と書式設定する式をまとめるのが煩雑すぎる場合は、補間よりもFormat()の方が良い選択かもしれません。

この仕組みは、技術的には複合書式設定として知られています。

_複合書式設定_を活用する文字列生成メソッドのより完全なリストは、この記事にあります。

文字列補間

補間文字列は$で始まり、波括弧で囲まれた実行時式を含みます。書式項目の構文は$"{<interpolationExpression>[,<alignment>][:<formatString>]}"です。これにより、引数を別に並べる必要がなくなります。結果は、String.Format()の仕組みと機能的に同等です。

式には、スコープ内のあらゆるものを指定できます。_配置_は、テキストが収まる「フィールド」の長さです。_配置_が正の場合、テキストは左側に空白で埋められ、負の場合はテキストの右側に埋められます。

var loadsOf = 55.5;
var thatDay = new DateTime(2010, 2, 25);
$"I had {loadsOf} bitcoins on {thatDay}, the day I forgot my password."
// => "I had 55.5 bitcoins on 2/25/2010 00:00:00, the day I forgot my password." - US settings

書式項目

波括弧の中のテキスト、つまり複合書式の場合はプレースホルダー、文字列補間の場合は補間式は、_書式項目_と呼ばれます。

書式項目は最大3つの部分から成ります。1つ目は、上のサンプルコードにあるような必須の式または引数のプレースホルダーです。さらに、省略可能な配置(コンマ「,」で始まります)と、省略可能な_書式文字列_(コロン「:」で始まります)があります。

{<interpolationExpression>[,<alignment>][:<formatString>]}

_配置_は、テキストが置かれる「フィールド」の長さを指定し、配置が正なら左に空白で埋め、負なら右に埋めます。

_書式文字列_は、テキスト出力の形を指定します。たとえば、数値に桁区切り記号を含めるかどうか、DateTimeオブジェクトの日付部分だけを出力するかどうか、といったことです。

次のコードは、DateTimeオブジェクトの日付部分の表示と、小数点数を指数形式で表示する例です。

var loadsOf = 55.5;
var thatDay = new DateTime(2010, 2, 25);
$"I had {loadsOf:E} bitcoins on {thatDay:d}, the day I forgot my password."
// => I had 5.550000E+001 bitcoins on 02/25/2010, the day I forgot my password. - US settings

string.Format(
    "I had {0:E} bitcoins on {1:d}, the day I forgot my password.",
    loadsOf, thatDay)
// => I had 5.550000E+001 bitcoins on 02/25/2010, the day I forgot my password. - US settings

数値と日付の両方に、標準とカスタムの書式設定があります。_カスタム_と_標準_の間に決定的な違いはありませんが、カスタム書式文字列は書式文字から組み立てられるという点が異なります。ここでいう「カスタム」は、独自のカスタムフォーマッターを開発する際に使うICustomFormatterインターフェースとは何の関係もありません。

BCLのフォーマッターと書式文字列

基本クラスライブラリ(BCL)は、DateTimeFormatInfoとNumberFormatInfoの2つのフォーマッターと、6つの書式文字列のグループを提供します。

_書式文字列_の各種リストは次のとおりです。

EnumとGUIDの_書式文字列_は_標準_に分類できます。enumとGUIDにはIFormatProviderを受け取るToString()オーバーロードがありますが、それが何かをするのかははっきりしません。

ライブラリでは、_書式文字列_にいくらかの一貫性を持たせようと試みています(それらが文字列として表現されるという事実はさておき)。この一貫性の追求は、標準の文字列に見られます。実際のところ、エンジニアが標準とカスタムの文字列の違いを気にすることはほとんどありません。自分のクラス用にフォーマッターを実装する場合は、クラスがそれを必要としているように見えるなら、既存の標準の文字列に合わせるのが良い考えですが、違いはほとんど無視して構いません。

カルチャー

実行スレッドにはそれぞれ、CultureInfoのインスタンスにカプセル化された既定のカルチャThread.CurrentThread.CurrentCultureがあります。スレッドのカルチャは、地域ごとの違いに応じて、日付と数値が既定でどのように書式設定されるかを決めます。たとえば、英国の_DD/MM/YYYY_と米国の_MM/DD/YYYY_という従来の日付形式の違いなどです。

CultureInfoはIFormatProviderインターフェースを実装しており、これはString.Format()の特定のオーバーロードに渡すことができます。これを使って、スレッドのカルチャを上書きできます。

参考資料

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

文字列の書式設定を学習する

練習はロックされています

文字列の書式設定を練習するには、あと11個の演習のロックを解除してください