Background and motivation
Since #32247/#40910, this code
string.Equals(a, b, StringComparison.OrdinalIgnoreCase)
is no longer equivalent to this code
a.ToUpperInvariant() == b.ToUpperInvariant()
That's why I'm proposing to add ToLowerOrdinal() and ToUpperOrdinal() methods that would be guaranteed to have the same semantics as OrdinalIgnoreCase comparisons, and that would also be guaranteed to be case folded letter-by-letter and have the same length as the input string (and IMO, ToLowerInvariant and ToUpperInvariant should be changed to use proper ICU case semantics that wouldn't have to result in the same length, as per #32247 (comment), but that's a separate discussion).
API Proposal
namespace System;
public sealed partial class String
{
public string ToLower();
public string ToLower(CultureInfo? culture);
public string ToLowerInvariant();
+ public string ToLowerOrdinal();
public string ToUpper();
public string ToUpper(CultureInfo? culture);
public string ToUpperInvariant();
+ public string ToUpperOrdinal();
}
public readonly partial struct Char
{
public static char ToLower(char c);
public static char ToLower(char c, CultureInfo culture);
public static char ToLowerInvariant(char c);
+ public static char ToLowerOrdinal(char c);
public static char ToUpper(char c);
public static char ToUpper(char c, CultureInfo culture);
public static char ToUpperInvariant(char c);
+ public static char ToUpperOrdinal(char c);
}
namespace System.Text;
public readonly partial struct Rune
{
public static Rune ToLower(Rune value, CultureInfo culture);
public static Rune ToLowerInvariant(Rune value);
+ public static Rune ToLowerOrdinal(Rune value);
public static Rune ToUpper(Rune value, CultureInfo culture);
public static Rune ToUpperInvariant(Rune value);
+ public static Rune ToUpperOrdinal(Rune value);
}
namespace System;
public static partial class MemoryExtensions
{
public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture);
public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination);
+ public static int ToLowerOrdinal(this ReadOnlySpan<char> source, Span<char> destination);
public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture);
public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination);
+ public static int ToUpperOrdinal(this ReadOnlySpan<char> source, Span<char> destination);
}
API Usage
...
Alternative Designs
No response
Risks
No response
cc @GrabYourPitchforks
Background and motivation
Since #32247/#40910, this code
is no longer equivalent to this code
That's why I'm proposing to add
ToLowerOrdinal()andToUpperOrdinal()methods that would be guaranteed to have the same semantics asOrdinalIgnoreCasecomparisons, and that would also be guaranteed to be case folded letter-by-letter and have the same length as the input string (and IMO,ToLowerInvariantandToUpperInvariantshould be changed to use proper ICU case semantics that wouldn't have to result in the same length, as per #32247 (comment), but that's a separate discussion).API Proposal
namespace System; public sealed partial class String { public string ToLower(); public string ToLower(CultureInfo? culture); public string ToLowerInvariant(); + public string ToLowerOrdinal(); public string ToUpper(); public string ToUpper(CultureInfo? culture); public string ToUpperInvariant(); + public string ToUpperOrdinal(); } public readonly partial struct Char { public static char ToLower(char c); public static char ToLower(char c, CultureInfo culture); public static char ToLowerInvariant(char c); + public static char ToLowerOrdinal(char c); public static char ToUpper(char c); public static char ToUpper(char c, CultureInfo culture); public static char ToUpperInvariant(char c); + public static char ToUpperOrdinal(char c); } namespace System.Text; public readonly partial struct Rune { public static Rune ToLower(Rune value, CultureInfo culture); public static Rune ToLowerInvariant(Rune value); + public static Rune ToLowerOrdinal(Rune value); public static Rune ToUpper(Rune value, CultureInfo culture); public static Rune ToUpperInvariant(Rune value); + public static Rune ToUpperOrdinal(Rune value); } namespace System; public static partial class MemoryExtensions { public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture); public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination); + public static int ToLowerOrdinal(this ReadOnlySpan<char> source, Span<char> destination); public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture); public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination); + public static int ToUpperOrdinal(this ReadOnlySpan<char> source, Span<char> destination); }API Usage
...
Alternative Designs
No response
Risks
No response
cc @GrabYourPitchforks