C# 3.0をはじめよう!! C# 3.0ってなに? •.NET Framework 3.5と同時に出荷された C#の最新バージョン •以前のバージョンのC# 2.0から様々な 機能拡張が行われた。 •でも、ランタイムであるCLRのバージョン は変わっていない(コンパイラが変わった)。 どう変わったの? •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ •式ツリー などの新しい言語仕様、機能が追加された。 何故使うの? •開発効率が高いから (型推論、拡張メソッド、ラムダ式、etc) •.NET Framework 3.5 Client Profileの存在 → 従来の.NET Framework 2.0よりもインス トールサイズが小さい(197MB →26.5MB) •「ラムダ式」とか言いたいから どうすれば使える? •開発には「Visual Studio 2008」が必要 •無償版の「Visual C# 2008 Express」でも可 •他にもオープンソースの無償のIDE、 SharpDevelopなんてのもある •もちろんテキストエディタと コンパイラ(SDK)だけでも可 (^^ 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ 型推論 •変数宣言の時、型を省略できるようになった。 var s = “hello”; var i = 1; // 文字列型 // 数値型 •といっても、型が判断できない時は使えない。 var s; // コンパイルエラー •あくまでも、型の記述を省略できるだけなので var s = “hello”; S = 1; // コンパイルエラー 違う型の代入はできない(Variantとかではない)。 型推論 •クラスのフィールド宣言では使えません!! class Person { var firstName = “”; } // NG ローカルなスコープ(メソッドの中)でのみ使用可能。 •一番役に立つときは、やっぱりジェネリックの時かな var strCollection = new List<string>(); var strIntDict = new Dictionary<string, int>(); // こんなん二回も書いてられない var complex = new Dictionary<string, List<int>>(); 型推論 •デリゲートの時は省略できない(当たり前?)。 void DoSomething(string arg) { // do something } var action = DoSomething; // コンパイルエラー // デリゲートの型を指定する必要がある Action<string> action = DoSomething; •型推論の是非については、色々あるようですが 便利なので、気にせずがんがん使いましょう。 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ 自動プロパティ •C# 1.0~2.0の場合 using System; class Person { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { firstName = value; } } public string LastName { get { return lastName; } set { lastName = value; } } } 自動プロパティ •C# 3.0の場合 using System; class Person { public string FirstName { get; set; } public string LastName { get; set; } } get、setを記述するだけでそれに対応したフィールドが 自動生成されるようになった。 自動プロパティ •でも、getだけとか、setだけとかは無理。 必ず両方宣言する必要がある。 using System; class Person { public string FirstName { get; // NG } public string LastName { set; // NG } } 使えね~ 自動プロパティ •プロパティの初期値はコンストラクタで設定するしかない。 using System; class Person { public string FirstName { get; set; } public string LastName { get; set; } public Person() { this.FirstName = “名無しさん”; this.LastName = “”; } } 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ クラスイニシャライザ •クラスの初期化時にプロパティを設定できるようになった。 var person = new Person { FirstName = “Kouji”, LastName = “Yamaguchi” }; •昔はこんな↓コンストラクタを用意したよね。 public Person(string firstName, string lastName) { this.firstName = firstName; this.lastName = lastName; } これからは要らないかも!?って、んなわきゃない。 クラスイニシャライザ •必須のプロパティはコンストラクタの引数で、そうでないプ ロパティはクラスイニシャライザで設定するという使い分け。 using System; class Person { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public Person(string firstName, string lastName) { this.FirstName = firstName; this.LastName = lastName; } } 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ コレクションイニシャライザ •コレクション(配列、リスト)の初期化時に、その要素を 指定できるようになった。 var collection = new List<string>() { “John”, “Bob”, “Kitty” }; •配列の場合は型を省略することもできる。 // string型の配列 var array = new[] { “John”, “Bob”, “Kitty” }; コレクションイニシャライザ •ただし、要素の型は統一する必要がある。 // コンパイルエラー var array = new[] “John”, // 1, // true // }; { 文字列 数値 真偽値 •ディクショナリの初期化もできるでよ。 var dict = new Dictionary<string, int>() { { “John”, 20 }, { “Bob”, 18}, { “Kitty”, 12 } }; コレクションイニシャライザ •ちなみにコレクションイニシャライザで初期化できる クラスの条件は、 •System.Collections.IEnumerableを実装している •引数を一つ以上とるpublicなAddメソッドを実装している。 class FakeCollection : IEnumerable { public void Add(string value) { } IEnumerator IEnumerable.GetEnumerator() { yield break; } } var c = new FakeCollection { “Hoge”, “Fuga” }; これが成立する。 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ ラムダ式 •匿名メソッドってあったよね? Action<string> showMsg = delegate(string msg) { Console.WriteLine(msg); }; showMsg(“Hello, World”); 名前の無いメソッドを定義できるやつ。 •これが、こんな感じ↓で書けるようになった。 Action<string> showMsg = (msg) => Console.WriteLine(msg); showMsg(“Hello, World”); ラムダ式 •引数が一つの場合は、引数の括弧を省略できる。 Action<string> showMsg = msg => Console.WriteLine(msg); •引数が無い場合は、括弧だけでOK。 Action newLine = () => Console.WriteLine(); •処理が一行の場合は返り値を返すのにreturnはいらない。 Func<string> getMsg = () => “Hello, World”; •処理が複数行に渡る場合は、returnが必要になる。 Func<bool, string> getMsg = (value) => { return value == “Hoge”; }; ラムダ式 •すごい便利ですね!! var list = new List<string> { “John”, “Bob”, “Kitty” }; // 簡潔に記述できる。 list.ForEach(s => Console.WriteLine(s)); •もちろんクロージャとしても機能する。 var i = 0; Action increment = () => i++; // iがインクリメントされる。 increment() 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ 拡張メソッド •今までちょっとした便利機能はユーティリティクラス (staticなメソッドのみのクラス)を作って実装していた。 public static class StringUtils { // 指定した文字列の末尾の文字を取得するメソッド public static char Last(string value) { return value[value.Length - 1]; } } // e Console.WriteLine(StringUtils.Last(“Hoge”)); •これでも十分事は足りるけど、やっぱり本当はstringクラス に「Last」というメソッドが欲しい。 •そこで「拡張メソッド」ですよ。 拡張メソッド •thisキーワードを使って引数を定義すると・・・ public static class StringUtils { // 指定した文字列の末尾の文字を取得するメソッド public static char Last(this string value) { return value[value.Length - 1]; } } // e Console.WriteLine(“Hoge”.Last()); その引数の型のメソッドのように振る舞う事ができる。 •これは基本ライブラリのクラス(stringとかintとか)に メソッドを追加できる(ように見える)という事。 •ちなみに、拡張メソッドを定義するクラスは必ず staticにする必要がある。 拡張メソッド •便利な拡張メソッドとして、 最大値・最小値・平均値を求めるもの var nums = new[] { 1, 5, 2, 4, 10, 16, 30, 88 }; Console.WriteLine(“最大値: ” + nums.Max()); Console.WriteLine(“最小値: ” + nums.Min()); Console.WriteLine(“平均値: ” + nums.Average()); •オブジェクトの配列からディクショナリに変換するもの var objs = new[] { new Person(“John”, “Sykes”), new Person(“Yngwei”, “Malmsteen”), new Person(“Ritchie”, “Blackmore”) } var dict = objs.ToDictionary(o => o.FirstName, o => o.LastName); なんてのがある。 拡張メソッド •拡張メソッドはインターフェースにも定義できるので、 interface IHoge { } interface IFuga { } static class HogeExtension { public static void HelloHoge(this IHoge hoge) { } } static class FugaExtension { public static void HelloFuga(this IFuga fuga) { } } class HogeFuga : IHoge, IFuga { } var o = new HogeFuga(); o.HelloHoge(); o.HelloFuga(); これを利用すると多重継承、Mix-In(みたいなの) ができるようになる。 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ 匿名型 •名前の無い、匿名のクラスを定義(プロパティのみ)できる。 var obj = new { Row = 1, Column = 1, Value = “John” }; // Row = 1, Column = 1, Value = John Console.WriteLine( “Row = {0}, Column = {1}, Value = {2}”, // プロパティとしてアクセスできる。 obj.Row, obj.Column, obj.Value ); ただし、ローカルスコープ(メソッド内)でしか使えない。 •普通は一時的なデータの入れ物として使う。 今までディクショナリとかインナークラスとかでやってた事 が、これで少しだけ楽になる。 匿名型 •メソッドは定義できないけど、デリゲートのプロパティを 定義すればメソッドのように振る舞える。 var obj = new { DoSomething = (Action<string>)(msg => Console.WriteLine(msg)) }; obj.DoSomething(); なにかに使えるかも!? 匿名型 •例えば、↓こんなメソッドがあった場合 void DoSomething(IDictionary<string, object> keyValues) { } ディクショナリを初期化して渡すのって、結構だるいよね。 DoSomething(new Dictionary<string, object> { { “Product”, “Hoge” }, { “Price”, 100 } }); •これが匿名クラスで指定できたら、楽じゃね? DoSomething(new { Product = “Hoge”, Price = 100 }); 匿名型 •そんな時は、↓こんなクラスを作れば、 static class ObjectExtension { // object型をIDictionary<string, object>型に変換する。 public static IDictionary<string, object> ToDict(this object obj) { var tp = obj.GetType(); var props = tp.GetProperties( BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty ); return props.ToDictionary( p => p.Name, p => tp.InvokeMember( p.Name, BindingFlags.GetProperty, null, obj, null ) ); } } 匿名型 •↓こんな風に書けます。 DoSomething(new { Product = “Hoge”, Price = 100 }.ToDict()); 新機能の紹介 •型推論 •自動プロパティ •クラスイニシャライザ •コレクションイニシャライザ •ラムダ式 •拡張メソッド •匿名型 •LINQ LINQ •Language Integrated Query(統合言語クエリ) var array = new[] { “John”, “Bob”, “Sandy” }; var query = from o in array where o.Contains(“o”) select o; // John // Bob foreach(var o in query) Console.WriteLine(o); コレクション(リスト、配列)に対して、SQLのようなクエリ 言語で検索がかけられる。 LINQ •LINQの特徴は共通のクエリ言語を使って、 異なる種類のデータソースに対して検索が行えること。 例えば、 オブジェクトのコレクションに対して検索を行う •LINQ to Object SQLサーバーに対して検索を行う •LINQ to SQL (DLINQ) XMLドキュメントに対して検索を行う •LINQ to XML (XLINQ) が用意されている。 LINQ •LINQのコンパイル時の処理フロー var query = from o in array where o.Contains(“o”) select o; •演算子が対応する拡張メソッドに置き換わる。 var query = array.Where(o => o.Contains(“o”)).Select(o => o); •プロバイダ毎のクエリに変換される。 LINQ to Object LINQ to SQL LINQ to XML SQLクエリ XPathクエリ LINQ •LINQで使用できる演算子 from [要素] in [コレクション] where [条件] join [要素] in [コレクション] on [左辺] equals [右辺] group [要素] by [キー] order by [キー] [ascending|decending] select [要素] •LINQに対応している拡張メソッド Single, SingleOrDefault First, FirstOrDefault Last, LastOrDefault Count Take, TakeWhile Skip, SkipWhile Max, Min, Sum (DLINQのデモ) まとめ •C# 3.0の新しい機能は全てLINQの為にある。 •LINQに魅力を感じるかどうかがC# 3.0を導入するかどうか のポイントになる。 •LINQを使いこなせなければ、C# 3.0を使うメリットはあま り無いかも? •まぁ、何にせよ開発効率とおもしろさは間違いなく向上する ので、やって損は無い。 •とりあえず皆さんC# 3.0をはじめましょう \(^o^)/ (おわり)
© Copyright 2024 ExpyDoc