学プロ - 第 1 回

Download Report

Transcript 学プロ - 第 1 回

QueSTudents
竹井 悠人










ラムダ式
拡張メソッド
匿名型
オブジェクト初期化子
コレクション初期化子
暗黙的型指定ローカル変数
暗黙的型指定配列
LINQ (統合言語クエリ)
自動実装プロパティ
式ツリー

関係付けられたデータ (XML 含む) の操作





メタデータの利用
コンパイル時の構文チェック
静的な型付け
IntelliSence による入力支援
セキュアなコード
sequence<Customer> locals =
customers.where(ZipCode == 98112);
by Anders Hejlsberg (2004)
IEnumerable<Customer> locals =
Extension.Where(customers,
delegate (Customer c)
{
return c.ZipCode == 98112;
});
長くて直観的ではない!

C# 2.0 時代の匿名メソッドを進化させたもの
delegate (int x)
{
x => 2 * x + 4;
return
}

=> 演算子によって、パラメータとコードを連結
しただけ

signature => body
signature: シグニチャ (パラメータのリスト)
body: 関数本体 (式もしくはコード ブロック)

パラメータの型は明示不要

 コンパイラは、匿名メソッドの型推測を行えない


パラメータが 1 つの場合は () で括る必要なし
body が式の場合には、ラムダ式自体を式ツリー
に変換できる






x => x + 1
x => { return x + 1; }
(int x) => x + 1
(int x) => { return x + 1; }
(x, y) => x * y
() => Console.WriteLine()
IEnumerable<Customer> locals =
Extension.Where(customers,
delegate
c
=> c.ZipCode
(Customer
== 98112);
c)
{
customers
returnに対する操作だから、
c.ZipCode == 98112;
customers を主語にしたい
});

外部で定義されたメソッドを、インスタンス メ
ソッドと同様の表記で扱うことができる
 コンパイラ側でのトリック


静的クラスで定義されるメソッドの第 1 パラ
メータに this キーワードを付加
定義されるクラスはジェネリックではいけない
拡張メソッド – 文字列の操作

英語の語順から日本語の語順へ
 Sequence.Select(
Sequence.OrderBy(
Sequence.Where(customer,
c => c.Country == "Japan"),
c => c.Name)
c => c);
 customer.Where(c => c.Country == "Japan")
.OrderBy(c => c.Name)
.Select(c => c);
IEnumerable<Customer> locals =
Extension.Where(customers,
customers.Where(
c => c.ZipCode == 98112);
もし、customer の名前と年齢の
セットだけがほしい場合には?

簡単なデータ構造がほしいけど、クラスを実装
するほどでもない

new { Name = "Yuto", Age = 19 }
コンパイル時に string 型の Name プロパティ、
int 型の Age プロパティを持つクラスが生成さ
れる


new { memberList }
memberList: カンマ区切りでメンバを宣言

メンバの宣言には、変数名やプロパティ名など
のように名前を持っている値、もしくは
identifier = expression という割り当てを
用いる
同じ構造の匿名型どうしには互換性がある


匿名型の宣言と似ている
 new 演算子と、メンバ宣言の間に型名を入れるだけ


new Point { X = 10, Y = 20 }
Point クラスのパラメータなしコンストラクタ
が呼び出され、X, Y プロパティにそれぞれ値が
代入される

new type { memberList }
type: 初期化するオブジェクトの型
memberList: カンマ区切りでメンバを宣言

パラメータを持たないパブリック コンストラク
タを持たないクラスは、オブジェクト初期化子
は使えない
メンバの宣言は、identifier = expression
形式しか使えない


IEnumerable を実装するコレクション型につい
て、そのコレクションの要素を初期指定したい
場合に利用する

int[] arr = new int[] { 1, 2, 3 };
List<int> col = new List<int> { 1, 2, 3 };


上は従来の配列初期化子、下はコレクション初
期化子

匿名型などで初期化されたオブジェクトは、型
の名前がないから型指定できない

var student =
new { Name = "Yuto", Age = 19 };
student という変数に型推測が適用され、自動
的にコンパイル時の型指定が行われる


var での変数宣言は、初期値指定が必須
 そうでないと型推測ができない

初期値は、コンパイル時に型が確定しなければ
いけない
 したがって、初期値に null 指定はできない


複数の変数を同時に宣言できない
配列初期化子を持ってきてはいけない
 var array = { 0, 1, 2, 3, 4};

配列の要素の型がすべて同一な時、配列の型指
定を省略できる
 string, int の要素が混在するような配列は不可



int[] array = new int[] { 1, 2, 3 };
var array = new[] { 1, 2, 3 };
上が C# 2.0 まで、下が C# 3.0 での宣言形式




new[] { 1, 2, 3 }
new[] { "A", "B", "C" }
new[,] {
{ 1, 2 },
{ 3, 4 } }
new[] {
new[] { 1, 2 },
new[] { 3, 4 } }
// int[3]
// string[3]
// int[2,2]
// int[2][]

型が混在する配列は不可
 new[] { "Hello", 3.14, "world!" }
 new[] {
new ArgumentException(),
new DivideByZeroException() }

型の推測ができないので要素がない配列は不可
 new[] { }
var locals = customers
.Where(c => c.ZipCode == 98112)
.Select(c => new { c.Name, c.Age });
そして・・・究極の文法へ


Language Integrated Query (統合言語クエリ)
データの操作には SQL という言語が存在する
 これを C# に組み込んだものが LINQ

var cus = from c in customers
where c.Country = "Japan"
select new { c.Name, c.Age };

次のクエリの要素で組み立てられる








from identifier in expr
let identifier = expr
where boolExpr
join identifier in expr
on expr equals expr [ into identifier ]
orderby expr direction
select expr
group expr by expr
into identifier query
LINQ



C# Language Specification 3.0
http://msdn2.microsoft.com/en-us/vcsharp/
aa336809.aspx
LINQ の進化の過程と C# のデザインへの影響
http://msdn.microsoft.com/msdnmag/issues/07/
06/CSharp30/default.aspx?loc=jp
LINQ: .NET 統合言語クエリ
http://www.microsoft.com/japan/msdn/net/
bb308959.aspx