Случайное сравнение строк в C # - PullRequest
13 голосов
/ 02 февраля 2009

Допустим, у меня есть две строки: а и б. Чтобы сравнить, имеют ли a и be одинаковые значения, когда регистр игнорируется, я всегда использовал:

// (Assume a and b have been verified not to be null)

if (a.ToLower() == b.ToLower())

Однако, используя Reflector, я видел это несколько раз в .NET Framework:

// (arg three is ignoreCase)

if (string.Compare(a, b, true) == 0)

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

Есть ли причина, по которой Compare() вместо ToLower()? Что-то о другом CultureInfo? Я чешу голову.

Ответы [ 6 ]

23 голосов
/ 02 февраля 2009

Главное, что вас должно беспокоить, это не производительность, а правильность, и с этой точки зрения метод, который вы вероятно хотите использовать для сравнения без учета регистра, является либо:

string.Compare(a, b, StringComparison.OrdinalIgnoreCase) == 0;

или

a.Equals(b, StringComparison.OrdinalIgnoreCase)

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

Ordinal или OrdinalIgnoreCase - безопасная ставка, если вы не знаете, что хотите использовать другой метод сравнения; Чтобы получить информацию, необходимую для принятия решения , прочтите эту статью на MSDN .

6 голосов
/ 02 февраля 2009

В разделе «Примечания» статьи MSDN следует объяснить некоторые вещи. По сути, причина заключается в совместимости в разных культурах.

3 голосов
/ 02 февраля 2009

При сравнении строк вы должны всегда использовать явный член StringComparison. Функции String несколько противоречивы в том, как они выбирают сравнение строк. Единственный способ гарантировать используемое сравнение - это а) запомнить их все (включая вас и всех в вашей команде) или б) использовать явное сравнение для каждой функции.

Гораздо лучше быть откровенным и не полагаться на то, что групповые знания совершенны. Ваши товарищи по команде будут вам благодарны.

Пример:

if ( StringComparison.OrdinalIgnoreCase.Equals(a,b) )

Использование ToLower для сравнения имеет 2 проблемы, которые я могу придумать, вне головы

  1. Распределяет память. Функции сравнения не должны выделять память, если они не обязаны это делать.
  2. Струны можно опускать несколькими способами. Наиболее заметный Ordinal или Culture Sensitive ниже. Каким образом .ToLower () работает? Лично я не знаю. Гораздо лучше передать явную культуру, чем полагаться на значение по умолчанию.
0 голосов
/ 05 марта 2009

Не могли бы вы опубликовать свой тест, показывающий, что вызов ToLower () выполняется быстрее, чем сравнение без учета регистра? Мои тесты показывают обратное, чтобы быть правдой! Несмотря на это, другие постеры о правильности высказываются.

0 голосов
/ 02 февраля 2009

Еще одна статья в MSDN, в которой приведены некоторые недостатки и недостатки, а также рекомендации по использованию метода сравнения в различных случаях: Новые рекомендации по использованию строк в Microsoft .NET 2.0

0 голосов
/ 02 февраля 2009

ToLower () не является функцией сравнения, она переводит строку в нижний регистр. Когда оператор == используется в объектах String в C #, он оптимизируется компилятором. По сути, оба зависят от System.String.Equals, как видно в Reflector.

...