【c#】List<T>のList<T>はインスタンス化してAddしよう

たとえば、ランダムに並んだDateTimeのListがあって、それを月毎にまとめてList化しておきたいケースがある。

そのとき、

①:とある月のDateTimeのList
②:①のList

ってカンジで、②のような[ List の List ]をつくるとしよう。

んで。

こーゆー、ListにListをAddするときはかならず、AddするListをインスタンス化してからAddしよーぜ。ってな話。

コード

using System;
using System.Collections.Generic;
using System.Linq;

namespace testNameSpace
{
    class testClass
    {
        public void testMethod()
        {
            List<DateTime> dtListRandom = new List<DateTime>();

            for(int nIndex = 0; nIndex < 50 ; nIndex++ ){
                DateTime dtStart = new DateTime(2019, 1, 1);
                DateTime dtEnd = new DateTime(2019, 12, 31);
                Random r = new Random();
                int nRange = ((TimeSpan)(dtEnd - dtStart)).Days;
                dtListRandom.Add(dtStart.AddDays(r.Next(nRange)));
                System.Threading.Thread.Sleep(1);
            }

            List<List<DateTime>> dtMonthly = getMonthly(dtListRandom);

            foreach(List<DateTime> dtList in dtMonthly){
                Console.WriteLine("↓" + dtList.ElementAtOrDefault(0).Month + "月のデータ");
                foreach(DateTime dt in dtList){
                    Console.WriteLine(dt);
                }
            }
        }

        // とある年のDateTimeのListを《月毎のList》にまとめ《全月分List》にして返す関数
        private List<List<DateTime>> getMonthly(List<DateTime> dtListRandom)
        {
            List<List<DateTime>> dtListMonthly = new List<List<DateTime>>();
            List<DateTime> dtListOneMonth = new List<DateTime>();

            for(int nCompareMonth = 1; nCompareMonth <= 12; nCompareMonth++)
            {
                foreach(DateTime dt in dtListRandom ){
                    int nMonth = dt.Month;
                    if(nCompareMonth == nMonth){
                        dtListOneMonth.Add(dt);
                    }
                }
                // ↓今回のポイントはコレ
                dtListMonthly.Add(new List<DateTime>(dtListOneMonth));
                dtListOneMonth.Clear();
            }
            return dtListMonthly;
        }
    }
}


出力

↓1月のデータ
2019/01/19 0:00:00
2019/01/18 0:00:00
2019/01/25 0:00:00
2019/01/05 0:00:00
↓2月のデータ
2019/02/20 0:00:00
2019/02/27 0:00:00
2019/02/07 0:00:00
2019/02/26 0:00:00
2019/02/06 0:00:00
2019/02/13 0:00:00
↓3月のデータ
2019/03/31 0:00:00
2019/03/11 0:00:00
2019/03/18 0:00:00
2019/03/17 0:00:00
↓4月のデータ
2019/04/19 0:00:00
2019/04/06 0:00:00
2019/04/25 0:00:00
↓5月のデータ
2019/05/09 0:00:00
2019/05/28 0:00:00
2019/05/08 0:00:00
2019/05/16 0:00:00
2019/05/27 0:00:00
↓6月のデータ
2019/06/30 0:00:00
2019/06/10 0:00:00
2019/06/18 0:00:00
2019/06/29 0:00:00
2019/06/16 0:00:00
↓7月のデータ
2019/07/19 0:00:00
2019/07/07 0:00:00
2019/07/26 0:00:00
↓8月のデータ
2019/08/09 0:00:00
2019/08/28 0:00:00
2019/08/07 0:00:00
2019/08/26 0:00:00
↓9月のデータ
2019/09/09 0:00:00
2019/09/28 0:00:00
2019/09/16 0:00:00
↓10月のデータ
2019/10/19 0:00:00
2019/10/06 0:00:00
2019/10/17 0:00:00
2019/10/25 0:00:00
2019/10/05 0:00:00
↓11月のデータ
2019/11/08 0:00:00
2019/11/19 0:00:00
2019/11/27 0:00:00
2019/11/07 0:00:00
2019/11/26 0:00:00
↓12月のデータ
2019/12/29 0:00:00
2019/12/16 0:00:00
2019/12/15 0:00:00

これならうまくいくんだけど、もし

// ↓今回のポイントはコレ
dtListMonthly.Add(new List<DateTime>(dtListOneMonth));

ここを

// ↓今回のポイントはコレ
dtListMonthly.Add(dtListOneMonth);

こうすると


出力

↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ
↓1月のデータ

データが消えるw

これは、Addするときにインスタンス化しないと参照がAddされるから、おなじアドレスの参照が連なったListができて、最後には

dtListOneMonth.Clear();

この処理で参照先の値がクリアされたと。


・・・ちゃんとインスタンス化してAddせんとな。

これマジ。