When i execute the below line
returnVal=string.Compare("stringOne","stringTwo",StringComparison.OrdinalIgnoreCase);
I get the returnVal as -5. Can anyone please explain me why is it like that? And also with other string values i get return value as 13,15 etc. It should usually be -1,0,1. If i am not wrong.
"It should usually be -1,0,1. If i am not wrong"
You are correct that those are typically the return values of the Compare
method, and the recommended practice, even in the documentation for IComparer.Compare
:
https://learn.microsoft.com/en-us/troubleshoot/dotnet/csharp/use-icomparable-icomparer
"The
IComparer.Compare
method requires a tertiary comparison.1
,0
, or-1
is returned depending on whether one value is greater than, equal to, or less than the other. The sort order (ascending or descending) can be changed by switching the logical operators in this method."
However, this isn't enforced anywhere.
Also, the String
class doesn't implement IComparer<string>
, and this overload of the Compare
signature is not defined in that interface anyway.
If we look at the source code for the Compare
method here, we see that for OrdinalIgnoreCase
, it calls the CompareOrdinalIgnoreCaseHelper
method, which returns the ascii value difference between the first pair of non-matching characters (after upper-casing them). If the strings are different lengths but the first characters of the longer one all match those of the shorter, then the difference in their length is returned.
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;
}
}
Therefore, we should always compare the result of a Compare
method to 0
and not -1
or 1
.