Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Culture-Invariant case-sensitive string comparison returns different results on different machines

I've found that the test results are different on my machine and the build server. I've managed to find the single line that differs. This is a string comparison. The two strings differ in case of the first character.

The test below passes on my local machine and fails on the build machine.

[TestClass]
public class Tests 
{
    [TestMethod]
    public void Strings()
    {
        Assert.IsFalse(0 == string.Compare("Term’s", "term’s", false, CultureInfo.InvariantCulture));
    }
}

I've also tried to change it to string.Equals:

string.Equals("Term’s", "term’s", StringComparison.InvariantCulture);

string.Equals returns true on the build server and returns false on my local machine.

Ordinal comparison gives same results on both machines:

string.Compare("Term’s", "term’s", StringComparison.Ordinal))

As I understand, InvariantCulture is supposed to return the same results everywhere. How can a case-sensitive culture-invariant string comparison depend on a machine? What settings should I check to identify the problem?

Update: platform and string

The string is important. These results can be observed for strings with "exotic" punctuation like RIGHT SINGLE QUOTATION MARK or RIGHT DOUBLE QUOTATION MARK

It seems the behavior reproduces on Windows 8 machines. You can see it even on https://dotnetfiddle.net/ if you type the following:

using System;
using System.Globalization;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(0 == string.Compare("Terms", "terms", false, CultureInfo.InvariantCulture));
        Console.WriteLine(0 == string.Compare("Term’s", "term’s", false, CultureInfo.InvariantCulture));
        Console.WriteLine(0 == string.Compare("Term“s", "term“s", false, CultureInfo.InvariantCulture));
        Console.WriteLine(0 == string.Compare("Term”s", "term”s", false, CultureInfo.InvariantCulture));

        //outputs
        //False
        //True
        //True
        //True
    }
}

Environment.OSVersion (server's): Microsoft Windows NT 6.2.9200.0
Environment.Is64BitOperatingSystem (server's): True
Environment.Version (server's) 4.0.30319.18449

Environment.OSVersion (local): Microsoft Windows NT 6.1.7601 Service Pack 1
Environment.Is64BitOperatingSystem (local): True
Environment.Version (local): 4.0.30319.18444

Update: related MSDN forums link

It may be a known bug in Windows 8, which is fixed in Windows 8.1.

http://social.msdn.microsoft.com/Forums/vstudio/en-US/4a1ab6b7-6dcc-46bf-8650-e0d9ebbf1735/stringcompare-not-always-casesensitive-on-windows-8?forum=netfxbcl

like image 522
filhit Avatar asked Sep 08 '14 15:09

filhit


1 Answers

InvariantCulture is unfortunately still a linguistic comparison and as such it can vary (and does vary, especially when new characters are added to Unicode) between versions of the OS. Versions of .Net prior to 4.0 carried their own payload of data and thus would not vary but since then they pick up the data from the OS and will potentially vary. Ordinal is the only comparison that will not change and is what you really need to do if you desire stability.

That said, you should not be seeing differences in behavior for the code that you supply. The differences you observe are due to a bug with Windows 8 that has been fixed in Windows 8.1.

like image 129
Eric MSFT Avatar answered Sep 22 '22 04:09

Eric MSFT