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

#結論
`Count`を使います。

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

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

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

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

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

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

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

```C#: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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/7d5aab6c-c1c3-ce05-3d8b-b8638801ebc3.png)


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

###Count()メソッドの内部実装
`Count()`メソッドの内部実装を調べた結果、下記のように実装されていました。
>参考：[Reference Source](https://referencesource.microsoft.com/#system.core/system/linq/Enumerable.cs)

```C#: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|

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

```C#:こんなソースコード書いたらソフトがﾀﾋりますね...
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()`メソッドを使用しないと行けない場合は注意しないといけませんね...！対処法としてはこのようにすればいいんだと思います。

```C#:これならﾀﾋらない
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/6d51c534-2431-aee4-bd1b-4c7560db4130.png)

以上！！！