はじめに
今回はstring-interpolation
の実態がどうなっているかについて取り上げたいと思います。
var x = 10; var y = 20; var str = $"{x}, {y}";
C#9時点
SharpLab
にて先ほどのコードをC#9
でIL
にコンパイルをし、C#
に逆コンパイルをするという手順をとると以下のようなコードが生成されます。

なんと以下のコードは実質的に全く同じであるということが分かります。
var str = $"{x}, {y}"; var str = string.Format("{0}, {1}", x, y);
ちなみにですが、string.Format
の引数はObject
なので、x
やy
がスタックに配置されている場合はboxing
が発生してしまいます。
String.Format メソッド (System) | Microsoft Learn
これはResults
をIL
に変換すると調べることができます。
IL_0000: ldc.i4.s 10 IL_0002: stloc.0 IL_0003: ldc.i4.s 20 IL_0005: stloc.1 IL_0006: ldstr "{0}, {1}" IL_000b: ldloc.0 IL_000c: box [System.Private.CoreLib]System.Int32 IL_0011: ldloc.1 IL_0012: box [System.Private.CoreLib]System.Int32 IL_0017: call string [System.Private.CoreLib]System.String::Format(string, object, object) IL_001c: pop IL_001d: ret
IL_000c
とIL_0012
がそれですね。
defalt(C#10.0以上)
コンパイラーを変えてみると、実は結果が変わります。
// 変換前 var x = 10; var y = 20; var str = $"{x}, {y}";
// 変換後 int value = 10; int value2 = 20; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 2); defaultInterpolatedStringHandler.AppendFormatted(value); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(value2); defaultInterpolatedStringHandler.ToStringAndClear();
よくわかりませんがDefaultInterpolatedStringHandler
を利用したコードに変換されました。
補間された文字列 String をインスタンスに処理するために言語コンパイラによって使用されるハンドラーを提供します。
前回と同じようにIL
を見てboxing
が発生していないか調べてみましょう。
IL_0000: ldc.i4.s 10 IL_0002: stloc.0 IL_0003: ldc.i4.s 20 IL_0005: stloc.1 IL_0006: ldloca.s 2 IL_0008: ldc.i4.2 IL_0009: ldc.i4.2 IL_000a: call instance void [System.Runtime]System.Runtime.CompilerServices.DefaultInterpolatedStringHandler::.ctor(int32, int32) IL_000f: ldloca.s 2 IL_0011: ldloc.0 IL_0012: call instance void [System.Runtime]System.Runtime.CompilerServices.DefaultInterpolatedStringHandler::AppendFormatted<int32>(!!0) IL_0017: ldloca.s 2 IL_0019: ldstr ", " IL_001e: call instance void [System.Runtime]System.Runtime.CompilerServices.DefaultInterpolatedStringHandler::AppendLiteral(string) IL_0023: ldloca.s 2 IL_0025: ldloc.1 IL_0026: call instance void [System.Runtime]System.Runtime.CompilerServices.DefaultInterpolatedStringHandler::AppendFormatted<int32>(!!0) IL_002b: ldloca.s 2 IL_002d: call instance string [System.Runtime]System.Runtime.CompilerServices.DefaultInterpolatedStringHandler::ToStringAndClear() IL_0032: pop IL_0033: ret
どこにもbox
の文字がありません。つまりstring-interpolation
はboxing
が発生しないような修正が裏で入ったということになります。
Unityとの関係性について
Unity 2022.1
の段階でもC#9.0
までしか対応していません。
またDefaultInterpolatedStringHandler
は.NET 6.0
から、つまりC#10.0
から導入されたようです。
DefaultInterpolatedStringHandler.AppendFormatted メソッド (System.Runtime.CompilerServices) | Microsoft Learn
C# 言語のバージョン管理 - C# ガイド | Microsoft Learn