2009-05-13 4 views
17

Существует ряд способов сравнения строк. Есть ли выигрыш в производительности, делая один путь над другим?Сравнение производительности строк в C#

Я всегда выбирал для сравнения строк, как так:

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.

+0

возможно дубликат [Различия в строку сравнить методы в C#] (http://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c-sharp) – crowder

+0

Вы можете посмотреть http://rhale78.wordpress.com/2011/05/16/string-equality-and-performance-in-c/ – nawfal

ответ

22

Согласно Рефлектор

"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

string.Equals не выполняет проверку равенства ссылок в .NET 4.0, она перегружена в строке для сравнения фактических строк. (Я бы не удивился, если это всегда было правдой.) – Massif

+0

AFAIK, string.Equals также рассматривает культуру. –

+1

@ Ответ массива правильный. String.Equals() и == не сравнивают ссылки на объекты. Чтобы доказать это самому себе, вызовите Object.ReferenceEquals (x, y), где x - жесткокодированная строка, а y - в командной строке. – GreenRibbon

2

Недавно был довольно похожий вопрос о самом быстром способе обрезки строки, но в основном он сравнивал различные способы их сравнения.

Вы можете проверить тесты on this post.

+0

Я проверил сообщение. Спасибо, это было полезно. Он просто подтвердил, что string.length - это самый быстрый способ проверить, является ли строка пустой, если я не понял результаты теста. – Jagd

15

На мой взгляд, вы должны всегда использовать самый чистый способ, который использует ==!

Это можно понять напрямую: когда «Hello» равно «World», тогда сделайте что-нибудь.

if ("Hello" == "World") 
    // ... 

Внутренне String::Equals вызываются, которая существует в явном виде для этой цели - Сравнение два строк на равенство. (Это не имеет никакого отношения к указателям и ссылкам и т. Д.)

Это не сразу понятно - зачем сравнивать с нолем?

if ("Hello".CompareTo("World") == 0) 

.CompareTo не предназначен только для проверки равенства (== Вы для этого) - Он сравнивает две строки. Вы используете .CompareTo для сортировки, чтобы определить, что одна строка «больше», чем другая. Вы можете получить для равенства, потому что он дает нуль для равных строк, но это не то, для чего оно предназначено.

Следовательно, существуют различные методы и интерфейсы для проверки равенства (IEquatable, оператор ==) и сравнения (IComparable)

Linq не ведут себя иначе, чем регулярный C# здесь.

+2

OP не спрашивал о том, что является самым ясным способом написать сравнение строк. То, что ясно для одного, может быть непонятным для другого. –

8

Прочитать Jeff's The Best Code is No Code at All. foo.CompareTo(bar) == 0: ужасный визуальный беспорядок. Занимает много места и не передает никакого интересного смысла. Фактически, он подчеркивает много неуместного материала, который отвлекает внимание от реальной проблемы.

Если нет четкой причины для использования этого более длинного варианта, не делайте этого.

Что касается производительности: это просто не имеет значения для этого простого случая. Если оператор равенства == должен действительно выполнять хуже, чем CompareTo, не стесняйтесь сообщать об ошибке в Microsoft. Этого не должно быть.

1

Если оператор равенства фактически выполнен хуже, чем CompareTo - не будет ли Microsoft выполнять реализацию оператора равенства равенства CompareTo?

Просто используйте оператор равенства для проверки равенства.

0

Я обычно использую String.Compare с перегрузкой, которая принимает параметр StringComparison, потому что тогда я могу быть абсолютно явным, будет ли сравнение чувствительным к регистру и культуре. Для этого требуется .NET 2.0 или новее.

Самый быстрый из них - это StringComparison.Ordinal (или StringComparison.OrdinalIgnoreCase, если он нечувствителен к регистру) для сопоставлений, которые не чувствительны к культуре.

Проблема с использованием == заключается в том, что неясно, что автор рассмотрел чувствительность к случаю и культуре.

Существует хорошая статья MSDN по теме here.

+0

== is Equals() и Equals() делает CaseSens. & CultureInsens. поиск (самый быстрый, легко запоминающийся). Вызов Equals (var, StringComparison.OrdinalCaseInsensetive) медленнее, чем вызов Equals(), поэтому в случае сравнения миллионов строк лучше использовать простые Equals() вместо версий == и 2arg. – Grigory

0

Чтобы наилучшим образом сравнить string «S в C# является использование a.Equals(b) где и б являются строки.Это лучший способ сравнить строку, потому что она сравнивает значения объектов a и b и не зависит от ссылки объектов.

Если вы собираетесь использовать «==» символ, результат будет равен, если оба объекта имеют одинаковые ссылки, но вы будете иметь проблемы, когда они имеют различные ссылки и имеют одинаковое значение.

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

+0

Это уже понятно из других ответов, но для того, чтобы убедиться: это неправильно. строка перегружает оператор '==' –

4

Ну MSDN утверждает, вы Шоул использовать функцию СРАВНЕНИЕ в соответствии с задачей, которую необходимо выполнить:

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

Так что, если его не о сортировке и значение Retrun не важно, я бы сказал один следует использовать:

first.Equals(second) или если сравнение является культура конкретных, например, в языках, как на немецком языке:

String.Equals(first, second, StringComparison.CurrentCulture)

Взгляните через эти ссылки:

How to: Compare Strings (C# Programming Guide)

String.CompareTo Method (Object)

0

Here является наиболее полным и полезным MSDN руководство для сравнения строк я нашел.

Используйте сравнения с StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase для лучшей производительности.

Смежные вопросы