Различия в методах сравнения строк в С#
Сравнение строки в С# довольно просто. На самом деле есть несколько способов сделать это. Я перечислил некоторые в блоке ниже. Что мне интересно узнать о различиях между ними и о том, когда нужно использовать других? Следует ли избегать любой ценой? Больше ли я не перечислял?
string testString = "Test";
string anotherString = "Another";
if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}
(Примечание. Я ищу равенство в этом примере, не меньше или больше, но не стесняйтесь прокомментировать это)
Ответы
Ответ 1
Вот правила работы этих функций:
stringValue.CompareTo(otherStringValue):
- null перед строкой
- он использует CultureInfo.CurrentCulture.CompareInfo.Compare, что означает, что он будет использовать сравнение, зависящее от культуры. Это может означать, что ß будет сравниваться с SS в Германии или аналогичным
stringValue.Equals(otherStringValue):
- null не считается равным чему-либо
- если вы не укажете опцию StringComparison, она будет использовать то, что выглядит как прямая ординальная проверка равенства, т.е. ß не совпадает с SS, на любом языке или культуре
stringValue == otherStringValue:
- Это не то же самое, что stringValue.Equals().
- Оператор == вызывает статический метод Equals (string a, string b) (который в свою очередь переходит к внутреннему EqualsHelper для сравнения.
- Вызов .Equals() в нулевой строке получает исключение для ссылочной ссылки, а на == - нет.
Object.ReferenceEquals(stringValue, otherStringValue):
Просто проверяет, что ссылки одинаковы, т.е. это не только две строки с одним и тем же содержимым, вы сравниваете строковый объект с самим собой.
Обратите внимание, что с вышеперечисленными опциями, использующими вызовы методов, существуют перегрузки с большим количеством опций, чтобы указать, как сравнивать.
Мой совет, если вы просто хотите проверить равенство, состоит в том, чтобы решить, хотите ли вы использовать сравнение, зависящее от культуры, или нет, а затем использовать .CompareTo или .Equals, в зависимости от выбора.
Ответ 2
Из MSDN:
"Метод CompareTo был разработан в основном для использования при сортировке или операции с алфавитом. Он не должен использоваться, когда первичный Цель вызова метода состоит в том, чтобы определить, являются ли две строки эквивалент. Чтобы определить, эквивалентны две строки, вызовите метод Equals.
Они предлагают использовать .Equals
вместо .CompareTo
, если смотреть только на равенство. Я не уверен, существует ли разница между .Equals
и ==
для класса string
. Я иногда использую .Equals
или Object.ReferenceEquals
вместо ==
для своих собственных классов, если кто-то приходит позже и переопределяет оператор ==
для этого класса.
Ответ 3
Если вам когда-либо нравятся различия в методах BCL, Reflector является вашим другом: -)
Я следую этим рекомендациям:
Точное соответствие: EDIT: я всегда всегда использовал == оператор по принципу, что внутри Equals (string, string) оператор object == используется для сравнения ссылок на объекты, но он Кажется, strA.Equals(strB) по-прежнему на 1-11% быстрее, чем string.Equals(strA, strB), strA == strB и string.CompareOrdinal(strA, strB). Я тестировал цикл с помощью StopWatch как с внутренними, так и с неинтерминированными строковыми значениями с одинаковыми/разными строковыми строками и различными размерами (от 1 до 5 МБ).
strA.Equals(strB)
Человеко-читаемое соответствие (западные культуры, без учета регистра):
string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0
Человеко-читаемое совпадение (все другие культуры, нечувствительный случай/акцент/кана/etc, определенные CultureInfo):
string.Compare(strA, strB, myCultureInfo) == 0
Человеко-читаемое совпадение с пользовательскими правилами (Все остальные культуры):
CompareOptions compareOptions = CompareOptions.IgnoreCase
| CompareOptions.IgnoreWidth
| CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0
Ответ 4
Как Ed сказал, CompareTo используется для сортировки.
Однако существует разница между .Equals и ==.
== разрешает по существу следующий код:
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;
Ответ 5
Хорошее объяснение и практика проблем с сопоставлением строк можно найти в статье Новые рекомендации по использованию строк в Microsoft.NET 2.0, а также в Рекомендации по использованию строк в .NET Framework.
Каждый из упомянутых методов (и других) имеет особую цель. Ключевое различие между ними - это то, что StringComparison Enumeration, которое они используют по умолчанию. Существует несколько вариантов:
- CurrentCulture
- CurrentCultureIgnoreCase
- InvariantCulture
- InvariantCultureIgnoreCase
- Порядковый
- OrdinalIgnoreCase
Каждый из указанных выше типов сравнения использует различный прецедент:
- Порядковый
- Внутренние идентификаторы с учетом регистра
- Идентификаторы, чувствительные к регистру, в стандартах, таких как XML и HTTP
- Чувствительные к безопасности параметры безопасности
- OrdinalIgnoreCase
- Внутренние идентификаторы, нечувствительные к регистру
- Идентификаторы, нечувствительные к регистру, в стандартах, таких как XML и HTTP
- Пути файлов (в Microsoft Windows)
- Ключи/значения реестра
- Переменные среды
- Идентификаторы ресурсов (например, имена дескрипторов)
- Нечувствительные к безопасности параметры, не зависящие от регистра.
- InvariantCulture или InvariantCultureIgnoreCase
- Некоторые сохраняющиеся лингвистически релевантные данные
- Отображение лингвистических данных, требующих фиксированного порядка сортировки
- CurrentCulture или CurrentCultureIgnoreCase
- Данные, отображаемые пользователю
- Большинство пользовательских ввода
Обратите внимание, что StringComparison Enumeration, а также перегрузки для методов сравнения строк существует с .NET 2.0.
На самом деле существует безопасная реализация IComparable.CompareTo Method. Учет по умолчанию: CurrentCulture.
Использование:
Метод CompareTo был разработан в первую очередь для использования в сортировке или в алфавитном порядке.
Таким образом,
Реализация интерфейса IComparable обязательно будет использовать этот метод
Статический член String Class, который имеет много перегрузок. Учет по умолчанию: CurrentCulture.
По возможности вы должны вызвать перегрузку метода Compare, который включает параметр StringComparison.
Преодоление класса объекта и перегрузка для безопасности типов. Учет по умолчанию: ординал.
Обратите внимание:
Методы равенства класса String включают static Equals, статический оператор == и метод экземпляра Equals.
Существует также другой способ справиться со строковыми сравнениями, особенно для сортировки:
Вы можете использовать класс StringComparer, чтобы создать сравнение типов для сортировки элементов в общей коллекции. Классы, такие как Hashtable, Dictionary, SortedList и SortedList, используют класс StringComparer для сортировки.
Ответ 6
Не то, что производительность обычно имеет значение в 99% случаев, когда вам нужно это делать, но если вам нужно было сделать это в цикле несколько миллионов раз, я бы настоятельно предложил использовать .Equals или ==, потому что, как только находит символ, который не соответствует ему, выдает все это как ложное, но если вы используете CompareTo, ему придется выяснить, какой символ меньше другого, что приводит к немного худшему времени исполнения.
Если ваше приложение будет работать в разных странах, я бы рекомендовал вам взглянуть на последствия CultureInfo и, возможно, использовать .Equals. Поскольку я только действительно пишу приложения для США (и не волнует, если кто-то не работает должным образом), я всегда просто использую ==.
Ответ 7
В тех формах, которые вы указали здесь, между ними нет большой разницы. CompareTo
заканчивается вызовом метода CompareInfo
, который выполняет сравнение с использованием текущей культуры; Equals
вызывается оператором ==
.
Если вы рассматриваете перегрузки, тогда все становится по-другому. Compare
и ==
могут использовать текущую культуру для сравнения строки. Equals
и String.Compare
могут принимать аргумент перечисления StringComparison
, который позволяет вам определять нечувствительные к культуре или не учитывающие регистр. Только String.Compare
позволяет вам указать CultureInfo
и выполнять сравнения с использованием культуры, отличной от культуры по умолчанию.
Из-за своей универсальности я считаю, что String.Compare
больше, чем любой другой метод сравнения; он позволяет мне точно указать, что я хочу.
Ответ 8
Одна большая разница в примечании .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");
Ответ 9
Использование .Equals также намного легче читать.
Ответ 10
CompareTo
сравнивает строку со строковым объектом и возвращает значение int. Если значение равно 0, значит, строки равны.
string country = "southindia";
object ob1 = country.Clone();
Console.WriteLine( country.CompareTo(ob1));
string country = "southindia";
string cou = "insia";
int n = country.CompareTo(cou);
Console.WriteLine( n );
Ответ 11
с .Equals, вы также получаете опции StringComparison. очень удобно для игнорирования случая и других вещей.
btw, это будет оцениваться как false
string a = "myString";
string b = "myString";
return a==b
Так как == сравнивает значения a и b (которые являются указателями), это будет оценивать только true, если указатели указывают на один и тот же объект в памяти..Equals разыгрывает указатели и сравнивает значения, хранящиеся в указателях.
a.Equals(b) будет здесь.
и если вы измените b на:
b = "MYSTRING";
то a.Equals(b) ложно, но
a.Equals(b, StringComparison.OrdinalIgnoreCase)
будет истинным
a.CompareTo(b) вызывает строку CompareTo, которая сравнивает значения в указателях и возвращает < 0, если значение, сохраненное в a, меньше значения, сохраненного в b, возвращает 0, если a.Equals(b) истинно, и > 0 в противном случае. Тем не менее, это чувствительно к регистру, я думаю, что есть возможности для CompareTo игнорировать случай и т.д., Но у меня нет времени смотреть сейчас.
Как уже указывали другие, это будет сделано для сортировки. Сравнение для равенства таким образом приведет к ненужным накладным расходам.
Я уверен, что я оставляю вещи, но я думаю, что для этого достаточно информации, чтобы начать экспериментировать, если вам нужно больше деталей.