Подтвердить что ты не робот

Могут ли строки сравнения действительно отличаться в зависимости от культуры, когда строка гарантированно не изменится?

Я читаю зашифрованные учетные данные/строки подключения из файла конфигурации. Resharper говорит мне: "String.IndexOf(строка) здесь специфична для культуры" в этой строке:

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf(
        "host=") + "host=".Length, line.Length - "host=".Length);

... и поэтому хочет изменить его на:

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf("host=", System.StringComparison.Ordinal) + "host=".Length, line.Length -   "host=".Length);

Значение, которое я читаю, всегда будет "host =" независимо от того, где приложение может быть развернуто. Действительно ли разумно добавить этот бит System.StringComparison.Ordinal?

Что еще более важно, может ли это повредить что-нибудь (использовать его)?

4b9b3361

Ответ 1

Совершенно верно. В MSDN (http://msdn.microsoft.com/en-us/library/d93tkzah.aspx),

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

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

В этом конкретном случае у вас, вероятно, не будет проблемы, но введите i в строке поиска и запустите его в Турции, и это, вероятно, испортит вам день.

См. MSDN: http://msdn.microsoft.com/en-us/library/ms973919.aspx

Эти новые рекомендации и API существуют для устранения ошибочных предположений о поведении стандартных API-интерфейсов по умолчанию. Канонический пример ошибок, возникающих там, где нелингвистические строковые данные интерпретируется лингвистически как проблема "турецкого-I".

Для почти всех латинских алфавитов, в том числе английского языка, характер я (\ u0069) является строчной версией символа я (\ u0049). Эта правило обкатки быстро становится стандартным для тех, кто программирует в такой культуры. Однако на турецком ( "tr-TR" ) существует капитал "i с точкой", символ (\ u0130), который является капитальной версией я. Точно так же на турецком языке есть строчный "я без точки" или (\ u0131), который капитализирует на I. Это поведение происходит на азербайджанском культуры ( "az" ).

Поэтому предположения, обычно сделанные об капитализировании я или нижняя шкала Я недействительна среди всех культур. Если значение по умолчанию используются перегрузки для процедур сравнения строк, они будут при условии различия между культурами. Для нелингвистических данных, как в в следующем примере это может привести к нежелательным результатам:

    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

Из-за разницы в сравнении я результаты сравнения изменяются при изменении культуры потока. Это Выход:

Culture = English (United States)
(file == FILE) = True
Culture = Turkish (Turkey)
(file == FILE) = False

Вот пример без случая:

var s1 = "é"; //é as one character (ALT+0233)
var s2 = "é"; //'e', plus combining acute accent U+301 (two characters)

Console.WriteLine(s1.IndexOf(s2, StringComparison.Ordinal)); //-1
Console.WriteLine(s1.IndexOf(s2, StringComparison.InvariantCulture)); //0
Console.WriteLine(s1.IndexOf(s2, StringComparison.CurrentCulture)); //0

Ответ 2

CA1309: UseOrdinalStringComparison

Не использовать вред, чтобы не использовать его, но ", явно устанавливая параметр либо в StringComparison.Ordinal, либо в StringComparison.OrdinalIgnoreCase, ваш код часто получает скорость, повышает правильность, и становится более надежным.".


Что такое Ординал и почему это имеет значение для вашего случая?

Операция, использующая порядковые порядки сортировки, выполняет сравнение, основанное на на числовое значение (кодовая точка Unicode) каждого Char в строке. Обычное сравнение выполняется быстро, но нечувствительно к культуре. Когда вы используете порядковые порядки сортировки для сортировки строк, начинающихся с символов Юникода (U +), строка U + xxxx предшествует строке U + yyyy, если значение xxxx численно меньше yyyy.

И, как вы заявили... строковое значение, которое вы читаете, не чувствительно к культуре, поэтому имеет смысл использовать сравнение ординалов, а не сравнение слов. Просто помните, Ординал означает "это не чувствительность к культуре".

Ответ 3

Чтобы ответить на ваш конкретный вопрос: Нет, но инструмент статического анализа не сможет понять, что ваше входное значение никогда не будет содержать в нем информацию, относящуюся к локали.