読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET 絡みのメモを公開しています。

Linq入門記-12 (LINQ To Object, 変換演算子, ToArray)

C# Linq


今回から、LINQ To Objectの各演算子をちょこちょこメモっていこうと思います。
まず最初は、変換演算子から。


最初は、SelectとかWhereとかから始めるのが筋ですが、個人的にLINQ使っていて
しょっちゅう利用するのが、私の場合変換演算子なのです。w


LINQ To Objectの変換演算子は文字通りクエリ結果を特定の型に変換する為のものです。


また、それとは別に以下の要素も持っています。

通常、LINQクエリは遅延評価される(つまりループ時に初めて実行される)ので、実行する度に
クエリが評価されます。変換演算子を利用すると、その時点でのクエリ結果のスナップショットを
取得することが出来ます。

クエリは遅延評価されるので、例えば、1回目の実行の後にコレクションの要素を変更したりすると
2回目のクエリ結果は1回目と異なる事になります。通常これで問題ないのですが、時には
その時点での結果を保持しておきたい時もあります。このような時に変換演算子を利用すると
クエリ結果を即評価して、配列なりリストなりに保持することが出来ます。


変換演算子には、以下のものが用意されています。

  • ToArray
  • ToList
  • ToDictionary
  • ToLookup
  • OfType
  • Cast
  • AsEnumerable

このうち、AsEnumerableメソッドだけは特別です。このメソッドのみクエリ結果のスナップショットが
作成されません。このメソッドに関しては、また別の記事にて記述します。


今回は、ToArrayメソッドです。
LINQ To Objectの各演算子は、全て拡張メソッドとして定義されています。


書式は、以下の通りです。

public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)

ToArrayメソッドは、クエリ結果を

TSource[]

に変換してくれます。


以下、サンプルです。

    #region LinqSamples-12
    public class LinqSamples12 : IExecutable
    {
        class Person
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        
        public void Execute()
        {
            var persons = new List<Person>
            {
                 new Person{ Id = 1, Name = "gsf_zero1" }
                ,new Person{ Id = 2, Name = "gsf_zero2" }
                ,new Person{ Id = 3, Name = "gsf_zero3" }
                ,new Person{ Id = 4, Name = "gsf_zero4" }
                ,new Person{ Id = 5, Name = "gsf_zero5" }
            };
            
            var query = from   aPerson in persons
                        where  (aPerson.Id % 2) == 0
                        select aPerson;
            
            Console.WriteLine("============ クエリを表示 ============");
            foreach(var aPerson in query)
            {
                Console.WriteLine("ID={0}, NAME={1}", aPerson.Id, aPerson.Name);
            }
            
            //
            // ToArrayを利用して、明示的に配列に変換.
            // (このタイミングでクエリが評価され、結果が構築される。)
            //
            Person[] filteredPersons = query.ToArray();
            
            Console.WriteLine("============ ToArrayで作成したリストを表示 ============");
            foreach(var aPerson in filteredPersons)
            {
                Console.WriteLine("ID={0}, NAME={1}", aPerson.Id, aPerson.Name);
            }
            
            //
            // 元のリストを変更.
            //
            persons.Add(new Person{ Id = 6, Name = "gsf_zero6" });
            
            //
            // もう一度、各結果を表示.
            //
            Console.WriteLine("============ クエリを表示(2回目) ============");
            foreach(var aPerson in query)
            {
                Console.WriteLine("ID={0}, NAME={1}", aPerson.Id, aPerson.Name);
            }
            
            Console.WriteLine("============ ToArrayで作成したリストを表示 (2回目)============");
            foreach(var aPerson in filteredPersons)
            {
                Console.WriteLine("ID={0}, NAME={1}", aPerson.Id, aPerson.Name);
            }
        }
    }
    #endregion


出力結果は以下のようになります。

  ============ クエリを表示 ============
  ID=2, NAME=gsf_zero2
  ID=4, NAME=gsf_zero4
  ============ ToArrayで作成したリストを表示 ============
  ID=2, NAME=gsf_zero2
  ID=4, NAME=gsf_zero4
  ============ クエリを表示(2回目) ============
  ID=2, NAME=gsf_zero2
  ID=4, NAME=gsf_zero4
  ID=6, NAME=gsf_zero6
  ============ ToArrayで作成したリストを表示 (2回目)============
  ID=2, NAME=gsf_zero2
  ID=4, NAME=gsf_zero4


次は、ToListメソッドです。
(といっても、ToArrayとほぼ同じですがw)