Warum kann der Standard-Zeichenfolgenvergleich die transitive Konsistenz nicht aufrechterhalten?

Ich kenne dieses Problemwurde schon einmal notiert, mehr oder weniger prägnant, aber ich erstelle immer noch diesen neuen Thread, weil ich beim Schreiben eines Komponententests erneut auf das Problem gestoßen bin.

Der standardmäßige Zeichenfolgenvergleich (dies ist der kulturabhängige Vergleich, bei dem zwischen Groß- und Kleinschreibung unterschieden wird)string.CompareTo(string), Comparer<string>.Default, StringComparer.CurrentCulture, string.Compare(string, string) und andere) verstoßen gegen die Transitivität, wenn die Zeichenfolgen Bindestriche enthalten (oder Minuszeichen, ich spreche von einfachen U + 002D-Zeichen).

Hier ist ein einfacher Repro:

static void Main()
{
  const string a = "fk-";
  const string b = "-fk";
  const string c = "Fk";

  Console.WriteLine(a.CompareTo(b));  // "-1"
  Console.WriteLine(b.CompareTo(c));  // "-1"
  Console.WriteLine(a.CompareTo(c));  // "1"

  var listX = new List<string> { a, b, c, };
  var listY = new List<string> { c, a, b, };
  var listZ = new List<string> { b, c, a, };
  listX.Sort();
  listY.Sort();
  listZ.Sort();
  Console.WriteLine(listX.SequenceEqual(listY));  // "False"
  Console.WriteLine(listY.SequenceEqual(listZ));  // "False"
  Console.WriteLine(listX.SequenceEqual(listZ));  // "False"
}

Im oberen Teil sehen wir, wie die Transitivität versagt.a ist weniger alsb, undb ist weniger alsc, nocha nicht kleiner sein alsc.

Das geht gegen diedokumentiertes Verhalten der Unicode-Kollatierung, die besagt, dass:

... für alle Zeichenfolgen A, B und C, wenn A <B und B <C, dann A <C.

Nun sortiere ich eine Liste mita, b undc ist genau wie der Versuch, die Hände zu ordnen"Rock", "Paper" und "Scissors" im bekannten intransitiven Spiel. Eine unmögliche Aufgabe.

Der letzte Teil meines obigen Codebeispiels zeigt, dass das Ergebnis der Sortierung von der anfänglichen Reihenfolge der Elemente abhängt (und es gibt keine zwei Elemente in der Liste, die "gleich" vergleichen (0)).

Linq'slistX.OrderBy(x => x) ist natürlich auch betroffen. Dies sollte eine stabile Sortierung sein, aber Sie erhalten seltsame Ergebnisse, wenn Sie eine Sammlung mit bestellena, b undc zusammen mit anderen Saiten.

Ich habe es mit versuchtalle dasCultureInfos auf meinem Computer (da dies eine kulturabhängige Art ist), einschließlich der "invarianten Kultur", und jeder hat das gleiche Problem. Ich habe dies mit der .NET 4.5.1-Laufzeit versucht, aber ich glaube, ältere Versionen haben den gleichen Fehler.

Fazit: Wenn Sie Zeichenfolgen in .NET mit dem Standardvergleich sortieren, sind die Ergebnisse nicht vorhersehbar, wenn einige Zeichenfolgen Bindestriche enthalten.

Welche Änderungen wurden in .NET 4.0 eingeführt, die dieses Verhalten verursachten?

Es wurde bereits festgestellt, dass dieses Verhalten in verschiedenen Versionen der Plattform inkonsistent ist: In .NET 3.5 können Zeichenfolgen mit Bindestrichen zuverlässig sortiert werden. In allen Versionen des Frameworks aufrufenSystem.Globalization.CultureInfo.CurrentCulture.CompareInfo.GetSortKey bietet einzigartigDeyData Warum werden diese Zeichenfolgen für diese Zwecke nicht richtig sortiert?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage