Problem description:
string.Copy was deprecated in .NET Core 3.0 (for good reason), however, I had been using it with TextRenderer.MeasureText, which modifies the string when calling it if the string is too long for the width specified. Without string.Copy, I'm not sure how else you would use this API without string.Copy for now. With the warning showing that this API was removed as strings may be deduplicated in the future, I wasn't sure about how to properly change this code to be more future-proof, as I'm not sure it can be in its current state.
Minimal repro:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ConsoleApp10
{
class Program
{
static void Main(string[] args)
{
string original = @"C:\New Folder\New Folder\New Folder\New Folder\New Folder\New Folder\text.txt";
string result = GetCompactedString(original, 4);
//Result is now correctly "...\text.txt"
//Expectation is that original is still the very long file path, but it is the same as result
}
public static string GetCompactedString(string stringToCompact, int maxWidth)
{
//This line is necessary to not cause the bug shown below
//string copy= string.Copy(stringToCompact);
string copy = stringToCompact;
var opts = TextFormatFlags.PathEllipsis | TextFormatFlags.ModifyString;
TextRenderer.MeasureText(copy, new Font("Segoe UI", 9), new Size(maxWidth, 0), opts);
// https://connect.microsoft.com/VisualStudio/feedback/details/620330
int nullByteLoc = copy.IndexOf('\0');
if (nullByteLoc != -1)
{
copy = copy.Substring(0, nullByteLoc);
}
return copy;
}
}
}
That sounds more like a bug in the MeasureText implementation than an intended feature, but nice catch anyways. I suspect fixing this needs a new overload though, I don't think the function should go around and break runtime invariants by writing into an immutable object.
I think we are beyond the timeframe where we can add an overload for 3.0 and 3.1 so we will probably need to fix this issue in 5.0. Moving to that milestone for now. We can always bring it back if we have the time to fix it.
It is not as simple as string.Copy, but can you just?:
```c#
string copy = new string(original.ToCharArray());
```c#
string copy= $"{original}";
Need to validate we don't allow corrupting the immutability of strings.
Like said above TextRenderer should probably filter out or throw on passing the ModifyString flag and have a separate API for mutable strings (i.e. StringBuilder, ref string or mutable span)
TextRenderer API with a safe alternative.
Most helpful comment
Need to validate we don't allow corrupting the immutability of strings.