0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C#】ListやDictionaryに格納されているデータ数を取得する方法

Last updated at Posted at 2022-02-06

結論

Countを使います。

Listに格納されているデータ数を取得
List<string> dataList = new List<string>();
var dataCount = dataList.Count;
//取得結果はint型で0が取得されます。
Dictionaryに格納されているデータ数を取得
Dictionary<int, string> dataDictionary = new Dictionary<int, string>();
var dataCount = dataDictionary.Count;
//取得結果はint型で0が取得されます。

解説

実は格納されているデータ数を取得する方法は2種類あります。
CountCount()です。
何が違うのか簡単に説明しますが、基本的にはCountを使ってください。
まず、Countはプロパティです。そしてCount()はメソッド(関数)です。
Countは参照するListの内容が変化した瞬間に変化します。例えばListにデータをAddした場合です。(Removeなどでデータを削除した場合も同様です。)

Countでデータ数を取得する場合
List<string> dataList = new List<string>();

//Listに文字列を追加する。
dataList.Add("Apex楽しい...");
//↑この時点でCountプロパティの内容が1に変わっています。

var dataCount = dataList.Count;
//↑データ数は1らしいで^ ^

Count()はデータ数をしようとした瞬間に改めてデータを確認します。

Count()でデータ数を取得する場合
List<string> dataList = new List<string>();

var dataCount = dataList.Count();
//↑じゃあ、今からデータ数を数えるからちょっとまってな^ ^
//↑データ数は0やったで^ ^

処理速度の差

実際にどれくらい処理速度が違うのか検証してみました。
結果は

種類 実行時間[ms] 格納データ数
Count 0 0
Count() 0 0
Count 0 10000
Count() 0 10000
Count 0 2146435071
Count() 0 2146435071

...あ、あれ?
処理速度変わんないの...?
じゃあ、マイクロ秒表示するように変更して...

種類 実行時間[us] 格納データ数
Count 10 0
Count() 30 0
Count 6 10000
Count() 29 10000
Count 38 2146435071
Count() 21 2146435071

...(·ε·`)あんまり変わらないっぽい。

ただ、インテリセンス君がCountを使え!!って言っているのでCountでいいんだと思います。
image.png

追記(2022/02/07)

コメントでICollectionインタフェースを実装している型(List型やDictionary型)の場合、Count()のメソッド内でCountプロパティを参照しているとご指摘いただいたので改めて調べ直しました。ご指摘頂きありがとうございますm(_ _)m

Count()メソッドの内部実装

Count()メソッドの内部実装を調べた結果、下記のように実装されていました。

参考:Reference Source

Enumrable.cs(Count()メソッド)
public static int Count<TSource>(this IEnumerable<TSource> source) {
            if (source == null) throw Error.ArgumentNull("source");
            ICollection<TSource> collectionoft = source as ICollection<TSource>;
            if (collectionoft != null) return collectionoft.Count;
            ICollection collection = source as ICollection;
            if (collection != null) return collection.Count;
            int count = 0;
            using (IEnumerator<TSource> e = source.GetEnumerator()) {
                checked {
                    while (e.MoveNext()) count++;
                }
            }
            return count;
        }

ご指摘頂いた通り、ICollectionインタフェース型に変換できる場合は
Countプロパティを参照しているようですね!

実行速度(ICollection VS IEnumerable)

改めてICollectionインタフェースを実装している場合と
実装していない(IEnumerableインタフェース)場合の実行速度を検証しました。
結果は

種類 実行時間[us] 格納データ数
ICollection 19 0
IEnumerable 390 0
ICollection 22 10000
IEnumerable 437 10000
ICollection 130 2146435071
IEnumerable 5495402 2146435071

おぉ...(´ε` )
格納データ数が多いと実行時間が全然変わってきますね...!
ということは...

こんなソースコード書いたらソフトがタヒりますね...
List<int> dataList = new();

//変数内に2146435071個データを格納する。
dataList.AddRange(Enumerable.Repeat(0, 2146435071));

IEnumerable<int> data = dataList.Where(x => x == 0).AsEnumerable();

//100万回格納データ数を使うぞ!
for (int i = 0; i < 1000000; i++)
{
    var dataCount2 = data.Count();
}

検証結果から上記のソースコードを実行完了するには
5.495402[秒] * 1000000 = 5,495,402[秒] = 1,526.5[時間] = 63[日]
かかるということになります😰
Count()メソッドを使用しないと行けない場合は注意しないといけませんね...!対処法としてはこのようにすればいいんだと思います。

これならタヒらない
List<int> dataList = new();

//変数内に2146435071個データを格納する。
dataList.AddRange(Enumerable.Repeat(0, 2146435071));

IEnumerable<int> data = dataList.Where(x => x == 0).AsEnumerable();

//Forの外で格納データ数を数えるぞ!
var dataCount = data.Count();

//100万回格納データ数を使うぞ!
for (int i = 0; i < 1000000; i++)
{
    var count = dataCount;
}

今回のご指摘で一つ勉強になりました!

余談

Listに2146435071個もデータを格納するとメモリを12.1[GB]も食われました笑
データベースに格納されているデータを全てを取得するとかで、もしかしたら発生するかもなので、こちらも今後は注意してプログラミングしたいと思いました。
image.png

以上!!!

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?