каким должно быть возвращаемое значение StringComparison.OrdinalIgnoreCase?

#c# #string #compare #string-comparison

#c# #строка #Сравнить #сравнение строк

Вопрос:

Когда я выполняю приведенную ниже строку

 returnVal=string.Compare("stringOne","stringTwo",StringComparison.OrdinalIgnoreCase);
  

Я получаю возвращаемое значение как -5.
Кто-нибудь, пожалуйста, может объяснить мне, почему это так? А также с другими строковыми значениями я получаю возвращаемое значение как 13,15 и т.д.
Обычно оно должно быть -1,0,1. Если я не ошибаюсь.

Комментарии:

1. Я предполагаю, что для эффективности это гарантирует только некоторое отрицательное значение для <. 0 для equal и некоторое положительное значение для > .

2. Черт, набирал ответ… Вы получаете -5, потому что "One" , особенно 'O' , это 5 букв перед 'T'

3. string.Compare("a","b"); <— -1 , в то время как string.Compare("a","z"); <— -25

Ответ №1:

«Обычно это должно быть -1,0,1. Если я не ошибаюсь»

Вы правы в том, что обычно это возвращаемые значения Compare метода и рекомендуемая практика, даже в документации для IComparer.Compare :

https://learn.microsoft.com/en-us/troubleshoot/dotnet/csharp/use-icomparable-icomparer

« IComparer.Compare Метод требует третичного сравнения. 1 , 0 или -1 возвращается в зависимости от того, является ли одно значение больше, равным или меньше другого. Порядок сортировки (по возрастанию или убыванию) может быть изменен путем переключения логических операторов в этом методе.»

Однако это нигде не применяется.

Кроме того, String класс не реализует IComparer<string> , и эта перегрузка Compare подписи в любом случае не определена в этом интерфейсе.

Если мы посмотрим на исходный код Compare метода здесь, мы увидим, что для OrdinalIgnoreCase он вызывает CompareOrdinalIgnoreCaseHelper метод, который возвращает разницу в значении ascii между первой парой несовпадающих символов (после их ввода в верхнем регистре). Если строки имеют разную длину, но все первые символы более длинной строки совпадают с символами более короткой, то возвращается разница в их длине.

 private unsafe static int CompareOrdinalIgnoreCaseHelper(String strA, String strB)
{
    Contract.Requires(strA != null);
    Contract.Requires(strB != null);
    Contract.EndContractBlock();
    int length = Math.Min(strA.Length, strB.Length);

    fixed (char* ap = amp;strA.m_firstChar) fixed (char* bp = amp;strB.m_firstChar)
    {
        char* a = ap;
        char* b = bp;

        while (length != 0) 
        {
            int charA = *a;
            int charB = *b;

            Contract.Assert((charA | charB) <= 0x7F, "strings have to be ASCII");

            // uppercase both chars - notice that we need just one compare per char
            if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
            if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;

            //Return the (case-insensitive) difference between them.
            if (charA != charB)
                return charA - charB;

            // Next char
            a  ; b  ;
            length--;
        }

        return strA.Length - strB.Length;
    }
}
  

Поэтому мы всегда должны сравнивать результат Compare метода с 0 , а не с -1 или 1 .