Intereting Posts
Почему я не должен использовать AutoDual? Переопределение полей или свойств в подclassах ASP.NET Core 1.1 работает нормально локально, но при публикации в Azure говорится: «Ошибка при запуске приложения». Нужно регистрировать asp.net webapi 2 тело запроса и ответа в базе данных OutputCache в моем веб-приложении asp.net mvc. Множественный синтаксис для предотвращения кеширования web api put распознает строки запроса, но не тело Установка таймаута команды в инфраструктуре сущности 4.3 Можно ли удалять точку останова навсегда при отладке? Проблема шифрования / дешифрования RSA в .NET. Необработанное исключение после перехода на платформу Entity Framework 4.3.1 Динамически меняющаяся схема в ядре Entity Framework создание простого листа excel в c # со строками в качестве входных данных Клиент WCF Test не может добавить службу, не может получать метаданные Насколько хорошим / плохим является программирование sharepoint? Как сериализовать List в XML?

someString.IndexOf (someString) возвращает 1 вместо 0 в .NET 4

Недавно мы обновили все наши проекты с .NET 3.5 до .NET 4. Я столкнулся с довольно странной проблемой в отношении string.IndexOf() .

Мой код явно делает что-то немного другое, но в процессе изучения проблемы я обнаружил, что вызов IndexOf() в строке с самим собой возвращает 1 вместо 0. Другими словами:

 string text = "\xAD\x2D"; // problem happens with "-dely N.China", too; int index = text.IndexOf(text); // see update note below. 

Дал мне индекс 1, а не 0. Несколько вещей, чтобы отметить эту проблему:

  • Проблемы, похоже, связаны с этими дефисами (первый символ – это мягкий дефис Юникода, второй – обычный дефис).

  • Я проверил дважды, этого не происходит в .NET 3.5, но в .NET 4.

  • Изменение IndexOf() для сравнения по порядку устраняет проблему, поэтому по какой-то причине первый символ игнорируется с помощью IndexOf по умолчанию.

кто-нибудь знает, почему это произошло?

РЕДАКТИРОВАТЬ

Извините, ребята, немного набросились на оригинальный пост и дважды нашли скрытую черту. Я обновил строку, это должно возвращать индекс 1 вместо 2, если вы вставляете его в правильный редактор.

Обновить:

Изменена исходная строка проблемы, в которой четко видны все фактические символы (с помощью экранирования). Это немного упрощает вопрос.

Ваша строка существует из двух символов: мягкий дефис (код Юникода 173) и дефис (код юникода 45).

Wiki : Согласно стандарту Unicode, мягкая дефис не отображается, если линия не сломана в этой точке.

При использовании "\xAD\x2D".IndexOf("\xAD\x2D") в .NET 4, кажется, игнорируется, что вы ищете мягкий дефис, возвращая начальный индекс 1 (индекс \x2D ) , В .NET 3.5 это возвращает 0.

Более забавно, если вы запустите этот код (поэтому, когда вы ищете мягкий дефис):

 string text = "\xAD\x2D"; string shy = "\xAD"; int i1 = text.IndexOf(shy); 

то i1 становится 0, независимо от используемой версии .NET. Результат text.IndexOf(text); действительно меняется, что с первого взгляда выглядит как ошибка для меня.

Насколько я могу отследить структуру, более старые версии .NET используют InternalCall для IndexOfString() (я не могу понять, к какому вызову API), а из .NET 4 – QCall to InternalFindNLSStringEx() , который, в свою очередь, вызывает FindNLSStringEx() .

Проблема (я действительно не могу понять, является ли это предполагаемым поведением) действительно возникает при вызове FindNLSStringEx :

 LPCWSTR lpStringSource = L"\xAD\x2D"; LPCWSTR lpStringValue = L"\xAD"; int length; int i = FindNLSStringEx( LOCALE_NAME_SYSTEM_DEFAULT, FIND_FROMSTART, lpStringSource, -1, lpStringValue, -1, &length, NULL, NULL, 1); Console::WriteLine(i); i = FindNLSStringEx( LOCALE_NAME_SYSTEM_DEFAULT, FIND_FROMSTART, lpStringSource, -1, lpStringSource, -1, &length, NULL, NULL, 1); Console::WriteLine(i); Console::ReadLine(); 

Распечатывает 0 и затем 1. Обратите внимание, что length , параметр out, указывающий длину найденной строки, равен 0 после первого вызова и 1 после второго; мягкий дефис считается равным 0.

Обходной путь заключается в использовании text.IndexOf(text, StringComparison.OrdinalIgnoreCase); , как вы уже отметили. Это делает QCall для InternalCompareStringOrdinalIgnoreCase() который, в свою очередь, вызывает FindStringOrdinal() , который возвращает 0 для обоих случаев.

Кажется, это ошибка в .NET4 , а новые изменения вернулись в .NET4 Beta1 к предыдущей версии, такой же, как .NET 2.0 / 3.0 / 3.5 .

Что нового в BCL в .NET 4.0 CTP (блоги MSDN) :

Изменения безопасности строки в .NET 4

По умолчанию частичные совпадения перегрузок в System.String (StartsWith, EndsWith, IndexOf и LastIndexOf) по умолчанию были изменены как агностические (по порядку).

Это изменение повлияло на поведение метода String.IndexOf , изменив их для выполнения стандартного (байтового байта) сравнения по умолчанию, будет изменено на использование CultureInfo.InvariantCulture вместо CultureInfo.CurrentCulture .

UPDATE для .NET 4 Beta 1

Чтобы поддерживать высокую совместимость между .NET 4 и предыдущими версиями, мы решили вернуть это изменение. Поведение String по умолчанию для частичного совпадения перегрузок и методов ToUpper и ToLower для String и Char теперь ведет себя так же, как в .NET 2.0 / 3.0 / 3.5. Изменения в исходном поведении присутствуют в .NET 4 Beta 1.


Чтобы исправить это , измените метод сравнения строк на перегрузку, которая принимает перечисление System.StringComparison как параметр и задает либо Ordinal либо OrdinalIgnoreCase .

 // string contains 'unicode dash' \x2D string text = "\xAD\x2D"; // woks in .NET 2.0/3.0/3.5 and .NET 4 Beta 1 and later // but seems be buggy in .NET 4 because of 'culture-sensitive' comparison int index = text.IndexOf(text); // fixed version index = text.IndexOf(text, StringComparison.Ordinal); 

Из документации (мой акцент):

Этот метод выполняет поиск по словам ( чувствительный к регистру и чувствительный к культуре ) поиск с использованием текущей культуры.

То есть. некоторые отдельные кодовые точки будут считаться равными.

Что произойдет, если вы используете перегрузку, которая принимает значение StringComparison и передает StringComparison.Ordinal чтобы избежать культурных зависимостей?