Как метод c# compareto сравнивает строки
Я хочу знать, как CompareTo метод C# сравнивает две строки, поэтому я протестировал так:
string str1 = "0";
string str2 = "-";
Console.WriteLine(str1.CompareTo(str2)); // output : 1
string str3 = "01";
string str4 = "-1";
Console.WriteLine(str3.CompareTo(str4)); // output : -1
Почему результаты отличаются?
1 ответ:
TLDR : порядок лексикографических строк по умолчанию специально обрабатывает символы
Ответ на этот вопрос заключается в том, что сравнение строк по умолчанию использует правила лексикографической сортировки. Это означает, что некоторые символы - например,-
.-
- обрабатываются специально.Документация для CompareOptions гласит:
Платформа .NET Framework использует три различных способа сортировки: сортировка слов, сортировка строк и сортировка по порядку. Слово сортировка выполняется с учетом культуры сравнение строк. Некоторые символы могут иметь им присваиваются специальные веса. Например, дефис ( " - " ) может быть имеют очень малый вес, назначенный ему так, что "coop" и " co-op" появляются рядом друг с другом в отсортированном списке. Сортировка строк похожа на слово сортировка, за исключением того, что нет особых случаев. Поэтому все приходят алфавитно-цифровые символы, прежде чем все алфавитно-цифровые символы. Порядковое сравнение строк на основе Значения Unicode каждого элемент строки.
В вашем случае используется порядок по умолчанию: сортировка слов.
Вы можете увидеть различные результаты, указав тип сравнения, который вы хотите в
string.Compare()
:Здесь вы можете видеть, что он обрабатываетstring str3 = "01"; string str4 = "-1"; Console.WriteLine(Math.Sign(string.Compare(str3, str4, StringComparison.InvariantCulture))); // output : -1 Console.WriteLine(Math.Sign(string.Compare(str3, str4, StringComparison.Ordinal))); // output : 1
-
специально, когда не делает порядкового сравнения.Это действительно
-
, который обрабатывается специально - это не предполагает, что это знак минус. Например, если вы используете+
вместо-
Вы получаете:string str1 = "0"; string str2 = "+"; Console.WriteLine(Math.Sign(string.Compare(str1, str2, StringComparison.InvariantCulture))); // output : 1 Console.WriteLine(Math.Sign(string.Compare(str1, str2, StringComparison.Ordinal))); // output : 1 string str3 = "01"; string str4 = "+1"; Console.WriteLine(Math.Sign(string.Compare(str3, str4, StringComparison.InvariantCulture))); // output : 1 Console.WriteLine(Math.Sign(string.Compare(str3, str4, StringComparison.Ordinal))); // output : 1
В сторону
Не путайте обычный дефис с мягким дефисом!
- обычный дефис имеет значение Unicode
\u002D
.- мягкий дефис имеет значение Unicode
\u00AD
.Примечание документация для
string.Compare()
который имеет пример кода, который показывает, что мягкий дефисигнорируется. В документации говорится:Наборы символов включают игнорируемые символы. То Метод Compare (String, String, Boolean) не учитывает такие символы, когда он выполняет сравнение с учетом культуры.
Aмягкий дефис является одним из игнорируемых символов, но важно отметить, что мягкий дефис-это не то же самое, что обычный дефис. Таким образом, эта документация не относится к вашему образцу кода.
Фактическая причина того, что нормальный дефис ведет себя иначе, приведена выше.(Если вы хотите полный список всех игнорируемые символы в Юникоде, перейдите к http://www.unicode.org/Public/UNIDATA/DerivedCoreProperties.txt и поиск
Default_Ignorable_Code_Point
- и обратите внимание, что этот список фактически не включает обычный дефис.)