web-dev-qa-db-ja.com

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クエリでそのような文字列比較を行う人はほとんどいません。

20
Jagd

リフレクターによると

"Hello" == "World"

と同じです

String.Equals("Hello", "World");

これは基本的に、それらが同じ参照オブジェクトであるかどうか、どちらかがnullであるかどうかを判断し、一方がnullでもう一方がそうでない場合は自動的にfalseになり、安全でないループで各文字を比較します。したがって、文化的なルールはまったく気にしません。これは通常、大したことではありません。

そして

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

と同じです

CultureInfo.CurrentCulture.CompareInfo.Compare("Hello", "World", CompareOptions.None);

これは、機能に関しては基本的に反対です。カルチャ、エンコーディング、およびその他すべての文字列をコンテキストに含めて考慮します。

したがって、String.CompareToは等式演算子よりも数桁遅いと想像します。

lINQに関しては、どちらも同じSQLを生成するため、LINQ-to-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を使用しているだけの場合は、上記のルールが適用されます。

25
Nick Berardi

私の意見では、常に==を使用する最も明確な方法を使用する必要があります。

これは直接理解できます。「Hello」が「World」と等しい場合は、何かを実行します。

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

内部的には、この目的のために明示的に存在するString::Equalsが呼び出されます-2つの文字列が等しいかどうかを比較します。 (これはポインタや参照などとは何の関係もありません)

これはすぐにはわかりません-なぜゼロと比較するのですか?

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

.CompareToは、同等性をチェックするためだけに設計されたものではありません(これには==があります)-2つの文字列を比較します。ソートで.CompareToを使用して、ある文字列が別の文字列より「大きい」かどうかを判断します。あなたcan等しい文字列に対してゼロを生成するため、等しいかどうかをチェックしますが、それはそれが概念化されているものではありません。

したがって、同等性をチェックし(IEquatable、演算子==)、比較する(IComparable)ためのさまざまなメソッドとインターフェイスがあります。

ここでは、Linqは通常のC#と同じように動作します。

16
Dario

ジェフの 最高のコードはコードがまったくない を読んでください。 foo.CompareTo(bar) == 0:ひどい視覚的混乱。多くのスペースを占有し、興味深い意味を伝えません。実際、それは実際の問題から注意をそらす多くの無関係なものを強調しています。

この長いバリアントを使用する明確な理由がない場合は、使用しないでください。

パフォーマンスに関しては、この単純なケースでは問題ではありません。等式演算子==は実際にはCompareToよりもパフォーマンスが悪いはずです。Microsoftにバグレポートを提出してください。これは起こってはなりません。

8
Konrad Rudolph

さて、MSDNは、実行する必要のあるタスクに応じて比較機能を使用する必要があると述べています。

CompareToメソッドは、主に並べ替えまたはアルファベット順の操作で使用するために設計されました。メソッド呼び出しの主な目的が2つの文字列が同等であるかどうかを判断することである場合は、使用しないでください。 2つの文字列が同等であるかどうかを判断するには、Equalsメソッドを呼び出します。

したがって、ソートに関するものではなく、retrun値が重要でない場合は、次を使用する必要があります。

first.Equals(second)または、比較が文化固有の場合、たとえばドイツ語などの言語の場合:

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

これらのリンクを見てください:

方法:文字列の比較(C#プログラミングガイド)

String.CompareToメソッド(オブジェクト)

4
CloudyMarble

最近、文字列をトリミングする最速の方法に関して非常によく似た質問がありましたが、基本的には、それらを比較するさまざまな方法のベンチマークでした。

あなたはベンチマークをチェックすることができます この投稿で

2
womp

素敵な記事があります 。NETでの同等性の値の比較:アイデンティティと同等性 これは文字列の比較よりも少し一般的ですが、それでも非常に興味深いものです。

1
tanascius

等式演算子のパフォーマンスが実際にCompareToよりも悪い場合、Microsoftは等式演算子の実装をCompareToと呼びませんか?

等式演算子を使用して、等式をテストするだけです。

1
Amy B

私は通常、String.CompareをStringComparisonパラメーターを受け取るオーバーロードと一緒に使用します。これは、比較が大文字と小文字およびカルチャに依存するかどうかを完全に明示できるためです。これには.NET2.0以降が必要です。

カルチャに依存しない比較の場合、最速はStringComparison.Ordinal(または大文字と小文字を区別しない場合はStringComparison.OrdinalIgnoreCase)です。

==を使用する際の問題は、作成者がケースと文化の感度を考慮したかどうかが明確でないことです。

この件に関する良いMSDNの記事があります ここ

0
Joe

ここ は、私が見つけた文字列比較のための最も完全で役立つMSDNガイドです。

StringComparison.OrdinalまたはStringComparison.OrdinalIgnoreCaseとの比較を使用して、パフォーマンスを向上させます。

0
Ognyan Dimitrov

C#でstringを比較する最良の方法は、a.Equals(b)を使用することです。ここでabは文字列です。これは、オブジェクトの値を比較するため、文字列を比較するための最良の方法ですaおよびbであり、オブジェクトの参照に依存しません。

使用する場合"== "シンボル、両方のオブジェクトが同じ参照を持っている場合、結果は等しくなりますが、それらが異なる参照を持ち、同じ値を持っている場合、問題が発生します。

compareToメソッドは、他の文字列が他の文字列の前、後、または同じ位置に表示され、負の値、正の値を返すかどうかをテストする場合に使用するのに最適な方法です。またはそれぞれゼロ値。パラメータがnullの場合も、正の値を返します。

0
Roy Marco Aruta