public class Program
{
public void Main()
{
IFormattable string1 = $"{1},{"test"}"; //Works
FormattableString string2 = $"{1},{"test"}"; //Works
LocStr string3 = $"{1},{"test"}"; ///Error: Cannot implicitly convert type 'string' to 'LocStr'
}
public class LocStr : IFormattable
{
public string ToString(string format, IFormatProvider formatProvider)
{
throw new NotImplementedException();
}
}
}
I am trying to create my own custon FormattableString class, however whether my class inherits from IFormattable or FormattableString, it cannot be directly be assigned from a formated string, as in LocStr testStr= $"Hello {User.Name}";
I tried inheriting from IFormattable, FormattableString, neither worked.
I checked if I can override assignment operator = but it is apparently not allowed in C#
as in public static LocStr operator =(string a)
but it is not allowed.
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 singleIFormattable
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)
{
}
}