#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
.