What's wrong
SemanticString<T>.CompareTo (Semantics.Strings/SemanticString.cs:95-103), and the <, <=, >, >= operators built on it (lines 441-465), delegate to string.CompareTo(string), which performs a culture-sensitive linguistic comparison using the current thread culture. Meanwhile Equals/GetHashCode on the same record are compiler-generated from WeakString alone, using EqualityComparer<string>.Default, which is ordinal. The rest of the codebase (e.g. PhysicalConstants, ConversionsGenerator) is otherwise scrupulous about invariant-culture parsing/formatting.
Why it matters (failure scenario)
.NET explicitly documents that culture-sensitive (StringComparison.CurrentCulture) comparisons give punctuation minimal collation weight, so e.g. "Co-op" and "Coop", or "e-mail" and "email", compare as equal (CompareTo == 0) even though they are Equals-distinct and hash differently. Since CompareTo/</<=/>/>= are public API inherited by every semantic string type — including hyphen-containing types like Uuid/Iban — this breaks the IComparable/IEquatable consistency contract:
- Sorting becomes machine/culture-dependent: the same two values can order differently depending on the running culture (e.g.
tr-TR).
SortedSet<T>/SortedDictionary<TKey,_> treat any two keys with CompareTo == 0 as duplicates, so two distinct, independently valid values (e.g. two different Iban/Uuid instances) can collide and one gets silently discarded.
Suggested fix / acceptance criteria
Change CompareTo to use ordinal comparison (string.CompareOrdinal(WeakString, other), or WeakString.AsSpan().CompareTo(other, StringComparison.Ordinal)), matching the ordinal semantics Equals/GetHashCode already use. Add a test asserting a.CompareTo(b) == 0 iff a.Equals(b).
What's wrong
SemanticString<T>.CompareTo(Semantics.Strings/SemanticString.cs:95-103), and the<,<=,>,>=operators built on it (lines 441-465), delegate tostring.CompareTo(string), which performs a culture-sensitive linguistic comparison using the current thread culture. MeanwhileEquals/GetHashCodeon the same record are compiler-generated fromWeakStringalone, usingEqualityComparer<string>.Default, which is ordinal. The rest of the codebase (e.g.PhysicalConstants,ConversionsGenerator) is otherwise scrupulous about invariant-culture parsing/formatting.Why it matters (failure scenario)
.NET explicitly documents that culture-sensitive (
StringComparison.CurrentCulture) comparisons give punctuation minimal collation weight, so e.g."Co-op"and"Coop", or"e-mail"and"email", compare as equal (CompareTo == 0) even though they areEquals-distinct and hash differently. SinceCompareTo/</<=/>/>=are public API inherited by every semantic string type — including hyphen-containing types likeUuid/Iban— this breaks theIComparable/IEquatableconsistency contract:tr-TR).SortedSet<T>/SortedDictionary<TKey,_>treat any two keys withCompareTo == 0as duplicates, so two distinct, independently valid values (e.g. two differentIban/Uuidinstances) can collide and one gets silently discarded.Suggested fix / acceptance criteria
Change
CompareToto use ordinal comparison (string.CompareOrdinal(WeakString, other), orWeakString.AsSpan().CompareTo(other, StringComparison.Ordinal)), matching the ordinal semanticsEquals/GetHashCodealready use. Add a test assertinga.CompareTo(b) == 0iffa.Equals(b).