quale dovrebbe essere il valore di ritorno di StringComparison.OrdinalIgnoreCase?

Aug 24 2020

Quando eseguo la riga sottostante

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

Ottengo il ritorno Val come -5. Qualcuno può spiegarmi perché è così? E anche con altri valori stringa ottengo il valore di ritorno come 13,15 ecc. Di solito dovrebbe essere -1,0,1. Se non sbaglio.

Risposte

1 RufusL Aug 24 2020 at 21:38

"Di solito dovrebbe essere -1,0,1. Se non sbaglio"

Hai ragione sul fatto che questi sono in genere i valori di ritorno del Comparemetodo e la pratica consigliata, anche nella documentazione per IComparer.Compare:

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

"Il IComparer.Comparemetodo richiede un confronto terziario. 1, 0O -1viene restituito a seconda che un valore sia maggiore, uguale o minore dell'altro. L'ordinamento (crescente o decrescente) può essere modificato cambiando gli operatori logici in questo metodo . "

Tuttavia, questo non viene applicato da nessuna parte.

Inoltre, la Stringclasse non implementa IComparer<string>e questo sovraccarico della Comparefirma non è comunque definito in quell'interfaccia.

Se guardiamo il codice sorgente per il Comparemetodo qui , vediamo che per OrdinalIgnoreCase, chiama il CompareOrdinalIgnoreCaseHelpermetodo, che restituisce la differenza di valore ASCII tra la prima coppia di caratteri non corrispondenti (dopo averli inseriti in maiuscolo) . Se le stringhe hanno lunghezze diverse ma i primi caratteri di quella più lunga corrispondono tutti a quelli di quella più corta, viene restituita la differenza nella loro lunghezza.

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 = &strA.m_firstChar) fixed (char* bp = &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;
    }
}

Pertanto, dovremmo sempre confrontare il risultato di un Comparemetodo con 0e non -1o 1.