-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comparer<string>.Default sort order different on Linux/OSX than Windows or Mono #20109
Comments
I suspect the difference is with |
@JonHanna looks like you're right: foreach (string k in keys)
{
foreach (string i in keys) Console.Write(Comparer<string>.Default.Compare(k, i));
Console.WriteLine();
} prints this on Windows/Mono:
and this on .NET Core OSX:
|
|
Changed the title. Though looking at it |
Are both OSes same culture - what does |
@jkotas it's empty. But I get the same result if I force English with |
A more concise repro: using System;
using System.Globalization;
class Program
{
static void Main()
{
Console.WriteLine(CultureInfo.CurrentCulture.CompareInfo.Name);
Console.WriteLine(CultureInfo.CurrentCulture.CompareInfo.Compare(",", ")"));
}
} On my Windows machine this outputs:
On my Linux machine this outputs:
|
On Linux, .NET Core uses ICU for string collation. See http://demo.icu-project.org/icu-bin/collation.html And type in So unless we are choosing the wrong culture, whatever ICU says should be the order is what is returned. Note there is never a guarantee of culture information being consistent between OSs, or even different versions of the same OS. If you are looking for consistent ordering, |
@eerhardt Mono uses ICU as well, so there shouldn't be a difference AFAIK. If you select |
If you wanted to use Console.WriteLine(CultureInfo.CurrentCulture.CompareInfo.Name);
Console.WriteLine(CultureInfo.CurrentCulture.CompareInfo.Compare(",", ")"));
CultureInfo posix = new CultureInfo("en-us-posix");
Console.WriteLine(posix.CompareInfo.Name);
Console.WriteLine(posix.CompareInfo.Compare(",", ")"));
|
@eerhardt so you are saying this is by design? just want to know if there is anything we need to do here. |
We just use whatever ICU says. So yes, I kind of think this is "by design", unless we are saying we are using ICU incorrectly. We (.NET Core) don't actually control culture-based string comparisons. |
Or, it sounds like unless we're saying we think we should change the default culture. If Mono is also using ICU but is getting different results, is it using a different culture by default? |
I did some searching last night in mono, and I couldn't find where ICU was actually being used. #if MONO
return internal_compare_switch (string1, 0, string1.Length, string2, 0, string2.Length, options);
#else
return InternalCompareString(m_dataHandle, m_handleOrigin, m_sortName, string1, 0, string1.Length, string2, 0, string2.Length, GetNativeCompareFlags(options));
#endif Where return UseManagedCollation ?
internal_compare_managed (str1, offset1, length1,
str2, offset2, length2, options) :
internal_compare (str1, offset1, length1,
str2, offset2, length2, options); And "ManagedCollation" looks like it is on by default: static bool UseManagedCollation {
get {
if (!managedCollationChecked) {
managedCollation = Environment.internalGetEnvironmentVariable ("MONO_DISABLE_MANAGED_COLLATION") != "yes" && MSCompatUnicodeTable.IsReady;
managedCollationChecked = true;
}
return managedCollation;
}
} That Anyway, if it doesn't use "managed collation", it just does invariant: int ves_icall_System_Globalization_CompareInfo_internal_compare (MonoCompareInfo *this_obj, MonoString *str1, gint32 off1, gint32 len1, MonoString *str2, gint32 off2, gint32 len2, gint32 options)
{
/* Do a normal ascii string compare, as we only know the
* invariant locale if we dont have ICU
*/
return(string_invariant_compare (str1, off1, len1, str2, off2, len2,
options));
} |
Seems like I misremembered, we do use the CLDR data (which ICU uses too) for certain things like date/time formats, but not ICU directly. String comparison is done differently too, so this seems like it's working as expected. Sorry about that, it makes sense now why .NET Core behaves different in this case. Thanks 👍 |
We are in the process of migrating some legacy applications to core to run on Linux. Does anyone have a recommended workaround for this ( I need the sort order to be identical across platforms)? I would rather not change the internal behaviors of the project/s during the port. I would prefer to preserve the current behavior and possibly refactor out any needed workarounds during a future iteration. Thanks! |
There is no good way to do that rather than build your own sorting component and use it. That is similar to what SQL is doing. |
@tarekgh thanks for your quick response. |
I cannot find any way to make XslCompiledTransform sort according to good old ASCII both on Linux and Windows. On Linux I can use CultureInfo("en-us-posix") but on Windows I don't know what to do. |
Found this while investigating #20007 (edit: see https://github.com/dotnet/corefx/issues/15825#issuecomment-277564885 where it looks like
Comparer<string>.Default
is the underlying culprit):This prints the following on OSX/Linux:
However, on Windows .NET Core or .NET Framework, as well as Mono on OSX/Linux it prints:
I suspected a difference due to culture/language, but forcing CurrentCulture to "en-US" didn't change the output. Maybe I'm not setting it correctly?
The text was updated successfully, but these errors were encountered: