C#3.0ではLINQが追加されました。
それに伴い、LINQの可読性を上げるための機能もC#3.0には追加されています。
目次
暗黙的に型指定されたローカル変数
- 明示的に型を指定することなく、ローカル変数を宣言することができようになった
- varキーワードを使用する
- コンパイル時に適切な型が割り当たる
- フィールドでは使用不可
- VB6のVariantと異なり、変数宣言時に初期化が必要
- VB6のVariantと異なり、型変換は出来ない
- 型名の冗長さを省く場合や、匿名型を使用した場合に用いる
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の後ろの型が省略可能となった
- コンパイル時に{} の中身から適切な型が割り当たる
- 複数の型が含まれる場合、コンパイルエラーとなる
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}
};
}
}
オブジェクト初期化子
- オブジェクトの初期化が簡潔に記述可能となった
- 中カッコ{ }内で初期化を行う
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; }
}
}
コレクション初期化子
- コレクションの初期化が簡潔に記述可能となった
- 中カッコ{ }内で初期化を行う
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 を用意する
class Person
{
public string Name { get; set; }
}
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旬で使用される機能
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("同じ型");
}
}
}
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文で指定すると有効となる
//拡張メソッドを含む名前空間を指定すると有効となる
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);
}
}
}
- 拡張メソッドとインスタンスメソッドが重複した場合、インスタンスメソッドが優先される
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)
{
}
}
}
ラムダ式
- ラムダ式は、式とステートメントを含めることができる匿名関数であり、デリゲート型または式ツリー型を作成するために使用される
- 演算子 => を使用する
- 演算子 => の左辺で入力パラメータを指定し、右辺で式、またはステートメントを指定する
デリゲート型を作成する場合
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;
}
}
}
式ツリー型を作成する場合
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の使用がクエリに対し可能となった
- 扱えるデータは主に以下となる
オブジェクト(LINQ to Objects)
XML(LINQ to XML)
ADO.NETのDataSet(LINQ to DataSet)
SQLサーバのデータベース(LINQ to SQL)
ADO.NET Entity Frameworkから提供される概念エンティティ(LINQ to Entities)
C$3.0でのLINQ to Objectsの例
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で同様のコードを記述した場合
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; }
}
}
最終更新:2010年02月12日 15:35