String.Containsメソッドは、内部的には次のようになります。
public bool Contains(string value)
{
return this.IndexOf(value, StringComparison.Ordinal) >= 0;
}
呼び出されるIndexOf
オーバーロードは次のようになります
public int IndexOf(string value, StringComparison comparisonType)
{
return this.IndexOf(value, 0, this.Length, comparisonType);
}
ここで、最終的なオーバーロードに対して別の呼び出しが行われCompareInfo.IndexOf
、署名付きで関連するメソッドが呼び出されます。
public int IndexOf(string value, int startIndex, int count, StringComparison comparisonType)
したがって、最終的なオーバーロードを呼び出すのが最も高速です (ただし、ほとんどの場合、マイクロ最適化と見なされる場合があります)。
明らかな何かが欠けている可能性がありますがContains
、中間呼び出しで他の作業が行われず、両方の段階で同じ情報が利用できることを考えると、メソッドが最終的なオーバーロードを直接呼び出さないのはなぜですか?
最終的なオーバーロードの署名が変更された場合、1 つの変更 (中間メソッドの変更) のみを行う必要があるという唯一の利点はありますか、それともそれ以上の設計がありますか?
コメントから編集 (速度の違いの説明については、更新 2 を参照してください)
どこかで間違いを犯した場合に得られるパフォーマンスの違いを明確にするために、このベンチマークString.Contains
を実行し (ジッター バイアスを避けるために 5 回ループしました)、この拡張メソッドを使用してメソッドと比較しました。
public static bool QuickContains(this string input, string value)
{
return input.IndexOf(value, 0, input.Length, StringComparison.OrdinalIgnoreCase) >= 0;
}
ループはこのように
for (int i = 0; i < 1000000; i++)
{
bool containsStringRegEx = testString.QuickContains("STRING");
}
sw.Stop();
Console.WriteLine("QuickContains: " + sw.ElapsedMilliseconds);
ベンチマーク テストでは、私のマシンQuickContains
よりも約 50% 高速に見えます。String.Contains
更新 2 (パフォーマンスの違いについて説明)
ベンチマークで不公平なことを発見しました。これは多くのことを説明しています。ベンチマーク自体は大文字と小文字を区別しない文字列を測定することでしたが、String.Contains
大文字と小文字を区別する検索しか実行できないため、ToUpper
メソッドが含まれていました。これは、最終的な出力に関してではなく、少なくともString.Contains
大文字と小文字を区別しない検索でのパフォーマンスを単に測定するという点で、結果をゆがめます。
さて、この拡張メソッドを使用すると
public static bool QuickContains(this string input, string value)
{
return input.IndexOf(value, 0, input.Length, StringComparison.Ordinal) >= 0;
}
StringComparison.Ordinal
2 オーバーロードIndexOf
呼び出しと removeで使用するToUpper
と、QuickContains
メソッドは実際には最も遅くなります。IndexOf
パフォーマンスの面でContains
はほぼ同等です。との間にToUpper
このような不一致があった理由の結果をゆがめたのは明らかに呼び出しでした。Contains
IndexOf
QuickContains
拡張メソッドが最も遅くなった理由がわかりません。(おそらく属性をContains
持っているという事実に関連してい[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
ますか?)。
4 オーバーロード メソッドが直接呼び出されない理由についてはまだ疑問が残りますが、(エイドリアンとデルナンがコメントで指摘したように) この決定によるパフォーマンスへの影響はないようです。