RSS

Advent LINQ (7): Count

07 12月

Enumerable.Count()メソッドの特徴を考えてみる。ただ要素数を数えるだけなら、以下のような実装で良い筈だ。

public static class LinqExtensions
{
	public static int Count<T>(this IEnumerable<T> enumerable)
	{
		var count = 0;
		foreach (var value in enumerable)
		{
			count++;
		}
		return count;
	}
}

当たり前だが、これでは要素を全て列挙しなければ個数が分からない。例えば:

// 100000000個の値が入ったリスト
var values = Enumerable.Range(0, 100000000).ToList();

// 有意に時間がかかる
var count1 = LinqExtensions.Count(values);
// こちらは一瞬
var count2 = Enumerable.Count(values);

何故、Enumerable.Count()は速いのだろうか。それは、列挙子の実行時の型を見て最適化を行っているからだ。ICollectionインターフェイスを実装しているクラスであれば、Countプロパティを参照するだけで個数が識別出来る。この方法を利用するには、以下のようにキャストで判定する。

public static class LinqExtensions
{
	public static int Count<T>(this IEnumerable<T> enumerable)
	{
		// 列挙子がICollectionを実装していれば
		var collection = enumerable as ICollection;
		if (collection != null)
		{
			// 直接Countプロパティを参照する
			return collection.Count;
		}

		var count = 0;
		foreach (var value in enumerable)
		{
			count++;
		}
		return count;
	}
}

列挙子として配列を使用する場合、配列の長さを調べるにはLengthプロパティを参照する。しかし、配列は暗黙にICollectionインターフェイスを実装しているため、わざわざ配列かどうかを確認しなくても、上記コードがそのまま使える。

広告
 
コメントする

投稿者: : 2013/12/07 投稿先 .NET, LINQ

 

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。