講義メモ

テキスト編:p.405「LINQとは」から
ゲーム開発編:自弾の敵弾衝突処理、テクスチャによる描画、自弾敵弾の衝突による爆散、など

p.405 LINQとは

・SQL(データベース操作言語)に近い構文によって、データ構造からの検索を行う仕掛け
・SQLの書式例:
 SELECT 項目名,… FROM 構造名 WHERE 項目名 条件演算子 値など
例:
 SELECT モンスター名,HP FROM モンスター表 WHERE HP > 100
・SQLによる検索のポイント:値を返す関数やメソッドと異なり、データ構造が返される
・LINQの対象例: 配列、リストなどのコレクション、XML文書 など

p.406 LINQのクエリ

・クエリとはSQLにおける問い合わせのことで、データ構造が返される
・C#が提供するジェネリックインターフェイスを用いると、SQLに近い構文が使える

p.408 linq01.cs

//p.408 linq01.cs
using System;
using System.Linq; //LINQ構文用
using System.Collections.Generic; //IEnumerable<T>インターフェイス用 
class linq01 {
    public static void Main() {
        int[] numbers = new int[] { -3, 4, 1, 2, -6, 3, 100, -25}; //クエリ対象の配列
        // クエリの作成
        IEnumerable<int> q = from n in numbers //配列numbersから
                where n > 0 //要素値が正であるものを
                select n; //得た結果の構造を返す
        // クエリの実行
        foreach (int x in q) { //IEnumerable<T>インターフェイス型オブジェクトから全要素(int型)について繰返す
            Console.WriteLine(x);
        }
    }
}

p.406 LINQのクエリ(続き)

・LINQ構文を用いるには「using System.Linq;」を記述する(必須)
・LINQ構文で得られるデータ構造は、IEnumerable<T>インターフェイス型になる
・このジェネリクスに、クエリ対象の型を指定する
・配列を対象とする場合は、配列の要素型を指定すれば良い
・得られたIEnumerable<T>インターフェイス型のオブジェクトから、foreachなどで要素を取り出す処理を繰返すと良い
・クエリ式の基本書式: 
 from 項目名 in 構造名 where 項目名 条件演算子 値 select 構造名
・配列の場合のクエリ式の基本書式: 
 from 作業変数 in 配列名 where 作業変数 条件演算子 値 select 配列名
・なお、IQueryable<T>を用いることも可能
※ VS2008ではp.407記載の手順が必要、VS2008より前のバージョンでは利用不可

p.409 データの並べ替えと個数

・LINQのメリットの一つはSQLのソート機能や関数機能などを利用できること
・構文:
 from 項目名 in 構造名 orderby 対象項目名 select 構造名
・規定値は昇順(小⇒大)だが、対象項目名に descending を付記すると降順(大⇒小)になる
・得られたIEnumerable<T>インターフェイス型のオブジェクトで、Count()メソッドを呼ぶと件数が得られる
 ※ SQLでもCOUNT(*)構文で件数が得られる

p.409 linq02.cs

//p.409 linq02.cs
using System;
using System.Collections.Generic; //IEnumerable<T>インターフェイス用 
using System.Linq; //LINQ構文用
class linq02 {
  public static void Main() {
    string[] myStr = {"flower", "cat", "dog", "bird", "rabbit"}; //クエリ対象の配列
    // クエリの作成
    IEnumerable<string> q =
      from s in myStr  //配列myStrから
      where s.Length >=  4 //要素値の文字数が4以上であるものを
      orderby s descending //要素値の降順に整列せよ
      select s;
    // クエリの実行
    foreach (string x in q)
      Console.WriteLine(x);
    // 検索条件に適合した要素の個数
    Console.WriteLine("適合した数={0}", q.Count());
  }
}

p.410 var型の利用

・クエリが返すオブジェクトの型はIEnumerable<T>インターフェイス型と決まっている
・しかも、型パラメータの型もクエリによって自動決定できる
・よって、IEnumerable<T>型をvarキーワードで置き換えて良い
・これにより「using System.Collections.Generic;」も自動化されるので記述不要
※ 加えて、foreachで用いる作業変数の型もvarキーワード指定で良い

アレンジ演習:p.409 linq02.cs

・IEnumerable<T>型をvarキーワードで置き換えてみよう

作成例

//アレンジ演習:p.409 linq02.cs
using System;
// using System.Collections.Generic; //【削除】不要
using System.Linq; //LINQ構文用
class linq02 {
    public static void Main() {
        string[] myStr = { "flower", "cat", "dog", "bird", "rabbit" }; //クエリ対象の配列
        var q = from s in myStr where s.Length >= 4 orderby s descending select s;
        // クエリの実行
        foreach (var x in q)
            Console.WriteLine(x);
        // 検索条件に適合した要素の個数
        Console.WriteLine("適合した数={0}", q.Count());
    }
}

p.410 Listコレクションからのデータ抽出

・配列と同様にList<T>型のコレクションオブジェクトをLINQで扱うことが可能
・この場合、List<T>型に与えた型パラメータが自動的にクエリ結果の要素型になる
・List<T>型の利用には「using System.Collections.Generic;」が必要

p.411 linq03.cs

//p.411 linq03.cs
using System;
using System.Collections.Generic; //List<T>用
using System.Linq; //LINQ構文用
class data { //Listに格納するオブジェクトの型になるクラス
  public string name;
  public string address;
  public int age;
}
class linq03 {
  public static void Main() {
    List<data> mydata = new List<data> { //クラスdataを要素型とするリスト
        new data { name = "田中和夫", address = "東京都", age = 24}, //オブジェクト初期化子で生成
        new data { name = "鈴木義男", address = "東京都", age = 17},
        new data { name = "吉田育子", address = "青森県", age = 24},
        new data { name = "田中和夫", address = "東京都", age = 34},
        new data { name = "小林一郎", address = "北海道", age = 29}
    };
    // 旧式のデータ追加
    data datax = new data();
    datax.name = "粂井康孝";
    datax.address = "北海道";
    datax.age = 22;
    mydata.Add(datax); //Listオブジェクトに格納
    // 新方式のデータ追加
    mydata.Add(new data { name = "猫山太郎", address = "青森県", age = 15 }); //オブジェクト初期化子で生成
    var q = from x in mydata
            where x.age < 30
            orderby x.age ascending //※ascendingは省略可能
            select x; //クエリを実行
    Console.WriteLine("氏名\t\t住所\t年齢");
    foreach (data z in q) {
      Console.WriteLine("{0}\t{1}\t{2}", z.name, z.address, z.age);
    }
  }
}

p.412 メソッド構文の利用

・LINQのクエリ構文はC#の文法と馴染まないので、可読性のために、メソッドをドットでつなぐ形式のメソッド構文も利用できる
・書式例:
 構造名.Where(条件メソッド名).Select(選択メソッド名);
・条件メソッドの書式例:
 static bool 条件メソッド名(型 作業変数) { return 作業変数を用いた条件式; }
・選択メソッドの書式例:
 static 項目型 選択メソッド名(型 作業変数) { return 作業変数; }
・ソートなども可能
・書式例:
 構造名.Orderby(整列メソッド名).Select(選択メソッド名);
 構造名.OrderbyDesending(整列メソッド名).Select(選択メソッド名); //降順用
・整列メソッドの書式例:
 static 項目型 整列メソッド名(型 作業変数) { return 作業変数; }

p.413 linq04.cs

//p.413 linq04.cs
using System;
using System.Linq; //LINQ構文用
class linq04 {
  static bool MyWhere(int x) { //条件メソッド
    return (x > 0); //作業変数を用いて条件(正の数のみ)を表す
  }
  static int MyOrderBy(int x) { //整列メソッド
    return x; //引数で得た作業変数を返すのみ
  }
  static int MySelect(int x) { //選択メソッド
    return x; //引数で得た作業変数を返すのみ
  }
  public static void Main() {
    int[] numbers = new int[] {200, -3, 4, 1, 2, -6, 3, 100, -25}; //クエリ対象の配列
    //メソッド構文
    var q = numbers.Where(MyWhere) //条件メソッドを指定
      .OrderByDescending(MyOrderBy) //整列メソッドを指定し降順でソート
      .Select(MySelect); //選択メソッドを指定
    //クエリの実行
    foreach (int x in q) {
      Console.WriteLine(x);
    }
  }
}

p.415(メソッド構文における匿名メソッドの利用)

・メソッド構文で別記している各メソッドは、匿名メソッド(p.304)にすることで簡略化できる
・書式例:
 構造名.Where(delegate(型 引数){return 条件式;}).Select(delegate(型 引数){return 引数;});
・デリゲートにより、各メソッドを別記する必要がなくなる

p.415 linq05.cs

//p.415 linq05.cs
using System;
using System.Linq; //LINQ構文用
class linq05 {
  public static void Main() {
    int[] numbers = new int[] {200, -3, 4, 1, 2, -6, 3, 100, -25}; //クエリ対象の配列
    //メソッド構文
    var q = numbers.Where(delegate(int x) { return x > 0; }) //条件をデリゲートで指定
      .OrderByDescending(delegate (int x) { return x; }) //整列メソッドをデリゲートで指定し降順でソート
      .Select(delegate (int x) { return x; }); //選択をデリゲートで指定
    //クエリの実行
    foreach (int x in q)
      Console.WriteLine(x);
  }
}

p.415(メソッド構文におけるラムダ式の利用)

・匿名メソッドはラムダ式(p.306)にすることで、よりシンプルにできる
・書式例:
 構造名.Where(引数 => 条件式).Select(引数 => 引数);
・型の自動判定ができるので、引数型は省略可能
・「引数 => 引数」は一律に「x => x」「w => w」などとしてOK

p.415 linq06.cs

//p.415 linq06.cs
using System;
using System.Linq; //LINQ構文用
class linq05 {
  public static void Main() {
    int[] numbers = new int[] {200, -3, 4, 1, 2, -6, 3, 100, -25}; //クエリ対象の配列
    //メソッド構文
    var q = numbers.Where(x => x > 0) //条件をラムダ式で指定
      .OrderByDescending(x => x) //整列をラムダ式で指定し降順でソート
      .Select(x => x); //選択をラムダ式で指定
    //クエリの実行
    foreach (int x in q)
      Console.WriteLine(x);
  }
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です