xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

挿入文字列

string.Format メソッドは大変汎用的で便利です。しかし、ちょっとばかり煩雑で、かつ書式文字列内のプレースホルダーの数が合わなかったりするエラーが発生しやすいという傾向にあります。

var p = new Person("xin9le", 30, Sex.Male);
var t1 = string.Format("{0} is {1} year(s) old.", p.Name, p.Age);         //--- OK
var t2 = string.Format("{0} is {1} year(s) old.", p.Name, p.Age, p.Sex);  //--- 引数が多くても例外は飛ばない
var t3 = string.Format("{0} is {1} year(s) old.", p.Name);                //--- 引数が少ないと例外が飛ぶ

このような書式に従った文字列の生成を幾分楽にするための機能が今回紹介する「挿入文字列」です。

string 編

新しい書式文字列の記述方法は以下のように利用します。どのプレースホルダーに何を埋め込むのかが直観的になり、かなり分かりやすい形になっていると思います。

var person = new Person("xin9le", 30);
var text = $"{person.Name} is {person.Age} year{{s}} old.";
Console.WriteLine(text);

/*
xin9le is 30 year{s} old.
*/

使い方は簡単で、文字列の前に '$' を付け、プレースホルダーの中にプロパティ名をそのまま挿入するだけです。また、以下のように書式指定子を入れて利用することもできます。

var person = new Person("xin9le", 30);
var text = $"{person.Name,10} is {person.Age:D2} year(s) old.";
Console.WriteLine(text);

/*
    xin9le is 30 year(s) old.
*/

また、先の例を逆コンパイルして、どのような展開が行われるのかを確認してみました。

var person = new Person("xin9le", 30);
var text = string.Format("{0,10} is {1:D2} year(s) old.", new object[]
{
    person.Name,
    person.Age,
});
Console.WriteLine(text);

内部的には string.Format に置換されることが分かります。パフォーマンス的にはこれまでと全く変わりませんし、ただの糖衣構文でしかありません。より簡潔に書ける方を基本としつつ、コードが見やすくなる方を選ぶと良いのではないかと思います。

IFormattable 編

Visual Studio 2015 CTP 6 より、文字列補間は string 型だけでなく IFormattable 型にも対応するようになりました。型推論 (var) で受ける場合は string 型として解釈されますが、下記のように明示的に IFormattable 型で受けることで動きが変わります

var x = 0;
IFormattable f = $"{x:c}";  //--- IFormattable型で受ける
var text = f.ToString(null, new CultureInfo("ja-jp"));

上記の例を逆コンパイルすると、下記のように展開されます。

int x = 0;
IFormattable f = FormattableStringFactory.Create("{0:c}", new object[]{ x });
string text = f.ToString(null, new CultureInfo("ja-jp"));

FormattableStringFactory.Create メソッドが出てきていることからも分かるように、先の string 型とは展開のされ方が全く異なります。このような違いがあることを覚えておきましょう。