Эффективность сравнения строк в С#
Существует несколько способов сравнения строк. Есть ли выигрыш в производительности, делая один способ над другим?
Я всегда предпочитал сравнивать строки следующим образом:
string name = "Bob Wazowski";
if (name.CompareTo("Jill Yearsley") == 0) {
// whatever...
}
Но я нахожу, что мало кто это делает, и, если угодно, я вижу, что больше людей просто делают прямое сравнение, насколько мне известно, это самый худший способ сравнить строки. Я не прав?
Кроме того, имеет ли значение то, как сравнивать строки в запросах LINQ? Например, мне нравится делать следующее:
var results = from names in ctx.Names
where names.FirstName.CompareTo("Bob Wazowski") == 0
select names;
Но опять же, я вижу, что немногие люди делают подобные строки в своих запросах LINQ.
Ответы
Ответ 1
Согласно Reflector
"Hello" == "World"
совпадает с
String.Equals("Hello", "World");
который в основном определяет, являются ли они одним и тем же ссылочным объектом, если любой из них является нулевым, что было бы автоматически ложным, если бы оно было нулевым, а другое отсутствовало, а затем сравнивало каждый символ в небезопасном цикле. Так что он вообще не заботится о культурных правилах, что обычно не имеет большого значения.
и
"Hello".CompareTo("World") == 0
совпадает с
CultureInfo.CurrentCulture.CompareInfo.Compare("Hello", "World", CompareOptions.None);
Это в основном противоположность функциональности. Он учитывает культуру, кодирование и все остальное с помощью строки в контексте.
Итак, я бы предположил, что String.CompareTo на пару порядков медленнее, чем оператор равенства.
так как для вашего LINQ не имеет значения, используете ли вы LINQ-to-SQL, потому что оба будут генерировать один и тот же SQL
var results = from names in ctx.Names
where names.FirstName.CompareTo("Bob Wazowski") == 0
select names;
о
SELECT [name fields]
FROM [Names] AS [t0]
WHERE [t0].FirstName = @p0
так что вы действительно ничего не получаете для LINQ-to-SQL, кроме более трудного для чтения кода и, возможно, большего разбора выражений. Если вы используете LINQ для стандартного массива, тогда применяются правила, изложенные выше.
Ответ 2
По-моему, вы всегда должны использовать самый ясный способ, который использует ==
!
Это можно понять напрямую: когда "Hello" равно "World", сделайте что-то.
if ("Hello" == "World")
// ...
Внутри вызывается String::Equals
, который существует явно для этой цели. Сравнение двух строк для равенства. (Это не имеет никакого отношения к указателям и ссылкам и т.д.)
Это не сразу понятно - зачем сравнивать с нолем?
if ("Hello".CompareTo("World") == 0)
.CompareTo не предназначен только для проверки равенства (у вас есть == для этого). Он сравнивает две строки. Вы используете .CompareTo для сортировки, чтобы определить, что одна строка "больше", чем другая. Вы можете проверить равенство, потому что оно равно нулю для равных строк, но это не то, для чего оно было понято.
Следовательно, существуют различные методы и интерфейсы для проверки равенства (IEquatable, operator ==) и сравнения (IComparable)
Linq не ведет себя иначе, чем обычный С#.
Ответ 3
Прочтите Jeffs Лучший код не содержит кода вообще. foo.CompareTo(bar) == 0
: ужасный визуальный беспорядок. Занимает много места и не передает никакого интересного смысла. Фактически, он подчеркивает много неулокального материала, который отвлекает внимание от реальной проблемы.
Если нет четкой причины использования этого более длинного варианта, не.
Что касается производительности: это просто не имеет значения для этого простого случая. Если оператор равенства ==
должен действительно работать хуже, чем CompareTo
, не стесняйтесь сообщать об ошибке в Microsoft. Этого не должно быть.
Ответ 4
Ну, MSDN заявляет, что вы используете функцию сравнения в соответствии с задачей, которую вам нужно выполнить:
Метод CompareTo был разработан в первую очередь для использования в сортировке или в алфавитном порядке. Его не следует использовать, когда основной целью вызова метода является определение того, являются ли две строки эквивалентными. Чтобы определить, эквивалентны две строки, вызовите метод Equals.
Так что если его не сортировка и значение возврата не важны, я бы сказал, что нужно использовать:
first.Equals(second)
или если сравнение является специфическим для культуры, например, на таких языках, как на немецком языке:
String.Equals(first, second, StringComparison.CurrentCulture)
Посмотрите эти ссылки:
Практическое руководство. Сравнение строк (Руководство по программированию на С#)
Метод String.CompareTo(объект)
Ответ 5
Недавно был довольно похожий вопрос о самом быстром способе обрезания строки, но в основном он сравнивал различные способы их сравнения.
Вы можете проверить этапы в этом сообщении.
Ответ 6
Есть хорошая статья Сравнение значений для Equality в .NET: Identity and Equivalence, которая является немного более общей, чем сравнение строк, но, тем не менее, очень интересно.
Ответ 7
Если оператор равенства фактически выполнял хуже, чем CompareTo
, не сделал бы Microsoft выполнение реализации оператора равенства равенства CompareTo
?
Просто используйте оператор равенства для проверки равенства.
Ответ 8
Обычно я использую String.Compare с перегрузкой, которая принимает параметр StringComparison, потому что тогда я могу быть абсолютно явным, будет ли сравнение чувствительным к регистру и культуре. Для этого требуется .NET 2.0 или новее.
Самый быстрый - это StringComparison.Ordinal(или StringComparison.OrdinalIgnoreCase, если он нечувствителен к регистру) для сравнений, которые не чувствительны к культуре.
Проблема с использованием == заключается в том, что неясно, что автор рассмотрел чувствительность к случаю и культуре.
Там хорошая статья MSDN по этому вопросу здесь.
Ответ 9
Лучшим способом сравнения string
в С# является использование a.Equals(b)
, где a и b являются строками. Это лучший способ сравнить строку, поскольку она сравнивает значения объектов a и b и не зависит от ссылки на объекты.
Если вы собираетесь использовать символ "==
" , результат будет равен, если оба объекта имеют одну и ту же ссылку, но у вас будет проблема, если у них есть разные ссылки, и то же значение.
Метод compareTo
- лучший способ использовать, если вы проверяете, предшествует ли другая строка, следуя или появляется в том же положении другой строки, в котором оно будет возвращать отрицательное значение, положительное значение или нулевое значение соответственно. Он также вернет положительное значение, если параметр null
Ответ 10
Здесь - наиболее полное и полезное руководство MSDN для сравнения строк, которое я нашел.
Используйте сравнения со строковым соглашением. StringComparison.OrdinalIgnoreCase для лучшей производительности.