vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

C# 6の String interpolation で遊ぶ

はじめに

最近ついうっかり Effective C# Edition 3 を読み始めました。

その第4項目で、 string.Format() ではなく String interpolation を使いましょう、というものがありました。

C# 6.0 から、以下のように書けるようになったとのこと(なお Unity でも C# 6.0 を使用可能にすれば問題なく動作します)。

// 今まで.
string outputTextLegacy = string.Format("Hello {0}", DateTime.Now.ToString("yyyy-M-d dddd"));
Console.WriteLine(outputTextLegacy);

// 6.0以降.
string outputTextNew = $"Hello {DateTime.Now:yyyy-M-d dddd}";
Console.WriteLine(outputTextNew);

...うむ、後者を初見だと何やってるかわからないだろうな\(^o^)/

初見だとわからないなら何度も見れば良いじゃない

という声が聞こえましたので、ちょっと触ってみることにしました。

書き方

$"Hello {DateTime.Now:yyyy-M-d dddd}"

を紐解くと、頭に $ をつけて、文字列として置き換えたい部分を {} でくくり、
フォーマットの形式は : 以降に書きます。

なおフォーマット形式がない場合はデフォルトの形式で出力されます。

また : 以降はすべてフォーマットの形式を指定する文字列として扱われるため、 } との間にスペースなどを入れるとコンパイルエラーとなります。

試す

String interpolation 扱えるものは、先程の DataTime.Now のように値をそのまま書くことも可能ですし、
変数やメソッドも使用できます。

またIDEであれば入力補完もバッチリです( Visual Studio2017 + ReSharper 、 Rider で確認)。

変数を使う

double pi = Math.PI;
// 出力結果: 3.14
string outputTextNew = $"{pi:F2}";
Console.WriteLine(outputTextNew);

メソッドを使う

static void Main(string[] args)
{
    // Mainメソッドから呼び出しているためstaticにしているが、普通のメソッドでも使用可能.
    string outputTextNew = $"{GetMessage()}";
    Console.WriteLine(outputTextNew);
}
private static string GetMessage()
{
    return "Hello";
}
  • ただし当然とも言えますが、戻り値が void のメソッドはコンパイルエラーとなり使用できません。

null 合体演算子を使う

Kotlinなどでいうエルビス演算子(Nullのときだけ ?? の右側の値が使用される)も使えちゃいます。

string test = null;
var outputTextNew = $"{test ?? "text is null"}";

三項演算子を使う

三項演算子を使う場合は少しだけ注意が必要です。

string test = null;
var outputTextNew = $"{(test == null ? "text is null" : DateTime.Now.ToString("yyyy-M-d dddd"))}";
  • 上記のように、式を () でくくる必要があります。

Linqを使う

普通に使えるようです。

ただ、あんまりやりすぎると可読性、という面から厳しそうですが。

List textSample = new List
{
    "text1",
    "text2"
};
var outputTextNew = $"{textSample.Select(t => t).Count().ToString()}";
Console.WriteLine(outputTextNew);

async / await

当然ながら使えません。

{} のエスケープ

$ をつけている場合、 {} が全て String interpolation として扱われるため、
{} をそのまま表示するにはエスケープが必要になります。

$"Hello World! {{\"text is null\"}}";

その他注意点

これも Effective C# で取り上げられている内容ですが、これを使ってSQL文を組み立ててはいけません。

SQLインジェクションを避けるため、これまで通りプレースホルダーを使用する必要があります。

おわりに

今までの方法と比較して、 String interpolation を使うことでセットする文字列の、
順番や数の間違いなどを防げる、という利点に加えて処理がグッとシンプルに書けそうなので良いと思いました。

ただ途中でも書きましたが、あまりごちゃごちゃやり過ぎると見づらくなったりバグの原因になりそうなので、
ほどほどにしておくのが良さそうですね。

参照