✅ Explicit call ToString() when interpolating on primitive (value) types

Is it necessary to call ToString() when interpolating string using primitive (int, float, etc.) or in general value types? Would it avoid boxing allocation? Example:
int someInt = 4;
MyStructWithImplementedInterfaceIFormatable myStruct;
Console.Write($"My number is: {someInt.ToString()} and struct: {myStruct.ToString()}");
int someInt = 4;
MyStructWithImplementedInterfaceIFormatable myStruct;
Console.Write($"My number is: {someInt.ToString()} and struct: {myStruct.ToString()}");
18 Replies
ero
ero2y ago
Well first off this doesn't compile. But also, why not just try it?
MODiX
MODiX2y ago
Ero#1111
REPL Result: Success
int someInt = 4;

Console.WriteLine($"{someInt}");
int someInt = 4;

Console.WriteLine($"{someInt}");
Console Output
4
4
Compile: 606.991ms | Execution: 32.196ms | React with ❌ to remove this embed.
Ice_trooper
Ice_trooperOP2y ago
What do you want to explain to me? ;p I know it would work, but the essence of the question is: should I call explicitlly ToString to avoid boxing allocation?
ero
ero2y ago
You asked 2 separate questions Not my fault
Ice_trooper
Ice_trooperOP2y ago
Ok, I'm sorry. You're right that it could be understood this way 😅
ero
ero2y ago
Calling ToString on anything will allocate (a string), i dont think it would box?
Ice_trooper
Ice_trooperOP2y ago
Yeah, but here I'm using value types
Thinker
Thinker2y ago
.ToString() is called implicitly when using string interpolation It will allocate a string regardless (I think)
Ice_trooper
Ice_trooperOP2y ago
Yes, but on what type is it called implicitly? On int/MyStruct directly or is it boxing value type to object and then it will call ToString() (less efficient)?
Thinker
Thinker2y ago
The IL contains no boxing, although you might have to dig into the source of DefaultInterpolatedStringHandler.
MODiX
MODiX2y ago
thinker227#5176
sharplab.io (click here)
int a = 2;
int b = 7;
string s = $"The first number is {a} and the second number...
System.Console.WriteLine(s);
int a = 2;
int b = 7;
string s = $"The first number is {a} and the second number...
System.Console.WriteLine(s);
React with ❌ to remove this embed.
Ice_trooper
Ice_trooperOP2y ago
Yeah, I also checked that it uses that handler, but I cannot find information how it behaves internally. :/
Thinker
Thinker2y ago
The source is here https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs,1aa9a7f847d81b2f It has some pretty extensive comments if you wanna read through it It appears that when formatting objects, it tries to format it using IFormattable, otherwise it calls ToString() on the type. However it's using a type argument, which means that no boxing is taking place.
MODiX
MODiX2y ago
Retax#0813
sharplab.io (click here)
System.Console.WriteLine($"{(new S()).ToString()}");
readonly struct S {}
System.Console.WriteLine($"{(new S()).ToString()}");
readonly struct S {}
React with ❌ to remove this embed.
Ice_trooper
Ice_trooperOP2y ago
@🌈 Thinker 🌈 @Retax I was just reading links you pasted and articles about that. Do I understand correctly that since C#10 we got a concept of String Interpolation Handlers and it's optimized on that level so we don't have to explicitly call ToString() on value-types? https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/interpolated-string-handler Unlike previous versions of C#, where string.Format was used when calling interpolation with int (without explicitly ToString() call). https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/improved-interpolated-strings#the-handler-pattern Last sum up question: Does it follow that up to C#10 version you should call ToString() yourself, but since this version they have improved it and DefaultInterpolatedStringHandler does it for us?
Ice_trooper
Ice_trooperOP2y ago
I think I'm going to disagree with that. Can you justify it? As far as I can see in the latest version of C# we use a generic method that checks if the type implements the IFormatable interface. However, the old C# uses the string.Format(string, object) method, so he is already doing the boxing allocation at the stage of calling this method. Calling ToString() by itself gets rid of this.
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server