.NET и юникод
От: _NN_ www.nemerleweb.com
Дата: 28.01.24 11:34
Оценка: 18 (3)
Как считаете, какой должен быть вывод этой программы ?

Проверьте себя .NET Framework, .NET 8.

using System;
                    
public class Program
{
    public static void Main()
    {
        string one = 1.ToString();
        bool starts = one.StartsWith("\U00011052"); // 𑁒
        bool equals_inv = one.Equals("\U00011052", System.StringComparison.InvariantCulture);
        bool equals = one.Equals("\U00011052");
        System.Console.WriteLine(starts);
        System.Console.WriteLine(equals_inv);
        System.Console.WriteLine(equals);
    }
}


  Для нетерпеливых
https://github.com/dotnet/csharplang/discussions/7876
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: .NET и юникод
От: m2user  
Дата: 28.01.24 19:31
Оценка:
Поведение конечно неожиданно. Но что ты хотел получить сравнивая строки без указания культуры
MS везде (в частности в code anlysis) пишет о том, что так делать не стоит.
Хотя бы потому, что если культура не указана, то берётся текущая локаль потока выполнения, которая в свою очередь зависит от локали процесса/пользователя/машины.
И может быть совсем не такой, какую ожидает разработчик.

Дополню: CA rules по глобализации: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/globalization-warnings

Best practices for comparing strings in .NET

Comparisons that use current culture semantics are the default for the following methods:

String.Compare overloads that don't include a StringComparison parameter.
String.CompareTo overloads.
The default String.StartsWith(String) method, and the String.StartsWith(String, Boolean, CultureInfo) method with a nullCultureInfo parameter.
The default String.EndsWith(String) method, and the String.EndsWith(String, Boolean, CultureInfo) method with a nullCultureInfo parameter.
String.IndexOf overloads that accept a String as a search parameter and that don't have a StringComparison parameter.
String.LastIndexOf overloads that accept a String as a search parameter and that don't have a StringComparison parameter.


Ordinal semantics are the default for String.Equals overloads that don't include a StringComparison argument (including the equality operator).


Т.е. результат String.StartsWith зависит от локали потока выполнения, и только по коду однозначно ответить нельзя.
Отредактировано 28.01.2024 21:20 m2user . Предыдущая версия .
Re[2]: .NET и юникод
От: _NN_ www.nemerleweb.com
Дата: 29.01.24 09:19
Оценка: +1
Здравствуйте, m2user, Вы писали:

M>Поведение конечно неожиданно. Но что ты хотел получить сравнивая строки без указания культуры


В тои и дело что даже указывая культуру результат немного другой в .NET 8.

using System;
                    
public class Program
{
    public static void Main()
    {
        string one = 1.ToString();
        bool starts_inv = one.StartsWith("\U00011052", System.StringComparison.InvariantCulture);
        bool starts_ord = one.StartsWith("\U00011052", System.StringComparison.Ordinal);
        bool starts = one.StartsWith("\U00011052"); // 𑁒
        bool equals_inv = one.Equals("\U00011052", System.StringComparison.InvariantCulture);
        bool equals_ord = one.Equals("\U00011052", System.StringComparison.Ordinal);
        bool equals = one.Equals("\U00011052");
        System.Console.WriteLine(starts_inv);
        System.Console.WriteLine(starts_ord);
        System.Console.WriteLine(starts);
        System.Console.WriteLine(equals_inv);
        System.Console.WriteLine(equals_ord);
        System.Console.WriteLine(equals);
    }
}


Результат:
  .NET Framework
False
False
False
False
False
False


  .NET 8
True
False
True
True
False
False
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: .NET и юникод
От: m2user  
Дата: 29.01.24 10:19
Оценка: 14 (1)
_NN>В тои и дело что даже указывая культуру результат немного другой в .NET 8.

Я полагаю, это с этим связано: Behavior changes when comparing strings on .NET 5+

Чтобы проверить, работает ли переключение на старую библиотеку (NLS), нужна машинка с MS Windows.

System.Globalization.UseNls:
false — Use ICU globalization APIs
true — Use NLS globalization APIs

Re[4]: .NET и юникод
От: _NN_ www.nemerleweb.com
Дата: 30.01.24 07:48
Оценка: +1
Здравствуйте, m2user, Вы писали:

Тут ещё стоит отметить , что в Equals в отличии от других методов сравнение по умолчанию использует Ordinal.
С точки зрения производительности это конечно хорошо, но может давать неожиданное поведение.
Т.е. строки могут быть разными по Equals но StartsWith с культурой по умолчанию либо инвариантной вернёт истину.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: .NET и юникод
От: Baiker  
Дата: 21.07.24 20:17
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Как считаете, какой должен быть вывод этой программы ?


_NN>System.StringComparison.InvariantCulture);


Вопрос с задних рядов: а причём тут вообще КУЛЬТУРА при сравнении строк? Или это намёк, что где-то есть такой "умный" код, который считает "понедельник" == "monday"?
Мы изобрели юникод не для того, чтобы ещё больше прыгать со всякими "особенностями сравнения строк на земном шаре". Case-sensitivity — всё, что нам надо от "культуры".
Поправьте каким-нть примером, где эта "культура" ещё нужна?
Re[2]: .NET и юникод
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.07.24 02:38
Оценка: 15 (3) +1
Здравствуйте, Baiker, Вы писали:

B>Вопрос с задних рядов: а причём тут вообще КУЛЬТУРА при сравнении строк? Или это намёк, что где-то есть такой "умный" код, который считает "понедельник" == "monday"?

B>Мы изобрели юникод не для того, чтобы ещё больше прыгать со всякими "особенностями сравнения строк на земном шаре". Case-sensitivity — всё, что нам надо от "культуры".
B>Поправьте каким-нть примером, где эта "культура" ещё нужна?
Ещё много где нужна. Та же case insensitivity работает в разных культурах по-разному. В частности, в Турции lowercase I вовсе не равна i. И uppercase от i не будет равно I.
При том, что сами эти буквы — ровно те же самые (а не как у нас — кириллическая а и латинская a имеют разные code points).
Опять же, чувствительность к умляутам при сравнении. Должны ли строки "осёл" и "осел" считаться одинаковыми? А "йод" и "иод"?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: .NET и юникод
От: syrompe  
Дата: 22.07.24 20:20
Оценка:
M>Поведение конечно неожиданно. Но что ты хотел получить сравнивая строки без указания культуры

Также:
string one = 1.ToString();


без культуры по идее может вернуть бяку.
Re[3]: .NET и юникод
От: Baiker  
Дата: 23.07.24 13:57
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

B>> Case-sensitivity — всё, что нам надо от "культуры".


S>Ещё много где нужна. Та же case insensitivity ....


Мы говорим об одном и том же

S>В частности, в Турции lowercase I вовсе не равна i. И uppercase от i не будет равно I.


Ну вот! Здесь "культура" уместна и это задача юникодного стандарта.

S>Опять же, чувствительность к умляутам при сравнении. Должны ли строки "осёл" и "осел" считаться одинаковыми? А "йод" и "иод"?


Нет, это разные строки. То, что в "культурных особенностях" иногда допускается опускание точек(потому что ЧЕЛОВЕК может применить дополнительные умственные усилия и ДОГАДАТЬСЯ, где Е, а где Ё), не делает слова одинаковыми.
Так что я не понимаю эти "прыжки в ширину" вокруг юникода (я про самый старт топика). Учитывать "не английские" народности нужно, но впадать в глубокий маразм со всеми культурными особенностями не стоит.
Та же "." и "," в числах может повлечь очень серьёзные ошибки вычислений! Некоторым маленьким, но гордым народам стоит уже перестать маяться %%%%й и принять стандарт "." (а заодно избавиться от маразматических фунтов и дюймов).
Re[4]: .NET и юникод
От: m2user  
Дата: 23.07.24 14:22
Оценка:
B>Нет, это разные строки. То, что в "культурных особенностях" иногда допускается опускание точек(потому что ЧЕЛОВЕК может применить дополнительные умственные усилия и ДОГАДАТЬСЯ, где Е, а где Ё), не делает слова одинаковыми.

Смотря какой comparison. Если ordinal, то конечно разные.
Предположим у тебя сравнение c IgnoreCase: в английской культуре i==I, а в турецкой — нет, там i==İ и ı==I. При этом бинарное представление у турецких I,i такое же как у латинских.

Взять тот же MS SQL Server: Collation у БД: CS/CI, AS/AI (accent sensitive), не говоря уже про KS (Distinguishes between the two types of Japanese kana characters: Hiragana and Katakana).
Так что культура имеет значение.

P.S. а ведь есть ещё такая странная штука как InvariantCulture.
Re[4]: .NET и юникод
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.07.24 16:43
Оценка:
Здравствуйте, Baiker, Вы писали:
B>Ну вот! Здесь "культура" уместна и это задача юникодного стандарта.
"Здесь" в данном топике — это "в сравнении строк". Я не очень понимаю, как вы собираетесь перевалить эту задачу на юникодный стандарт.

S>>Опять же, чувствительность к умляутам при сравнении. Должны ли строки "осёл" и "осел" считаться одинаковыми? А "йод" и "иод"?

B>Нет, это разные строки.
Прекрасно. А Über и Uber — одинаковые или разные?

B>То, что в "культурных особенностях" иногда допускается опускание точек(потому что ЧЕЛОВЕК может применить дополнительные умственные усилия и ДОГАДАТЬСЯ, где Е, а где Ё), не делает слова одинаковыми.

Всё ровно наоборот — "одинаковость" похожих строк определяется культурой.
Вот у вас задача — сделать case-insensitive логин в систему. Пользователь вводит юзернейм Igor. Совпадает ли он с хранящимся в базе "igör"? Как вы это поймёте без культуры?

B>Так что я не понимаю эти

Это вполне очевидно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.