Вопрос

Сравнить строку в C # довольно просто.На самом деле есть несколько способов сделать это.Я перечислил некоторые из них в блоке ниже.Что меня интересует, так это различия между ними и когда одно из них следует использовать поверх других?Следует ли избегать этого любой ценой?Есть ли еще что-то, чего я не перечислил?

string testString = "Test";
string anotherString = "Another";

if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(Примечание:Я ищу равенство в этом примере, не меньше или больше, чем, но не стесняйтесь комментировать и это)

Это было полезно?

Решение

Вот правила работы этих функций:

stringValue.CompareTo(otherStringValue)

  1. null появляется перед строкой
  2. он использует CultureInfo.CurrentCulture.CompareInfo.Compare, что означает, что он будет использовать сравнение, зависящее от культуры.Это может означать , что ß будет сравниваться равным SS в Германии или аналогичном

stringValue.Equals(otherStringValue)

  1. null не считается равным чему-либо
  2. если только вы не укажете StringComparison вариант, он будет использовать то, что выглядит как прямая проверка на порядковое равенство, т.е. ß это не то же самое, что SS, на любом языке или культуре

stringValue == otherStringValue

  1. Это не то же самое, что stringValue.Equals().
  2. Тот Самый == оператор вызывает статический Equals(string a, string b) метод (который, в свою очередь, переходит к внутреннему EqualsHelper чтобы провести сравнение.
  3. Зовущий .Equals() на null строка получает null ссылочное исключение, находясь на == не делает этого.

Object.ReferenceEquals(stringValue, otherStringValue)

Просто проверяет, что ссылки совпадают, т.е.это не просто две строки с одинаковым содержимым, вы сравниваете объект string сам с собой.


Обратите внимание, что с приведенными выше параметрами, которые используют вызовы методов, возникают перегрузки с большим количеством опций для указания способа сравнения.

Мой совет, если вы просто хотите проверить равенство, - это решить, хотите ли вы использовать сравнение, зависящее от культуры, или нет, а затем использовать .CompareTo или .Equals, в зависимости от выбора.

Другие советы

Из MSDN:

"Compareto метод был разработан в первую очередь для сортировки или по алфавиту операций.Его не следует использовать, когда основной целью вызова метода является определение того, являются ли две строки эквивалентными.Чтобы определить, эквивалентны ли две строки, вызовите метод Equals."

Они предлагают использовать .Equals вместо того, чтобы .CompareTo когда ищешь исключительно равенства.Я не уверен, есть ли разница между .Equals и == для string класс.Я буду иногда использовать .Equals или Object.ReferenceEquals вместо того, чтобы == для моих собственных занятий на случай, если кто-нибудь придет позже и переопределит == оператор для этого класса.

Если вам когда-нибудь будет интересно узнать о различиях в методах BCL, Отражатель это твой друг :-)

Я следую этим рекомендациям:

Точное совпадение: Редактировать:Ранее я всегда использовал оператор == исходя из принципа, что внутри Equals(строка, string) оператор object == используется для сравнения ссылок на объекты, но, похоже, strA.Equals(strB) по-прежнему на 1-11% быстрее, чем string.Равно(strA, strB), strA == strB и строка.Сравните порядковый номер (strA, strB).Я циклически тестировал с помощью секундомера как интернированные, так и не интернированные строковые значения, с одинаковой / разной длиной строки и различными размерами (от 1 Б до 5 МБ).

strA.Equals(strB)

Удобочитаемое соответствие (западные культуры, без учета регистра):

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

Удобочитаемое соответствие (для всех других культур, нечувствительный регистр / акцент / кана / и т.д., определенный CultureInfo):

string.Compare(strA, strB, myCultureInfo) == 0

Удобочитаемое соответствие пользовательским правилам (для всех других культур):

CompareOptions compareOptions = CompareOptions.IgnoreCase
                              | CompareOptions.IgnoreWidth
                              | CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

Как Эд сказано, compareTo используется для сортировки.

Однако существует разница между .Равно и ==.

== принимает решение по существу следующий код:

if(object.ReferenceEquals(left, null) && 
   object.ReferenceEquals(right, null))
    return true;
if(object.ReferenceEquals(left, null))
    return right.Equals(left);
return left.Equals(right);

Простая причина заключается в том, что следующее вызовет исключение:

string a = null;
string b = "foo";

bool equal = a.Equals(b);

И следующего не будет:

string a = null;
string b = "foo";

bool equal = a == b;

Хорошее объяснение и практические рекомендации по проблемам сравнения строк можно найти в этой статье Новые рекомендации по использованию строк в Microsoft .NET 2.0 а также в Рекомендации по использованию строк в .NET Framework.


Каждый из упомянутых методов (и других) имеет определенную цель.Ключевое различие между ними заключается в том, какого рода Перечисление сравнения строк они используются по умолчанию.Есть несколько вариантов:

  • Современная культура
  • Текущая культурная ситуация игнорируется
  • Инвариантная культура
  • Инвариантный случай игнорирования культуры
  • Порядковый номер
  • OrdinalIgnoreCase - Порядковый номер

Каждый из приведенных выше типов сравнения предназначен для разных вариантов использования:

  • Порядковый номер
    • Внутренние идентификаторы с учетом регистра
    • Идентификаторы, чувствительные к регистру, в таких стандартах, как XML и HTTP
    • Параметры безопасности, учитывающие регистр символов
  • OrdinalIgnoreCase - Порядковый номер
    • Внутренние идентификаторы без учета регистра
    • Идентификаторы без учета регистра в таких стандартах, как XML и HTTP
    • Пути к файлам (в Microsoft Windows)
    • Разделы/ значения реестра
    • Переменные среды
    • Идентификаторы ресурсов (например, имена дескрипторов)
    • Настройки безопасности без учета регистра
  • Инвариантная культура или InvariantCultureIgnoreCase
    • Некоторые сохранившиеся лингвистически значимые данные
    • Отображение лингвистических данных, требующих фиксированного порядка сортировки
  • Текущая культура или CurrentCultureIgnoreCase
    • Данные, отображаемые пользователю
    • Большая часть пользовательского ввода

Обратите внимание, что Перечисление сравнения строк а также перегрузки для методов сравнения строк, существующих начиная с .NET 2.0.


Строка.Метод сравнения (строка)

Является ли на самом деле типобезопасной реализация IComparable.Метод сравнения.Интерпретация по умолчанию:Современная культура.

Использование:

Метод compareTo был разработан в первую очередь для использования при сортировке или расположении в алфавитном порядке

Таким образом

Реализация интерфейса IComparable обязательно будет использовать этот метод

Строка.Метод сравнения

Статический член Класс String ( Строка) который имеет много перегрузок.Интерпретация по умолчанию:Современная культура.

Всякий раз, когда это возможно, вы должны вызывать перегрузку метода Compare, который включает параметр StringComparison.

Строка.Метод Equals

Переопределен из класса объекта и перегружен для обеспечения безопасности типов.Интерпретация по умолчанию:Порядковый номер.Обратите внимание на это:

Методы равенства класса String включают в себя статические Значения Равны, тот самый статический оператор ==, и тот метод экземпляра Равен.


Класс StringComparer

Существует также другой способ работы со сравнениями строк, особенно направленный на сортировку:

Вы можете использовать Класс StringComparer создать сравнение для конкретного типа для сортировки элементов в универсальной коллекции.Такие классы, как Hashtable, Dictionary, SortedList и SortedList, используют класс StringComparer для целей сортировки.

Не то чтобы производительность обычно имела значение в 99% случаев, когда вам нужно это сделать, но если бы вам пришлось делать это в цикле несколько миллионов раз, я бы настоятельно рекомендовал вам использовать.Равно или == потому что, как только он находит символ, который не соответствует, он выдает все это как false , но если вы используете compareTo, ему придется выяснить, какой символ меньше другого, что приведет к немного худшему времени выполнения.

Если ваше приложение будет запущено в разных странах, я бы порекомендовал вам взглянуть на значение CultureInfo и, возможно, использовать .Равно.Поскольку я действительно пишу приложения только для США (и меня не волнует, если у кого-то это не работает должным образом), я всегда просто использую == .

В формах, которые вы перечислили здесь, между ними нет большой разницы. CompareTo заканчивается тем, что вызывается CompareInfo метод, который выполняет сравнение с использованием текущей культуры; Equals вызывается == оператор.

Если вы принимаете во внимание перегрузки, то все становится по-другому. Compare и == можно использовать только текущий язык для сравнения строки. Equals и String.Compare может занять некоторое StringComparison аргумент перечисления, который позволяет вам указывать сравнения без учета культуры или регистра.Только String.Compare позволяет вам указать CultureInfo и выполняйте сравнения, используя культуру, отличную от культуры по умолчанию.

Из-за его универсальности я обнаружил, что использую String.Compare больше, чем любой другой метод сравнения;это позволяет мне точно указать, чего я хочу.

Следует отметить одно БОЛЬШОЕ отличие .Equals() выдаст исключение, если первая строка равна null, тогда как == этого не произойдет.

       string s = null;
        string a = "a";
        //Throws {"Object reference not set to an instance of an object."}
        if (s.Equals(a))
            Console.WriteLine("s is equal to a");
        //no Exception
        if(s==a)
            Console.WriteLine("s is equal to a");
  • s1.Сравнение (s2): НЕ используйте, если основной целью является определение того, эквивалентны ли две строки
  • s1 == s2: Нельзя игнорировать случай
  • s1.Равно(s2, сравнение строк): Выдает исключение NullReferenceException, если s1 равно null
  • Строка.Равно(s2, сравнение строк): В процессе элиминации этот статический метод заключается в ПОБЕДИТЕЛЬ (предполагая типичный вариант использования для определения того, эквивалентны ли две строки)!

Использование .Equals также намного проще для Читать.

с помощью .Equals вы также получаете параметры сравнения строк.очень удобно для игнорирования case и других вещей.

кстати, это будет равно false

string a = "myString";
string b = "myString";

return a==b

Поскольку == сравнивает значения a и b (которые являются указателями), это будет равно true только в том случае, если указатели указывают на один и тот же объект в памяти..Equals разыменовывает указатели и сравнивает значения, хранящиеся в указателях.a.Здесь значение Equals(b) было бы истинным.

и если вы измените b на:

b = "MYSTRING";

тогда a.Equals(b) равно false, но

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

было бы правдой

a.compareTo(b) вызывает функцию compareTo строки, которая сравнивает значения в указателях и возвращает <0, если значение, сохраненное в a, меньше значения, сохраненного в b, возвращает 0, если a.Equals(b) имеет значение true, и >0 в противном случае.Однако это чувствительно к регистру, я думаю, что у compareTo, возможно, есть варианты игнорировать регистр и тому подобное, но сейчас у меня нет времени смотреть.Как уже заявляли другие, это будет сделано для сортировки.Сравнение на предмет равенства таким образом привело бы к ненужным накладным расходам.

Я уверен, что я что-то упускаю из виду, но я думаю, что этой информации должно быть достаточно, чтобы начать экспериментировать, если вам нужно больше деталей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top