string.IsNullOrEmpty の配列版。あると便利。
※ null で例外が欲しい場合は、Enumerable.Any() がある。
ちなみに、string にも使用可能。(IEnumerable<char> なので)
ICollection<T> を実装しているクラス(List<T> や配列)は、Count の参照だけで済むため、早くなる。
(A) 引数が IEnumerable<T>
(B) 引数が IEnumerable<T> と ICollection<T> (おまけのパターン)
(C) 引数が IEnumerable<T> で、内部で ICollection<T> にキャスト試行(下記実装)
[測定コード]
[結果]
※コマンドプロンプトで実施(csc /optimize)
※10回の算術平均、単位は[s]
結果は、(B) > (A) > (C) となった。(左の方が高性能)
(C) が遅い原因はキャスト試行処理なので、つまり、パフォーマンス目的でキャスト処理を追加する際は要注意。
(B) のようにキャストをオーバーロードに任せられるパターンは、そうすべき。(メソッドが増えるデメリットはあるけど)
Intel(R) Celeron(R) CPU G530 @ 2.40GHz/DDR3 8GB(4GB x 2)
※ null で例外が欲しい場合は、Enumerable.Any() がある。
// generic 版
public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
{
if( source == null ) return true;
using( var e = source.GetEnumerator() ) return !e.MoveNext();
}
// 非 generic 版(普通は不要)
public static bool IsNullOrEmpty(this IEnumerable source)
{
return source == null || !source.GetEnumerator().MoveNext();
}
ちなみに、string にも使用可能。(IEnumerable<char> なので)
おまけ
パフォーマンスを上げたい場合は、下記メソッドを別途定義する。ICollection<T> を実装しているクラス(List<T> や配列)は、Count の参照だけで済むため、早くなる。
public static bool IsNullOrEmpty<T>(this ICollection<T> source)
{
return source == null || source.Count == 0;
}
おまけのおまけ
下記パターンでパフォーマンスを測定してみた。(A) 引数が IEnumerable<T>
(B) 引数が IEnumerable<T> と ICollection<T> (おまけのパターン)
(C) 引数が IEnumerable<T> で、内部で ICollection<T> にキャスト試行(下記実装)
public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
{
if( source == null ) return true;
var c = source as ICollection<T>;
if( c != null ) return c.Count == 0;
using( var e = source.GetEnumerator() ) return !e.MoveNext();
}
[測定コード]
static void Main(string[] args)
{
var testdata = new[]{
new int[]{},
new[]{1}
};
var loopCount = int.Parse(args[0]);
var result = false;
var sw = new Stopwatch();
sw.Start();
for( var i=0; i<loopCount; i++ ){
result = testdata[i % testdata.Length].IsNullOrEmpty();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
Console.WriteLine(result);
}
[結果]
loopCount | (A) | (B) | (C) |
---|---|---|---|
10000 | 0.0012318 | 0.0004056 | 0.0056082 |
100000 | 0.0038177 | 0.0010864 | 0.0455488 |
※10回の算術平均、単位は[s]
結果は、(B) > (A) > (C) となった。(左の方が高性能)
(C) が遅い原因はキャスト試行処理なので、つまり、パフォーマンス目的でキャスト処理を追加する際は要注意。
(B) のようにキャストをオーバーロードに任せられるパターンは、そうすべき。(メソッドが増えるデメリットはあるけど)
検証環境
Windows 7 64bit/Visual Studio 2010 SP1/.NET 4.0Intel(R) Celeron(R) CPU G530 @ 2.40GHz/DDR3 8GB(4GB x 2)
0 件のコメント:
コメントを投稿