Better optimizations around combining string concatenation and string interpolation
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
I've recently seen a fair amount of code that involves expressions like:
```C#
string s1 = ..., s2 = ..., s3 = ...;
...
s1 += $"{s2} {s3} {somethingElse}";
```
When the string interpolation can be lowered to just usage of string.Concat, downstream optimizations combine the concat from the interpolation with the explicit concat:
```C#
public class C
{
public string M1(string s1, string s2, string s3)
{
s1 += $"{s2} {s3}";
return s1;
}
}
```
generates the equivalent of:
```C#
public class C
{
public string M1(string s1, string s2, string s3)
{
s1 = string.Concat(s1, s2, " ", s3);
return s1;
}
}
```
But, when the interpolation doesn't lower to a concat, the resulting code has both the string generated by the interpolation and then separately the concatenation, e.g.
```C#
public class C
{
public string M2(string s1, string s2, string s3)
{
s1 += $"{s2} {s3} {42}";
return s1;
}
}
```
generates the equivalent of:
```C#
public class C
{
public string M2(string s1, string s2, string s3)
{
string text = s1;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 3);
defaultInterpolatedStringHandler.AppendFormatted(s2);
defaultInterpolatedStringHandler.AppendLiteral(" ");
defaultInterpolatedStringHandler.AppendFormatted(s3);
defaultInterpolatedStringHandler.AppendLiteral(" ");
defaultInterpolatedStringHandler.AppendFormatted(42);
s1 = string.Concat(text, defaultInterpolatedStringHandler.ToStringAndClear());
return s1;
}
}
```
While a developer could rewrite the code to better handle this, it'd be helpful if the compiler could instead optimize it to the equivalent of if the developer had written:
```C#
public class C
{
public string M2(string s1, string s2, string s3)
{
s1 = $"{s1}{s2} {s3} {42}";
return s1;
}
}
```
such that it would generate the equivalent of:
```C#
public class C
{
public string M2(string s1, string s2, string s3)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(2, 4);
defaultInterpolatedStringHandler.AppendLiteral(s1);
defaultInterpolatedStringHandler.AppendFormatted(s2);
defaultInterpolatedStringHandler.AppendLiteral(" ");
defaultInterpolatedStringHandler.AppendFormatted(s3);
defaultInterpolatedStringHandler.AppendLiteral(" ");
defaultInterpolatedStringHandler.AppendFormatted(42);
return defaultInterpolatedStringHandler.ToStringAndClear();
}
}
```
Contributor guide
Research direction
The issue names no source files, tests, or entry points. Start by locating the C# lowering and optimization coverage for interpolated strings, then compare the M1 and M2 examples; done means combining the explicit concatenation with the interpolated-string handler so the generated code matches the single-handler equivalent shown.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers, performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100