There is some compiler magic going behind the scenes. If you define variable type as explicitly string
or allow compiler to determine it with var
then it will result in type string
:
var string0 = $"{1},{"test"}";
Console.WriteLine(string0.GetType()); // System.String
But for formattable strings there is also a special type FormattableString
:
A FormattableString
instance may result from an interpolated string in C# or Visual Basic.
which you can actually use in your code which results in the following behavior:
IFormattable string1 = $"{1},{"test"}"; //Works
FormattableString string2 = $"{1},{"test"}"; //Works
Console.WriteLine(string1.GetType()); // System.Runtime.CompilerServices.FormattableStringFactory+ConcreteFormattableString
Console.WriteLine(string2.GetType()); // System.Runtime.CompilerServices.FormattableStringFactory+ConcreteFormattableString
Demo @sharplab.io (also check out the decompilation to C#).
This is actually described in Implicit conversions and how to specify IFormatProvider
implementation section of the docs:
There are three implicit conversions from an interpolated string:
- Conversion of an interpolated string to a
String
instance. ...
- Conversion of an interpolated string to a
FormattableString
instance that represents a composite format string along with the expression results to be formatted. ...
- Conversion of an interpolated string to an
IFormattable
instance that also allows you to create multiple result strings with culture-specific content from a single IFormattable
instance. ...
Compiler out of the box does not know how to convert the interpolated string into your specific type but since C# 10 you can implement the interpolated string handler pattern (not that you should though in general case, usually it is needed for specific high performance scenarios):
[InterpolatedStringHandler]
public class LocStr : IFormattable
{
public LocStr(int literalLength, int formattedCount)
{
}
public string ToString(string format, IFormatProvider formatProvider)
{
throw new NotImplementedException();
}
public void AppendLiteral(string s)
{
}
public void AppendFormatted<T>(T t)
{
}
}
Updated demo @sharplab.io