C#3.0メモ1

主にLINQまわり1

3.0での省略記法について

データ型は型推論により決定される。
その為、省略して書かれていても型はしっかりと決まっている。

クラス定義の省略記法

public class Parson
{
    public String Name { get; set; }
    public String Sex { get; set; }
    public String Belong { get; set; }
}

//この書き方は、ParsonがNewされた後に各項目へ値をセットする。
//その為、ReadOnlyなメンバなどにはセットできない。
Parson[] parsons = {
   new Parson(){Name = "山田太郎", Sex="男", Belong="営業"},
   new Parson(){Name = "勝山次郎", Sex="男", Belong="営業"},
   new Parson(){Name = "山中真奈美", Sex="女", Belong="技術"},
   new Parson(){Name = "としこ", Sex="女", Belong="秘書"},
   new Parson(){Name = "越中銀次郎", Sex="男", Belong="広報"},
   new Parson(){Name = "大鳥昭信", Sex="男", Belong="社長"}
};

LINQでの反復処理

Enumerableクラスで定義されているメソッド・IEnumerableクラスの拡張メソッドで、ごにょごにょすることが多い。

シンプルなクエリ

//select句には、クエリを実行したときに生成される値の型を指定します。
//省略した場合は、範囲変数と同じデータ型のシーケンスが返される。
//qのデータ型はIEnumerable<int>
var q = from x in Enumerable.Range(1, 10) select x;  
foreach (var rec in q)
    Console.WriteLine(rec.ToString());

クエリ同士の結合

//商品分類
private class ItemKind
{
    public int KindId { get; set; }
    public String KindName { get; set; }
}

//商品
private class Item
{
    public int ItemId { get; set; }
    public int KindId { get; set; }
    public String ItemName { get; set; }
    public int ItemPrice { get; set; }
}

//クエリ実行
private class JoinQueryTest
{
	private ItemKind[] kinds;
	private List<Item>items = new List<Item>();
	private Random rmd;

	public JoinQueryTest()
	{
		rmd = new Random();

		kinds = new ItemKind[]
		{
		    new ItemKind() { KindId = 1, KindName = "分類1" },
		    new ItemKind() { KindId = 2, KindName = "分類2" },
		    new ItemKind() { KindId = 3, KindName = "分類3" },
		    new ItemKind() { KindId = 4, KindName = "分類4" },
		};

		for (int i = 0; i < 10000; i++)
		{
		    items.Add(new Item(){ItemId = i + 1
		                            , ItemName = "アイテム" + i.ToString()
		                            , ItemPrice = 10000 - i
		                            , KindId=rmd.Next(1,4)
		    });
		}
	}

	public void DoTasukigakeQuery()
	{
		var sw = new System.Diagnostics.Stopwatch();

		//下記クエリのようなJoinしないたすきがけは非常に遅いので使用しないこと。
		sw.Start();
		var q1 = from x in kinds
		         from y in items
		         where x.KindId == y.KindId && x.KindId == 2
		         select new { Name = y.ItemName, Kind = x.KindName };
		sw.Stop();
		Console.WriteLine("Query1 Define Time:{0}", sw.ElapsedMilliseconds);
		sw.Reset();
		sw.Start();

		StringBuilder sb = new StringBuilder();
		foreach (var rec in q1)
		    sb.Append("Name:" + rec.Name + "   Kind:" + rec.Kind.ToString());
		sw.Stop();
		Console.WriteLine("Query1 ResultOutputInfo  Count:{0}   Time:{1}", q1.Count(), sw.ElapsedMilliseconds);
		sw.Reset();
	}

	public void DoJoinQuery()
	{
		var sw = new System.Diagnostics.Stopwatch();

		sw.Start();
		var q2 = from x in items
		         join y in kinds on x.KindId equals y.KindId
		         where x.KindId == 2
		         select new { Name = x.ItemName, Kind = y.KindName };
		sw.Stop();
		Console.WriteLine("Query2 Define Time:{0}", sw.ElapsedMilliseconds);
		sw.Reset();
		sw.Start();

		StringBuilder sb = new StringBuilder();
		foreach (var rec in q2)
		    sb.Append("Name:" + rec.Name + "   Kind:" + rec.Kind.ToString());
		sw.Stop();
		Console.WriteLine("Query2 ResultOutputInfo  Count:{0}  Time:{1}", q2.Count(), sw.ElapsedMilliseconds);
		sw.Reset();
	}
}

//[実行結果]
//1回目
//Query1 Define Time:0
//Query1 ResultOutputInfo  Count:3308   Time:14
//Query2 Define Time:2
//Query2 ResultOutputInfo  Count:3308  Time:16

//2回目
//Query1 Define Time:0
//Query1 ResultOutputInfo  Count:3354   Time:10
//Query2 Define Time:0
//Query2 ResultOutputInfo  Count:3354  Time:2

//3回目
//Query1 Define Time:0
//Query1 ResultOutputInfo  Count:3392   Time:8
//Query2 Define Time:0
//Query2 ResultOutputInfo  Count:3392  Time:3

//4回目
//Query1 Define Time:0
//Query1 ResultOutputInfo  Count:3325   Time:27
//Query2 Define Time:0
//Query2 ResultOutputInfo  Count:3325  Time:3

//5回目
//Query1 Define Time:0
//Query1 ResultOutputInfo  Count:3329   Time:14
//Query2 Define Time:0
//Query2 ResultOutputInfo  Count:3329  Time:4