Repository navigation
Flow System.Text.Rune through more APIs #27912
Copy link
Copy link
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Runtime
Milestone
Description
System.Text.Rune was recently introduced (see dotnet/coreclr#20935) to make it easier for applications to work with Unicode text. We should do a pass of our APIs which currently take or return System.Char instances and enlighten them to understand System.Text.Rune. Here's an initial proposal that can serve as a first pass.
namespace System
{
// Adds overloads to existing char-consuming methods
// TODO: Do we need overloads of MemoryExtensions methods? May cause overload explosion.
// If we had such overloads, they'd basically look like the below, but with a "this ROS<char>" parameter.
public partial sealed class String
{
public bool Contains(Rune value);
public bool Contains(Rune value, StringComparison comparisonType);
public bool EndsWith(Rune value);
public bool EndsWith(Rune value, StringComparison comparisonType);
public bool EndsWith(char value, StringComparison comparisonType); // missing overload
public int IndexOf(Rune value);
public int IndexOf(Rune value, int startIndex);
public int IndexOf(Rune value, int startIndex, int count);
public int IndexOf(Rune value, StringComparison comparisonType);
// no IndexOfAny overloads for now due to complexity of implementation, can add later if there's demand
// no Join overloads for now, can add later if there's demand
public int LastIndexOf(Rune value);
public int LastIndexOf(Rune value, int startIndex);
public int LastIndexOf(Rune value, int startIndex, int count);
public int LastIndexOf(Rune value, StringComparison comparisonType);
public string Replace(Rune oldRune, Rune newRune);
public string[] Split(Rune separator, int count, StringSplitOptions options = default);
public string[] Split(Rune separator, StringSplitOptions options = default);
public bool StartsWith(Rune value);
public bool StartsWith(Rune value, StringComparison comparisonType);
public bool StartsWith(char value, StringComparison comparisonType); // missing overload
// no Trim*(Rune[]) overloads for now due to complexity of implementation, can add later if there's demand
public string Trim(Rune trimRune);
public string TrimEnd(Rune trimRune);
public string TrimStart(Rune trimRune);
}
}
namespace System.Text
{
// New methods on newly-introduced type
public partial struct Rune
{
public static bool Equals(Rune left, Rune right); // mimics (left == right), ordinal
public static bool Equals(Rune left, Rune right, StringComparison comparisonType); // for any non-ordinal comparison
}
// Adds overloads to existing char-consuming methods
// Not all methods get overloads (e.g., AppendJoin) due to perceived rare usage and complexity of implementation
public partial sealed class StringBuilder
{
public StringBuilder Append(Rune value);
public Rune GetRuneAt(int index); // new method to match String, not an overload of an existing method
public StringBuilder Insert(int index, Rune value);
public StringBuilder Replace(Rune oldRune, Rune newRune);
public StringBuilder Replace(Rune oldRune, Rune newRune, int startIndex, int count);
public bool TryGetRuneAt(int index, out Rune value); // new method, not overload of existing method
}
}
namespace System.IO
{
// Adds overloads to existing char-consuming methods
public partial abstract class TextWriter
{
public virtual void Write(Rune value);
public virtual Task WriteAsync(Rune value);
public virtual void WriteLine(Rune value);
public virtual Task WriteLineAsync(Rune value);
}
}
namespace System.Globalization
{
public partial class TextInfo
{
public Rune ToLower(Rune r);
public Rune ToUpper(Rune r);
}
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Runtime
Activity
GrabYourPitchforks commentedon Nov 15, 2018
I propose the
String.DoSomething(Rune value, ...)APIs that do not take aStringComparisonparameter default to ordinal. This matches the behavior that theString.DoSomething(char value, ...)APIs have (but does not necessarily match the behavior ofString.DoSomething(string value, ...)).Example:
terrajobst commentedon Nov 20, 2018
Rune:
Equalsmethods instance methods (first one is already there).StringBuilder:
EnumeratorRunes()(or whateverstringdoes).TextInfo
rtovalueTextWriter
Consider return. Probabably not, because it shifts the onus on the implementer.ValueTaskfor the async onesdanmoseley commentedon Jun 10, 2019
Moving to Future as this need not happen for 3.0 as these changes are additive.
29 remaining items
Add methods from #27912 (Flow System.Text.Rune through more APIs) (#1…
tarekgh commentedon Sep 26, 2025
Done through the PR #117168
Revert "Add methods from #27912 (Flow System.Text.Rune through more A…
Revert "Add methods from #27912 (Flow System.Text.Rune through more A…
jkotas commentedon Sep 26, 2025
The PR was reverted
Joy-less commentedon Sep 26, 2025
Please see #120145. The PR should be un-reverted now that the fixes are available.
Reapply "Add methods from dotnet#27912 (Flow System.Text.Rune through…
Fix test containing reflection erroring from #117168 (Add methods from …
tarekgh commentedon Sep 27, 2025
Fixed by #120145