CLR/H No.35-2
-
Upload
nobuhisa-koizumi -
Category
Documents
-
view
1.520 -
download
0
description
Transcript of CLR/H No.35-2
More C#
λ
自己紹介自己紹介
• 名称 := K 泉将久 | のぶ | Nobuhisa |• 特技 ⇒
C#におけるλ式
Func<int, int> f = (x => x * x);
C#3.0 – lambda expressionC#3.0 – lambda expression
• 書き方色々 Func<T1, .., T4, TResult>
Func<string> f1 = () => “hello, world”;
Func<int, int> f2 = (int x) => x + 1;Func<int, string> f3 = x => (x<=5 ? “foo” : “bar”);
Func<int, int, int> f4 = (x, y) => x * y;
Func<string, int> f5 = x => {int length = x.Length;return length;
};
System.Action nop = () => {};
意外と嬉しいコレクション初期化子
var lst = new List{ 1, 2, 4, 8 };
C#3.0 – Collection InitializersC#3.0 – Collection Initializers
• Before…
List<Employee> lst = new List<Employee>();
Employee john = new Employee();john.Name = "john";john.Age = 58;Employee michael = new Employee();michael.Name = "taro";michael.Age = 62;
lst.Add( john );lst.Add( michael );
C#3.0 – Collection InitializersC#3.0 – Collection Initializers
•After !var + オブジェクト初期化子 + コレクション初期化子
v a r l s t = n e w Li s t <Emp l o y e e >( ) {n e w Emp l o y e e { Na me = " j o h n " , Ag e = 2 2 } ,n e w Emp l o y e e { Na me = " t a r o " , Ag e = 2 4 } ,
} ;
C#3.0 – Collection InitializersC#3.0 – Collection Initializers
• クラス変数の dic を初期化
public class Foo{
Dictionary<string,int> dic = new Dictionary<string,int>{{ "one", 1 }, { "two", 2 }, { "three", 3 }
};
/*public Foo() {this.dic.Add( "one", 1 );this.dic.Add( "two", 2 );this.dic.Add( "three", 3 );
}*/}
型パラメータによって振る舞いを変える
Foo<ClassA>.Method( x );Foo<ClassB>.Method( x );
GenericsGenerics
渡された型 T は実行時に if 文等で判別できない
( 引数なしの場合 )
.4 静的フィールドと静的コンストラクタを活用する
⇒ Demo
.5 C#3.0 の拡張メソッドを使う
⇒ 容易だがこの場合やや柔軟性に欠ける
11 . . 静的フィールドの利用静的フィールドの利用
• ジェネリッククラスに属する静的な変数は、型パラメータが違うとどんな扱いになる?
class Foo<T> { public static int Value; }~
Foo<int>.Value = 99;Foo<string>.Value++;
Console.WriteLine( Foo<int>.Value );Console.WriteLine( Foo<string>.Value );
991
Demonstration
型パラメータによって振る舞いを変える
- 静的フィールド利用編 -
型パラメータの判別型パラメータの判別
渡された型 T は実行時に if 文等で判別できない
( 引数なしの場合 )
.4 静的フィールドと静的コンストラクタを活用する
⇒ Demo
.5 C#3.0 の拡張メソッドを使う
⇒ 容易だがこの場合やや柔軟性に欠ける
22 . . 拡張メソッドを使った場合拡張メソッドを使った場合
• 拡張メソッドの使い方– 静的クラス、静的メソッド
– 第一引数の this キーワード
public static class SampleExtensions{
public static int Add( this int a, int b ){
return a + b;}
}~
int a = 60;int result = a.Add( 40 ); // 100
22 . . 拡張メソッドを使った場合拡張メソッドを使った場合
public class Foo<T> { }
public static class FooExtensions{
public static void Method( this Foo<string> f, int x ){
Console.WriteLine( x + " かもしれない " );}public static void Method( this Foo<int> f, int x ){
Console.WriteLine( x + " じゃないと思う " );}public static void Method<T>( this Foo<T> f, int x ){
Console.WriteLine( x );}
}つづく
22 . . 拡張メソッドを使った場合拡張メソッドを使った場合
public void Test(){
new Foo<string>().Method( 10 );new Foo<int>().Method( 100 );new Foo<Foo<string>>().Method( 1000 );
}
10 かもしれない
100 だと思う1000
22 . . 拡張メソッドを使った場合拡張メソッドを使った場合
• 好きそうな人向けのおまけ ~ カリー化
– 拡張メソッドの第一引数部分に f を束縛した状態
• 本格的なカリー化はクロージャで
var f = new Foo<string>();Action<int> curry = f.Method;
curry( 10 ); // 10 かもしれない
C#におけるクロージャのからくり
x => y => x * y;
函数はファーストクラスオブジェ
クト
f = Console.WriteLine;
ファーストクラスオブジェクト?ファーストクラスオブジェクト?
• (ほぼ)第一級オブジェクトです– だから何?(←みんなの心の声)
– 次ページから具体例をお見せします
• 高階関数が直感的に書ける– これを使う利点が分かりません(←みんなの心の声)
– 後ほど扱います
実用例~関数の足し算実用例~関数の足し算
public Func<string> GetFunc() {string data = "hello";Func<string> fns = null;
fns += (() => data += " world");fns += (() => data = data.ToUpper());fns += (() => data = "<b>"+data+"</b>");return fns;
}~
var f = this.GetFunc();Console.WriteLine( f() ); // <b>HELLO WORLD</b>
“ ”責任 を動的に組み替えられる⇒ ミニマムな Decoratorパターン
実用例2~実用例2~ switchswitch の除去の除去
public abstract class Food { }public class ちくわ : Food { }public class ネオちくわ : ちくわ { }public class いも : Food { }public class じゃがいも : いも { }public class みそしる : Food { }~public Food Create( string name ) {
switch ( name ) {case "taro": return new ネオちくわ ();case "hanako": return new いも ();case "mae": return new みそしる ();default: throw new ArgumentException();
}}
Before…
実用例2~実用例2~ switchswitch の除去の除去
private Dictionary<string, Func<Food>> table =new Dictionary<string, Func<Food>>()
{{ "taro", () => new ネオちくわ () },{ "hanako", () => new いも () },{ "mae", () => new みそしる () }
};
public Food Create( string name ){
if ( this.table.ContainsKey( name ) )return this.table[ name ]();
throw new ArgumentException();}
After !
高階関数をもう少し
(sort '((one . 1) (two . 2) (three . 3)) #'> :key #'cdr)
高階関数高階関数
• 「関数を受け取る」高階関数– 関数の抽象化が可能となり、汎用性が増す
– 従来の抽象化の概念がクラスレベルから関数レベルへ
• 「関数を返す」高階関数– 関数を動的に生成したり、改造したりできる
– 知らなくても良い情報を隠蔽する価値もある
– 前者より脚光を浴びてない(?)ので、今日はこっちを主役にします
高階関数~メモ化高階関数~メモ化
• 本日ご紹介するのはコレ! ⇒ 渡された関数にキャッシュ機能を追加して返す
– 処理が重い && 複数回実行される関数などを渡す
– 2 回目以降は高速化が期待できる
– 外部の可変変数に依存していない関数を渡す
• 引数と計算結果のペアを、コレクションに保存しておき、クロージャにして返す
• このような機能をメモ化 (memoization,memoize) という
高階関数~メモ化高階関数~メモ化
• Demoプログラムの主要部分抜粋
publicFunc<T, TResult> Memoize<T, TResult>( Func<T, TResult> fn ){
var dic = new Dictionary<T, TResult>();
return x => {if ( ! dic.ContainsKey( x ) )
dic.Add( x, fn( x ) );return dic[ x ];
};}
関数 + 環境 ⇒ クロージャ ( Closure)
Demonstration
メタボ関数を軽くする
- メモ化 -
ちょっとマイナーな標準クエリ演算子
SelectMany.ToLookup.
OfType.
Demonstration
いくつかクエリを
- LINQ -
質問タイム
\ (^ o^ )/
まとめ
まとめまとめ
• 色々な λ 式の書き方
• コレクション初期化子、オブジェクト初期化子
• 型パラメータによって振る舞いを変える
• ファーストクラスオブジェクト
• 高階関数– 関数を受け取る
– 関数を返す( demo: メモ化)
• 標準クエリ演算子( LINQ )
最後に
Demonstration.
ご清聴どうもありがとうございました。
Nobuhisa Koizumi.