web-dev-qa-db-ja.com

String.Contains()はString.IndexOf()より高速ですか?

約2000文字の文字列バッファーがあり、特定の文字列が含まれているかどうかを確認する必要があります。
すべてのwebrequestに対してASP.NET 2.0 webappでチェックを行います。

String.Containsメソッド のパフォーマンスが String.IndexOfメソッド よりも優れているかどうかは誰にもわかりますか?

    // 2000 characters in s1, search token in s2
    string s1 = "Many characters. The quick brown fox jumps over the lazy dog"; 
    string s2 = "fox";
    bool b;
    b = s1.Contains(s2);
    int i;
    i = s1.IndexOf(s2);

面白い事実

109
Kb.

ContainsIndexOfを呼び出します:

_public bool Contains(string value)
{
    return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
_

最終的にCLR実装を使用する_CompareInfo.IndexOf_を呼び出します。

CLRで文字列がどのように比較されるかを確認したい場合 これにより表示されますCaseInsensitiveCompHelperを探します)。

IndexOf(string)にはオプションがなく、Contains()は順序比較を使用します(eとéなどのスマート比較を実行するのではなく、バイトごとの比較)。

したがって、IndexOfはkernel32.dllのFindNLSStringを使用した文字列検索(リフレクターの力!)に直接進むため、IndexOfは(理論上)わずかに高速になります。

。NET 4.0用に更新-IndexOfは順序比較を使用しなくなったため、Containsはより高速になりました。以下のコメントを参照してください。

166
Chris S

おそらく、それはまったく問題ではないでしょう。 Coding Horrorに関するこの投稿を読んでください;): http://www.codinghorror.com/blog/archives/001218.html

20
Gonzalo Quero

Contains(s2)は、IndexOf(s2)よりも何倍も(私のコンピューターでは10倍)高速です http://davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx )。

Containsは、テストではIndexOf(s2、StringComparison.Ordinal)> = 0とまったく同じパフォーマンスを持ちますが、より短く、意図が明確になります。

11
ggf31416

私は実際のケースを実行しています(合成ベンチマークとは反対に)

 if("=,<=,=>,<>,<,>,!=,==,".IndexOf(tmps)>=0) {

versus

 if("=,<=,=>,<>,<,>,!=,==,".Contains(tmps)) {

これは私のシステムの重要な部分であり、131,953回実行されます(DotTraceに感謝します)。

しかし、衝撃的な驚き、結果は予想とは反対です

  • IndexOf 533ms。
  • 266msが含まれています。

:-/

ネットフレームワーク4.0(2012年2月13日更新)

7
magallanes

Reflectorを使用すると、ContainsがIndexOfを使用して実装されていることがわかります。これが実装です。

public bool Contains(string value)
{
   return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}

したがって、ContainsはIndexOfを直接呼び出すよりも少し遅い可能性がありますが、実際のパフォーマンスに重要な意味があるとは思いません。

6
Brian Rasmussen

コードを本当に最適化したい場合、最良のアプローチは常にベンチマークです。

.netフレームワークには優れたストップウォッチ実装があります- System.Diagnostics.Stopwatch

6
Andrew Harry

少し読んでみると、内部ではString.Containsメソッドが単にString.IndexOfを呼び出しているように見えます。違いは、String.Containsはブール値を返しますが、String.IndexOfは、部分文字列が見つからなかったことを表す(-1)の整数を返します。

100,000程度の反復で小さなテストを書くことをお勧めします。推測するなら、IndexOfの方が少し速いかもしれませんが、先ほど言ったように推測にすぎません。

Jeff Atwoodが his blog で文字列に関する優れた記事を公開しています。連結についての詳細ですが、それでも役に立つかもしれません。

3
Mike Roosa

これの更新として、テストを行い、入力文字列がかなり大きい場合、並列Regexが私が見つけた最速のC#メソッドです(複数のコアがある場合)

たとえば、一致の合計量を取得する-

needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 );

お役に立てれば!

3
gary

Jon Skeetからのこの最近の進出 のようなベンチマークライブラリを使用して、それを測定します。

警告エンプター

すべての(マイクロ)パフォーマンスの質問と同様に、これは使用しているソフトウェアのバージョン、検査されたデータの詳細、および呼び出しを取り巻くコードによって異なります。

すべての(マイクロ)パフォーマンスの質問と同様に、最初のステップは、簡単に保守可能な実行バージョンを取得することです。その後、推測する代わりに、ベンチマーク、プロファイリング、チューニングを測定されたボトルネックに適用できます。

2
David Schmitt