Сравнение строк без учета регистра странное поведение - PullRequest
0 голосов
/ 12 октября 2018

Это происходит как в C #, так и в Java, так что я думаю, что это не ошибка, просто удивляюсь, почему.

var s = "?";
var lower = s.ToLower();
var upper = s.ToUpper();

if (!lower.Equals(upper, StringComparison.OrdinalIgnoreCase))
{
    //How can this happen?
}

Согласно этой странице нижний регистр "?"«?», они должны быть равны при сравнении с параметром IgnoreCase.Почему они не равны?

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Вы можете получить более интересные значения, когда вы приведете оба «?» и «?» к их числовым значениям.Вы получите для обоих одинаковое целое значение 55297 в качестве результата приведения.StringComparison.Ordinal основан на числовых значениях символов.Поскольку «Порядковый» означает «основанный на числе», и оба символа (заглавные и маленькие) имеют одинаковое порядковое значение после приведения, любое сравнение «основанное на числе» даст неожиданные результаты.OrdinalIgnoreCase, по-видимому, не определен для символов, которые имеют одинаковое «порядковое» значение как для заглавной, так и для маленькой версии символа, чтобы избежать непредвиденных результатов, и потерпит неудачу (то есть приведет к значению false) при сравнении таких символов.

0 голосов
/ 12 октября 2018

В защиту API Java: документация о методе String.equalsIgnoreCase никогда не утверждала, что он будет работать "как положено" в произвольных кодовых точках Юникода.В нем говорится:

Два символа c1 и c2 считаются одним и тем же регистром игнорирования, если верно хотя бы одно из следующего:

  • Два символа одинаковы (каксравнивается оператором ==)
  • Применение метода Character.toUpperCase (char) к каждому символу дает одинаковый результат
  • Применение метода Character.toLowerCase (char) к каждому символу дает одинаковыйрезультат

Итак, в документации совершенно недвусмысленно говорится, что она применяется Character.toUpperCase к char с, то есть к кодовым единицам UTF-16 , а не кКодовые точки Unicode.

Если вы используете метод Character.toUpperCase(int codePoint) для каждого кода point , то сравнение ведет себя как ожидалось.Вот краткий пример в Scala (использует тот же Java API, метод высшего порядка forall, надо надеяться, самоочевиден):

val a = "?"
val b = "?"
(a.codePoints.toArray zip b.codePoints.toArray).forall { 
  case (x, y) => 
  Character.toLowerCase(x) == Character.toLowerCase(y) 
}

печатает

true

какожидается.Почему это?Я думаю, что можно смело винить в этом обратную совместимость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...