「C#3.0」の編集履歴(バックアップ)一覧はこちら

C#3.0 - (2010/02/12 (金) 15:35:31) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

C#3.0ではLINQが追加されました。 それに伴い、LINQの可読性を上げるための機能もC#3.0には追加されています。 &bold(){目次} #contents() *暗黙的に型指定されたローカル変数 ・明示的に型を指定することなく、ローカル変数を宣言することができようになった ・varキーワードを使用する ・コンパイル時に適切な型が割り当たる ・フィールドでは使用不可 ・VB6のVariantと異なり、変数宣言時に初期化が必要 ・VB6のVariantと異なり、型変換は出来ない ・型名の冗長さを省く場合や、匿名型を使用した場合に用いる #highlight(csharp){{ class Program {   //フィールドでは使用不可   //var a = 123;   static void Main(string[] args)   {     var i = 123;     var d = 12.3M;     var str = "abc";     var dt = DateTime.Now;     //変数宣言時に初期化が必要     //var b;     //型変換は出来ない     //i = "abc";     //型の冗長さを省く場合     var obj1 = new Myclass();     //匿名型を使用した場合     var obj2 = new { Name = "abc" };   } } class Myclass { } }} *暗黙的に型指定された配列 ・newで配列を作成する際、newの後ろの型が省略可能となった ・コンパイル時に{} の中身から適切な型が割り当たる ・複数の型が含まれる場合、コンパイルエラーとなる #highlight(csharp){{ class Program {   static void Main(string[] args)   {     var i = new[] { 1, 2, 3, };     var d = new[] { 1.1, 2.2, 3.3 };     var str = new[] { "abc", "def", "ghi" };     //複数の型が含まれる場合、コンパイルエラーとなる     //var obj = new[] { 1, "abc", 2 };     //匿名型を使用した場合     var persons = new[]{       new{Name = "Taro",Age = 20},       new{Name = "Jiro",Age = 18}     };   } } }} *オブジェクト初期化子 ・オブジェクトの初期化が簡潔に記述可能となった ・中カッコ{ }内で初期化を行う #highlight(csharp){{ class Program {   static void Main(string[] args)   {     //C#3.0の場合     var person3 = new Person { Age = 20, Name = "Taro" };     //C#2.0の場合     Person person2 = new Person();     person2.Age = 20;     person2.Name = "Taro";   } } class Person { public string m_name; public int m_age; public string Name { get { return m_name; } set { m_name = value; } } public int Age { get { return m_age; } set { m_age = value; } } } }} *コレクション初期化子 ・コレクションの初期化が簡潔に記述可能となった ・中カッコ{ }内で初期化を行う #highlight(csharp){{ class Program {   static void Main(string[] args)   {     //C#3.0の場合     var list3 = new List<int> { 1, 2, 3 };     var dic3 = new Dictionary<string, int>() { { "a", 1 }, { "b", 2 }, { "c", 3 } };     //C#2.0の場合     List<int> list2 = new List<int>();     list2.Add(1);     list2.Add(2);     list2.Add(3);     Dictionary<string, int> dic2 = new Dictionary<string, int>();     dic2.Add("a", 1);     dic2.Add("b", 2);     dic2.Add("c", 3);   } } }} *自動プロパティ ・プロパティの記述が簡潔に記述可能となった ・コンパイル時、従来のプロパティが自動的に生成される ・get、set 両方を記述する必要がある ・読み取り専用のプロパティを作成するには、プライベートな set を用意する #highlight(csharp){{ class Person {   public string Name { get; set; } } }} 上記クラスをコンパイルし[[Reflector for.NET>http://www.red-gate.com/products/reflector/]]を使用し生成ファイルを見ると、以下のフィールド、プロパティが自動生成されていることがわかる #highlight(csharp){{ internal class Person {   // Fields   private string <Name>k__BackingField;   // Properties   public string Name   {     get     {       return this.<Name>k__BackingField;     }     set     {       this.<Name>k__BackingField = value;     }   } } }} *匿名型 ・クラスを別途定義せずにオブジェクト生成が可能となった ・匿名型は、プログラマからはクラス名が不明のためvarキーワードを使用する ・コンパイル時、クラスが自動的に作成される ・同じ名前、同じ型、同じ並び順のプロパティを持つ匿名型は同一のクラスとなる ・主にLINQのselect旬で使用される機能 #highlight(csharp){{ class Program {   static void Main(string[] args)   {     var obj1 = new { Name = "Taro", Age = 20 };     var obj2 = new { Name = "Jiro", Age = 18 };     if (obj1.GetType() == obj2.GetType())     {       Console.WriteLine("同じ型");     }   } } }} 上記クラスをコンパイルし[[Reflector for.NET>http://www.red-gate.com/products/reflector/]]を使用し生成ファイルを見ると、以下のクラスが自動生成されていることがわかる #highlight(csharp){{ internal sealed class <>f__AnonymousType0<<Name>j__TPar, <Age>j__TPar> {   // Fields   private readonly <Age>j__TPar <Age>i__Field;   private readonly <Name>j__TPar <Name>i__Field;   // Methods   public <>f__AnonymousType0(<Name>j__TPar Name, <Age>j__TPar Age)   {     this.<Name>i__Field = Name;     this.<Age>i__Field = Age;   }   // Properties   public <Age>j__TPar Age   {     get     {       return this.<Age>i__Field;     }   }   public <Name>j__TPar Name   {     get     {       return this.<Name>i__Field;     }   } } }} *拡張メソッド ・既存クラスを継承することなく、既存クラスにインスタンスメソッドを追加出来る機能 ・非ジェネリックのstaticクラス内にてstaticメソッドで宣言する必要がある ・this修飾子にて、拡張メソッドを追加する型を指定する ・拡張メソッドを含む名前空間をusing文で指定すると有効となる #highlight(csharp){{ //拡張メソッドを含む名前空間を指定すると有効となる using B; namespace A { class Program { static void Main(string[] args) { //拡張メソッドの呼び出し "abc".Print(); //通常のstaticメソッドとしての呼び出しも可能 StingExtensions.Print("abc"); } } } namespace B { static class StingExtensions { //拡張メソッド public static void Print(this string str) { System.Console.WriteLine(str); } } } }} ・拡張メソッドとインスタンスメソッドが重複した場合、インスタンスメソッドが優先される #highlight(csharp){{ namespace A { class Program { static void Main(string[] args) { X obj = new X(); //クラスXのMethod()が呼ばれる obj.Method(); } } class X { public void Method() { } } static class Y { public static void Method(this X x) { } } } }} *ラムダ式 ・ラムダ式は、式とステートメントを含めることができる匿名関数であり、デリゲート型または式ツリー型を作成するために使用される ・演算子 => を使用する ・演算子 => の左辺で入力パラメータを指定し、右辺で式、またはステートメントを指定する デリゲート型を作成する場合 #highlight(csharp){{ namespace LambdaExpression { delegate int D(int x, int y); class Program { static void Main(string[] args) { //C#1.0 //外部メソッドを用意する必要があった D d1 = new D(Add); //C#2.0 //匿名メソッド使用 { }内に直接記述可能となった D d2 = delegate(int x, int y) { return x + y; }; //C#3.0 //ラムダ式使用 匿名メソッドより簡略し記述可能となった       D d3 = (x, y) => x + y; //以下の記述も可 //D d3 = (int x, int y) => { return x + y; }; //D d3 = (int x, int y) => return x + y; //D d3 = (int x, int y) => x + y; Console.WriteLine(d1(1, 2)); Console.WriteLine(d2(1, 2)); Console.WriteLine(d3(1, 2)); } static int Add(int x, int y) { return x + y; } } } }} 式ツリー型を作成する場合 #highlight(csharp){{ using System.Linq.Expressions; namespace LambdaExpression { class Program { static void Main(string[] args) { //ラムダ式をデリゲートに代入すると匿名メソッドとなる Func<int, int, int> f = (x, y) => x + y; Console.WriteLine(f(1, 2)); //ラムダ式をExpression式に代入すると式ツリー型となる Expression<Func<int, int, int>> e = (x, y) => x + y; var bin = (BinaryExpression)e.Body; var p1 = (ParameterExpression)bin.Left; var p2 = (ParameterExpression)bin.Right; Console.WriteLine(bin); Console.WriteLine(p1); Console.WriteLine(p2); } } } }} *LINQ ・LINQは、Language Integrated Query(統合言語クエリ)の略 ・LINQにより、異なる種類のデータに対して統一したクエリ構文でアクセスが可能となった ・LINQにより、C#、VB.NETのコード内にクエリを記述することが出来る ・LINQにより、コンパイル時の型チェック、IntelliSenseの使用がクエリに対し可能となった ・扱えるデータは主に以下となる&br()オブジェクト(LINQ to Objects)&br()XML(LINQ to XML)&br()ADO.NETのDataSet(LINQ to DataSet)&br()SQLサーバのデータベース(LINQ to SQL)&br()ADO.NET Entity Frameworkから提供される概念エンティティ(LINQ to Entities) C$3.0でのLINQ to Objectsの例 #highlight(csharp){{ class Program { static void Main(string[] args) { var persons = new[] { new { Name="Taro", Age=20 }, new { Name="Jiro", Age=18 } }; var adults = from person in persons where person.Age >= 20 select new { person.Name, person.Age }; foreach (var adult in adults) { Console.WriteLine(adult.Name + "," + adult.Age); } } } }} C#2.0で同様のコードを記述した場合 #highlight(csharp){{ class Program { static void Main(string[] args) { List<Person> persons = new List<Person>(); persons.Add(new Person("Taro", 20)); persons.Add(new Person("Jiro", 18)); List<Person> adults = new List<Person>(); foreach (Person person in persons) { if (person.Age >= 20) { Person adult = new Person(person.Name, person.Age); adults.Add(adult); } } foreach (Person adult in adults) { Console.WriteLine(adult.Name + "," + adult.Age); } } } class Person { public string m_name; public int m_age; public Person(string name, int age) { m_name = name; m_age = age; } public string Name { get { return m_name; } set { m_name = value; } } public int Age { get { return m_age; } set { m_age = value; } } } }} 参考 C# 3.0 の概要 [[http://www.microsoft.com/japan/msdn/net/bb308966.aspx>http://www.microsoft.com/japan/msdn/net/bb308966.aspx]]
C#3.0ではLINQが追加されました。 それに伴い、LINQの可読性を上げるための機能もC#3.0には追加されています。 &bold(){目次} #contents() *暗黙的に型指定されたローカル変数 ・明示的に型を指定することなく、ローカル変数を宣言することができようになった ・varキーワードを使用する ・コンパイル時に適切な型が割り当たる ・フィールドでは使用不可 ・VB6のVariantと異なり、変数宣言時に初期化が必要 ・VB6のVariantと異なり、型変換は出来ない ・型名の冗長さを省く場合や、匿名型を使用した場合に用いる #highlight(csharp){{ class Program {   //フィールドでは使用不可   //var a = 123;   static void Main(string[] args)   {     var i = 123;     var d = 12.3M;     var str = "abc";     var dt = DateTime.Now;     //変数宣言時に初期化が必要     //var b;     //型変換は出来ない     //i = "abc";     //型の冗長さを省く場合     var obj1 = new Myclass();     //匿名型を使用した場合     var obj2 = new { Name = "abc" };   } } class Myclass { } }} *暗黙的に型指定された配列 ・newで配列を作成する際、newの後ろの型が省略可能となった ・コンパイル時に{} の中身から適切な型が割り当たる ・複数の型が含まれる場合、コンパイルエラーとなる #highlight(csharp){{ class Program {   static void Main(string[] args)   {     var i = new[] { 1, 2, 3, };     var d = new[] { 1.1, 2.2, 3.3 };     var str = new[] { "abc", "def", "ghi" };     //複数の型が含まれる場合、コンパイルエラーとなる     //var obj = new[] { 1, "abc", 2 };     //匿名型を使用した場合     var persons = new[]{       new{Name = "Taro",Age = 20},       new{Name = "Jiro",Age = 18}     };   } } }} *オブジェクト初期化子 ・オブジェクトの初期化が簡潔に記述可能となった ・中カッコ{ }内で初期化を行う #highlight(csharp){{ class Program {   static void Main(string[] args)   {     //C#3.0の場合     var person3 = new Person { Age = 20, Name = "Taro" };     //C#2.0の場合     Person person2 = new Person();     person2.Age = 20;     person2.Name = "Taro";   } } class Person { public string m_name; public int m_age; public string Name { get { return m_name; } set { m_name = value; } } public int Age { get { return m_age; } set { m_age = value; } } } }} *コレクション初期化子 ・コレクションの初期化が簡潔に記述可能となった ・中カッコ{ }内で初期化を行う #highlight(csharp){{ class Program {   static void Main(string[] args)   {     //C#3.0の場合     var list3 = new List<int> { 1, 2, 3 };     var dic3 = new Dictionary<string, int>() { { "a", 1 }, { "b", 2 }, { "c", 3 } };     //C#2.0の場合     List<int> list2 = new List<int>();     list2.Add(1);     list2.Add(2);     list2.Add(3);     Dictionary<string, int> dic2 = new Dictionary<string, int>();     dic2.Add("a", 1);     dic2.Add("b", 2);     dic2.Add("c", 3);   } } }} *自動プロパティ ・プロパティの記述が簡潔に記述可能となった ・コンパイル時、従来のプロパティが自動的に生成される ・get、set 両方を記述する必要がある ・読み取り専用のプロパティを作成するには、プライベートな set を用意する #highlight(csharp){{ class Person {   public string Name { get; set; } } }} 上記クラスをコンパイルし[[Reflector for.NET>http://www.red-gate.com/products/reflector/]]を使用し生成ファイルを見ると、以下のフィールド、プロパティが自動生成されていることがわかる #highlight(csharp){{ internal class Person {   // Fields   private string <Name>k__BackingField;   // Properties   public string Name   {     get     {       return this.<Name>k__BackingField;     }     set     {       this.<Name>k__BackingField = value;     }   } } }} *匿名型 ・クラスを別途定義せずにオブジェクト生成が可能となった ・匿名型は、プログラマからはクラス名が不明のためvarキーワードを使用する ・コンパイル時、クラスが自動的に作成される ・同じ名前、同じ型、同じ並び順のプロパティを持つ匿名型は同一のクラスとなる ・主にLINQのselect旬で使用される機能 #highlight(csharp){{ class Program {   static void Main(string[] args)   {     var obj1 = new { Name = "Taro", Age = 20 };     var obj2 = new { Name = "Jiro", Age = 18 };     if (obj1.GetType() == obj2.GetType())     {       Console.WriteLine("同じ型");     }   } } }} 上記クラスをコンパイルし[[Reflector for.NET>http://www.red-gate.com/products/reflector/]]を使用し生成ファイルを見ると、以下のクラスが自動生成されていることがわかる #highlight(csharp){{ internal sealed class <>f__AnonymousType0<<Name>j__TPar, <Age>j__TPar> {   // Fields   private readonly <Age>j__TPar <Age>i__Field;   private readonly <Name>j__TPar <Name>i__Field;   // Methods   public <>f__AnonymousType0(<Name>j__TPar Name, <Age>j__TPar Age)   {     this.<Name>i__Field = Name;     this.<Age>i__Field = Age;   }   // Properties   public <Age>j__TPar Age   {     get     {       return this.<Age>i__Field;     }   }   public <Name>j__TPar Name   {     get     {       return this.<Name>i__Field;     }   } } }} *拡張メソッド ・既存クラスを継承することなく、既存クラスにインスタンスメソッドを追加出来る機能 ・非ジェネリックのstaticクラス内にてstaticメソッドで宣言する必要がある ・this[[修飾子]]にて、拡張メソッドを追加する型を指定する ・拡張メソッドを含む[[名前空間]]をusing文で指定すると有効となる #highlight(csharp){{ //拡張メソッドを含む名前空間を指定すると有効となる using B; namespace A { class Program { static void Main(string[] args) { //拡張メソッドの呼び出し "abc".Print(); //通常のstaticメソッドとしての呼び出しも可能 StingExtensions.Print("abc"); } } } namespace B { static class StingExtensions { //拡張メソッド public static void Print(this string str) { System.Console.WriteLine(str); } } } }} ・拡張メソッドとインスタンスメソッドが重複した場合、インスタンスメソッドが優先される #highlight(csharp){{ namespace A { class Program { static void Main(string[] args) { X obj = new X(); //クラスXのMethod()が呼ばれる obj.Method(); } } class X { public void Method() { } } static class Y { public static void Method(this X x) { } } } }} *ラムダ式 ・ラムダ式は、式とステートメントを含めることができる匿名関数であり、デリゲート型または式ツリー型を作成するために使用される ・[[演算子]] => を使用する ・演算子 => の左辺で入力パラメータを指定し、右辺で式、またはステートメントを指定する デリゲート型を作成する場合 #highlight(csharp){{ namespace LambdaExpression { delegate int D(int x, int y); class Program { static void Main(string[] args) { //C#1.0 //外部メソッドを用意する必要があった D d1 = new D(Add); //C#2.0 //匿名メソッド使用 { }内に直接記述可能となった D d2 = delegate(int x, int y) { return x + y; }; //C#3.0 //ラムダ式使用 匿名メソッドより簡略し記述可能となった       D d3 = (x, y) => x + y; //以下の記述も可 //D d3 = (int x, int y) => { return x + y; }; //D d3 = (int x, int y) => return x + y; //D d3 = (int x, int y) => x + y; Console.WriteLine(d1(1, 2)); Console.WriteLine(d2(1, 2)); Console.WriteLine(d3(1, 2)); } static int Add(int x, int y) { return x + y; } } } }} 式ツリー型を作成する場合 #highlight(csharp){{ using System.Linq.Expressions; namespace LambdaExpression { class Program { static void Main(string[] args) { //ラムダ式をデリゲートに代入すると匿名メソッドとなる Func<int, int, int> f = (x, y) => x + y; Console.WriteLine(f(1, 2)); //ラムダ式をExpression式に代入すると式ツリー型となる Expression<Func<int, int, int>> e = (x, y) => x + y; var bin = (BinaryExpression)e.Body; var p1 = (ParameterExpression)bin.Left; var p2 = (ParameterExpression)bin.Right; Console.WriteLine(bin); Console.WriteLine(p1); Console.WriteLine(p2); } } } }} *LINQ ・LINQは、Language Integrated Query(統合言語クエリ)の略 ・LINQにより、異なる種類のデータに対して統一したクエリ構文でアクセスが可能となった ・LINQにより、C#、VB.NETのコード内にクエリを記述することが出来る ・LINQにより、コンパイル時の型チェック、IntelliSenseの使用がクエリに対し可能となった ・扱えるデータは主に以下となる&br()オブジェクト(LINQ to Objects)&br()XML(LINQ to XML)&br()ADO.NETのDataSet(LINQ to DataSet)&br()SQLサーバのデータベース(LINQ to SQL)&br()ADO.NET Entity Frameworkから提供される概念エンティティ(LINQ to Entities) C$3.0でのLINQ to Objectsの例 #highlight(csharp){{ class Program { static void Main(string[] args) { var persons = new[] { new { Name="Taro", Age=20 }, new { Name="Jiro", Age=18 } }; var adults = from person in persons where person.Age >= 20 select new { person.Name, person.Age }; foreach (var adult in adults) { Console.WriteLine(adult.Name + "," + adult.Age); } } } }} C#2.0で同様のコードを記述した場合 #highlight(csharp){{ class Program { static void Main(string[] args) { List<Person> persons = new List<Person>(); persons.Add(new Person("Taro", 20)); persons.Add(new Person("Jiro", 18)); List<Person> adults = new List<Person>(); foreach (Person person in persons) { if (person.Age >= 20) { Person adult = new Person(person.Name, person.Age); adults.Add(adult); } } foreach (Person adult in adults) { Console.WriteLine(adult.Name + "," + adult.Age); } } } class Person { public string m_name; public int m_age; public Person(string name, int age) { m_name = name; m_age = age; } public string Name { get { return m_name; } set { m_name = value; } } public int Age { get { return m_age; } set { m_age = value; } } } }} 参考 C# 3.0 の概要 [[http://www.microsoft.com/japan/msdn/net/bb308966.aspx>http://www.microsoft.com/japan/msdn/net/bb308966.aspx]]

表示オプション

横に並べて表示:
変化行の前後のみ表示: