Tuesday, December 28, 2010

Опасный IndexOf

Нашел интересный пост Wei Zhao про поиск и сравнение строк. Задача формулируется так: заменить все двойные пробелы на одиночные. Код очень простой:
            while (original.IndexOf("  ") != -1)
            {
                original = original.Replace("  ", " ");
            }

Для “обычных” строк все работает отлично.
А вот если строка original содержит символы пробелов в Unicode, то этот код зависает. Вот такая например:
  string original = new string(new char[]{ '\u0020', '\ufffd', '\u0020' });

Проблема заключается в том, что метод IndexOf ищет в текущей культуре, а символом \ufffd обозначаются ошибочные Unicode-символы. Другими словами, IndexOf будет возвращать всегда ноль:
  char[] test = { '\u0020', '\ufffd', '\u0020' };
  string testStr = new string(test);
  int i = testStr.IndexOf("  "); // вернет 0, а не -1

Более подробно можно прочитать по ссылке выше в блоге автора.
А правильный вариант кода такой:
     while (original.IndexOf("  ",  StringComparison.Ordinal) != -1)
     {
        original = original.Replace("  ", " ");
     }

Теперь код зависать не будет ни при каких обстоятельствах.

No comments: