FITEAのC#勉強会に行ってきた
2008.03.12(水) C#2.0&3.0勉強会についてのレポート
ξ*゚⊿゚)ξ <べ、別におもしろかったから書くわけじゃないのよ。
ξ*゚⊿゚)ξ <勤務扱いで参加したから、会社に強制されてるだけなんだから。
ξ*゚⊿゚)ξ <か、勘違いしないでよね!
閑話休題
さて内容そのもののレポートは諸兄がいくらでもしてくれると思うので、ちょっと突っ込んだ・または補足的な内容をエントリー。
# 本題に入る前に、リファレンスへのリンクをば。
C# 2.0 の新機能
C# 3.0 の概要
■匿名型
1 2 3 4 | var product = new { Name = "リアホイールベアリング", Price = 2000 }; |
C#3.0で追加になる書式。上記のように書くことで、クラス宣言を記述しなくてもデータ定義ができる構文。JavaScriptのJSONを連想する向きも多いはず。(ま、JSONはevalによる評価が可能により動的なオブジェクト生成が可能なのがキモなんだけどね)
さてここで、型の同一性についての実験。
1 2 3 4 5 6 | var p1 = new { Name = "ピストンリングセット", Price = 1300 }; var p2 = new { Name = "フロントフォークAssy", Price = 12000 }; |
上記コードにより生成できる2インスタンスの双方の型は、同じなのかどうか。
1 | Console.WriteLine( p1.GetType() == p2.GetType() ); |
結果は見事にTrue。
次に、2つのオブジェクトを別々のクラス内で生成させてみよう。
1 2 3 4 5 6 7 8 9 10 11 | // in Class1 var p3 = new { Name = "マスターシリンダーセット", Price = 1650 }; // in Class2 var p4 = new { Name = "シングルシートComp", Price = 3900 }; Console.WriteLine( p3.GetType() == p4.GetType() ); |
OK。結果はTrueだ。
さて今度は、別々のアセンブリで匿名型を生成してみよう。
1 2 3 4 5 6 7 8 9 10 11 | // in SampleClassLibrary.dll var p5 = new { Name = "フライホイールAssy", Price = 8000 }; // in TestApplication.exe var p6 = new { Name = "リードバルブガスケット", Price = 200 }; Console.WriteLine( p5.GetType() == p6.GetType() ); |
これは結果False。匿名型はアセンブリ内でのみ完結するようだ。それぞれのアセンブリごとに、コンパイル時に完結して型解決ができないといけないので、当然といえば当然か。
次に趣向を変えて、プロパティを少し変えてみる。
1 2 3 4 5 6 7 8 9 10 | var p7 = new { Name = "ヘッドライトComp" }; var p8 = new { Naming = "シリンダスタッドボルト" }; var p9 = new { Name = 200 }; Console.WriteLine( "p7 : {0}", p7.GetType().Name ); Console.WriteLine( "p8 : {0}", p8.GetType().Name ); Console.WriteLine( "p9 : {0}", p9.GetType().Name ); |
すると、なんということでしょう。出力結果が以下のようになってしまった。
1 2 3 | p7 : <>f__AnonymousType0`1 p8 : <>f__AnonymousType1`1 p9 : <>f__AnonymousType0`1 |
この型名というのはコンパイル時に自動生成される特殊な名前なんだが、p7 != p8なのは当然として、p7 == p9となってしまっているのが見て取れる(という罠が仕掛けられている)。実際p7とp9はNameという同じ名前のプロパティがあるにも関わらず、型はstringとintで異なっている。
実は以下のようにすると、ちゃんと違っていることが分かることになる。
1 2 3 | Console.WriteLine( "p7 : {0}", p7.GetType().FullName ); Console.WriteLine( "p8 : {0}", p8.GetType().FullName ); Console.WriteLine( "p9 : {0}", p9.GetType().FullName ); |
出力される型のフルネームは長いため省略するが、持っているプロパティの型が含まれた名前が取得できることが分かるはずだ。当然のことながら、以下のようにチェックすればすべてFalseとなる。
1 2 3 | Console.WriteLine( p7.GetType() == p8.GetType() ); Console.WriteLine( p7.GetType() == p9.GetType() ); Console.WriteLine( p8.GetType() == p9.GetType() ); |
こういった型の扱いが実際のコーディング上どう影響するか、これは今後実例を蓄積して検証したいところ。
■匿名メソッド
こちらはC#2.0での追加フィーチャー。類似品として、C#3.0のラムダ式がある。
とりあえず個人的に一番使う場面が多そうなのは、ワーカースレッドでの処理完了をうけて画面に反映するようなシチュエーション。ご存じのとおり.NETでは、UIスレッド以外からの画面へのアクセスが禁止されているため、Control.Invokeという仕組みを使用することが義務付けられているのだが...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // 1.0的 public void ThreadCompleted() { this.Invoke( new MethodInvoker( this.UpdateView ); } private void UpdateView() { ・・・ } // 2.0的 private void ThreadCompleted() { this.Invoke( (MethodInvoker) delegate() { ・・・ } ); } |
とシンプルに書けるようになる。
ちなみに2.0の例の方で匿名メソッドをMethodInvokerにキャストしている点については、こちらに詳しいのでご一読の程を。
■コレクションイニシャライザ
平鍋さんが質問されてた内容にフォロー。
1 2 3 4 | List<Point> points = new { new Point( 0, 1 ), new Point( 2, 3 ), new Point( 4, 5 ) }; |
これは平鍋さんの指摘通り、ListのAddメソッドを順次コールしていることを確認。
■LINQ
SQL使ったことないから(゚⊿゚)シラネ...
と切って捨ててしまうには面白すぐる。
しかも驚くべきは、これだけの大がかりな文法のアップデートだというにも関わらず、ランタイムとしてはあくまで.NET Framework2.0互換だということ。つまり、コンパイラが内部的には見えないクラス・見えないメソッド・見えないデリゲートなどなどを生成し、工夫して組み合わせることでこれを実現しているということ。これこそがシンタックスシュガーということか。
・・・
うーん。
なんだかすっかりGEEK向けっぽい内容を書きなぐってしまったナリwww
TrackBack URL :
Comments (1)
むげんメモ
i花火
cornering force!
ウィンドチャイム
記事拝見しました! イベントでスピーカーとかしていただけないでしょうか?
コメント by 若い女性 — 2011/5/12 木曜日 @ 12:57:15