I see this now and then:
_ = $"...{foo.ToString("bar")}...";
The .ToString(" and ") spans (or maybe just the ToString token?) should be faded and a code fix should be available inside .ToString("bar") to convert to:
_ = $"...{foo:bar}...";
The degenerate case .ToString() could also have the same treatment with a code fix to entirely remove.
In a similar vein, PadLeft and PadRight could be replaced using the alignment component:
_ = $"...{foo.ToString("bar").PadRight(3)}...";
_ = $"...{foo2.PadLeft(4, ' ')}...";
⬇
_ = $"...{foo,3:bar}...";
_ = $"...{foo2,-4}...";
Looking into this.
This code fix will box value types. The reason ToString() was used could've been to avoid boxing it.
This code fix will box value types. The reason ToString() was used could've been to avoid boxing it.
@dotnet/roslyn-compiler is there any reason the compiler cannot optimize this case (string interpolation to string, as opposed to IFormattable) as was done for concatenation?
@sharwell
Overall better efficiency around string interpolation is a feature we're looking at for C# 9.0.
The comment chain is a bit ambiguous but I assume the ask is to implicitly call ToString on value types before passing them into the string formatting functions for interpolated strings? If so then the reason why is:
ToString calls before the boxing operationThat is the reason we haven't made any changes up through C# 8.0. Going into C# 9 though better performance here, at the possible expense of corner case compat changes, is a goal.
@jaredpar Thanks! Based on this, I'm going to push for the readability of {value} outweighing the performance advantage of {value.ToString()} for value types that either don't implement IFormattable or do so in a way that is known to ignore the culture.
In a similar vein, PadLeft and PadRight could be replaced using the alignment component:
_ = $"...{foo.ToString("bar").PadRight(3)}..."; _ = $"...{foo2.PadLeft(4, ' ')}...";⬇
_ = $"...{foo,3:bar}..."; _ = $"...{foo2,-4}...";@jnm2 @CyrusNajmabadi @sharwell
Hasn't the PadLeft/PadRight to alignment component fix been implemented to do the reverse here?
A PadLeft becomes a PadRight when simplifying to alignment component and vice versa?
Console.WriteLine($"|{"Bug".PadLeft(10)}|");
Console.WriteLine($"|{"Bug",-10}|");
=>
| Bug|
|Bug |
@martinstenhoff Thanks for checking on this. That's a bit embarrassing! I'm especially happy that you caught this before it got further than a preview. We read this but then accidentally equated 'left-aligned' with PadLeft, when really PadLeft is right-aligning and PadRight is left-aligning:
The formatted data in the field is right-aligned if alignment is positive and left-aligned if alignment is negative.
https://docs.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting#alignment-component
Is this something you'd be willing to submit a PR to fix? I think I'd do it by fixing this line:
and then fixing up the tests that begin failing in https://github.com/dotnet/roslyn/blob/master/src/EditorFeatures/CSharpTest/SimplifyInterpolation/SimplifyInterpolationTests.cs.
I have some time here, so I think I'll get a PR up.
Most helpful comment
@jaredpar Thanks! Based on this, I'm going to push for the readability of
{value}outweighing the performance advantage of{value.ToString()}for value types that either don't implementIFormattableor do so in a way that is known to ignore the culture.