以下の記事で、IEnumerable<T>.ToArray
の中身を確認した。
【C#】IEnumerable<T>.ToArray の中身を確認 - てくメモ
この機会に、それ以外のコレクションにするメソッド(ToList
、ToDictionary
、ToHashSet
、ToLookup
)を確認しておく。
ちなみに、変わったことはなかったので本当に確認。
ToArray
v.s. ToList
どっちを使うのがよいの? というような感じで並べられることがある。
しかし、ToList
は(IIListProvider<TSource>
を用いて最適化が図られているが基本的には)List<T>
コンストラクタのショートハンドなので、単純に配列とリストのどっちが適するかで決めればよいと思う。
参考:Source Browser(ToList<TSource>
拡張メソッド)
少し踏み込めば、リストは配列より高級なので、リスト操作を必要としなければ常にToArray
でよい。
ToDictionary
、ToHashSet
、ToLookup
ToDictionaryはシーケンスを辞書にする。
実質、シーケンスを渡すDictionary<TKey, TValue>
コンストラクタのショートハンド。
参考:Source Browser(ToDictionary<TKey, TValue>
拡張メソッド)
普通に操作する場合もそうであるように、重複要素があると例外が飛ぶ。
IEnumerable<int> source = new int[] { 1, 2, 3, 1 }; var dic = source.ToDictionary(v => v); // ❌ ArgumentException
ただ、辞書が浮かんでも、実際にしたいのはToHashSet
あるいはToLookup
という場合がある。
ユニークな要素のコレクションをつくりたい場合は前者、重複ありのキー-要素コレクションをつくりたい場合は後者を使う。
ToHashSet
はHashSet<T>
コンストラクタのショートハンド。
参考:Source Browser(ToHashSet<TSource>
拡張メソッド)
var set = source.ToHashSet(); Console.WriteLine(set.ToListString()); // ToListString という [a, b, c...] というような文字列とする拡張メソッドがあるものとする // [1, 2, 3]
HashSet<T>.Add
が例外を出さないのと同様、これも例外は飛ばない。
リストのときと同じくLINQ固有の話ではないけれど、ユニークな要素のコレクションで順序が重要でなければHashSet<T>
を使う。
ToLookup
は、キーで要素をグルーピングしたコレクションを生成する。
参考:Source BrowserToLookup<TSource, TKey>
拡張メソッド
百聞は一見に如かず。
var lookup = source.ToLookup(v => v); foreach ( var group in lookup) { Console.WriteLine($"Key={group.Key}, Items={group.ToListString()}"); } // Key=1, Items=[1, 1] // Key=2, Items=[2] // Key=3, Items=[3]
これに関しては既存コレクション生成のショートハンドではなく、引き出しに入れておきたい。
ちなみに、このメソッドで返ってくるILookup
、そしてそれが内容として持つIGrouping
は、実装クラスがinternal
であり、実装の流用ができない。(😥)
個人的なまとめ
- 基本を置くのは
ToArray
- リスト、辞書、セットが使いたければそれぞれの ToXXX
- これらに関しては LINQ というより単にどの構造を使うかというお話
ToLookup
は頭に入れておく