Как метод 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 3

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 - и обратите внимание, что этот список фактически не включает обычный дефис.)