4

C# で初めての Web サイトを作成しています。

IntelliSense で拡張メソッドが重複していることに気付きました。さらに調べたところ、次の 2 つでした。

public static void ThrowNullOrEmpty<T>(this IEnumerable<T> obj, string param)
{
}

public static void ThrowNullOrEmpty(this string obj, string param)
{
}

string もできるようIEnumerable<char>です。

コンパイルの基礎から文字列バリアントを削除できますが、パフォーマンスの問題やその他の注意事項はありますか?

アップデート

100 万回以上の反復テストを行いました。

public bool IsNullOrEmpty1(string @this)
{
    return String.IsNullOrEmpty(@this);
}

public bool IsNullOrEmpty2<T>(IEnumerable<T> @this)
{
    return @this == null || !@this.Any();
}

IsNullOrEmpty1 は、開発マシン IsNullOrEmpty2 (125 - 250ms) で 12 ミリ秒のクロックを記録したため、10 - 20 倍遅くなりました。

現実の世界では、1 か月あたり 3,000 万回の反復という非常に高い数値を取りました。これは、1 分あたり 1,388 回 (1 日 12 時間) に相当します。結果は両方とも 1 ミリ秒未満でした。

したがって、 IsNullOrEmpty1 を削除することは最善の方法ではありませんが、サイト キラーでもありません。

4

2 に答える 2

3

おそらくこれらのメソッドの実装に依存します.文字列バージョンはパフォーマンスのために最適化できますが、文字列バージョンはIEnumerable<T>より一般的である必要があります. ジェネリック メソッドの呼び出しにはオーバーヘッドがなく、コンパイル時に正しいジェネリック パラメーターに解決されます。

文字列バージョンは次のように実装でき、オーバーヘッドはほとんどありません (基本的に 2 つの比較を行う必要があります)。

if (String.IsNullOrEmpty(value))  

一方IEnumerable<T>、おそらく次のようなものを実装する必要があります。

if (value == null || !value.Any())

ここで重要なのはAny、GetEnumerator メソッドを呼び出して列挙子を返す呼び出しです。(簡単にするために、ここでは、フレームワークが一部の型に対して内部的に使用する可能性があるパフォーマンスの最適化を無視します)。これは、実装が実際に新しいオブジェクトを作成し、後でガベージ コレクションが必要になることを意味します。どちらも、stringバージョンで言及されている 2 つの比較を行うよりも多くのクロック サイクルを必要とします。

実際には、これらのメソッドが非常に頻繁に呼び出されない限り、パフォーマンスに大きな違いがあるとは思えません。

ところで、これが機能する理由stringは、IEnumerable<char>.

于 2012-09-16T10:39:17.813 に答える
0

stringは封印されたクラスであるためstring、仮想関数ポインターにアクセスせずにクラス内のメソッドを直接呼び出すことができます。理論的には、Iを渡すよりも高速ですEnumerable<char>stringただし、実際には、メソッド内でメソッドを呼び出す回数によって異なります。

于 2012-09-16T10:48:06.203 に答える