C#3.0の言語拡張
暗黙に型付けされたローカル変数
拡張メソッド
ラムダ式
オブジェクト初期化子および コレクション初期化子
匿名型
Linq クエリ式
パーシャルメソッド
Linq もどきを C#2.0で書いてみた
List<MyAccount> al = new List<MyAccount>();
al.Add(new MyAccount("hnaka", "553-0001", "大阪府"));
al.Add(new MyAccount("hkodama", "168-0064", "東京都"));
IEnumerable<MyAccount2> accounts =
EnumerableExtensions<MyAccount, MyAccount2>.Select(
EnumerableExtensions<MyAccount, MyAccount2>.Where
(al, delegate(MyAccount a) { return a.ZipCode == "168-0064"; }),
delegate(MyAccount a) { return new MyAccount2(a.Name, a.ZipCode); }
);
Console.WriteLine("C#2.0");
foreach (MyAccount2 account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
public class MyAccount
{
public MyAccount()
{
_name = "";
_zipcode = "";
_prefecture = "";
}
public MyAccount(string name, string zipcode, string prefecture)
{
_name = name;
_zipcode = zipcode;
_prefecture = prefecture;
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _zipcode;
public string ZipCode
{
get { return _zipcode; }
set { _zipcode = value; }
}
private string _prefecture;
public string Prefecture
{
get { return _prefecture; }
set { _prefecture = value; }
}
}
public class MyAccount2
{
public MyAccount2()
{
_name = "";
_zipcode = "";
}
public MyAccount2(string name, string zipcode)
{
_name = name;
_zipcode = zipcode;
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _zipcode;
public string ZipCode
{
get { return _zipcode; }
set { _zipcode = value; }
}
}
static class EnumerableExtensions<TS, TD>
{
public delegate TD SelectFunc(TS t);
public static IEnumerable<TD> Select
(IEnumerable<TS> e, SelectFunc f)
{
foreach (TS i in e)
{
yield return f(i);
}
}
public static IEnumerable<TS> Where(IEnumerable<TS> e, Predicate<TS> p)
{
foreach (TS i in e)
{
if (p(i)) yield return i;
}
}
}
これからどんどんC#3.0の言語拡張で簡単に書けていく。
暗黙に型付けされたローカル変数
var al = new List<MyAccount>();
al.Add(new MyAccount("hnaka", "553-0001", "大阪府"));
al.Add(new MyAccount("hkodama", "168-0064", "東京都"));
var accounts =
EnumerableExtensions<MyAccount, MyAccount2>.Select(
EnumerableExtensions<MyAccount, MyAccount2>.Where
(al, delegate(MyAccount a) { return a.ZipCode == "168-0064"; }),
delegate(MyAccount a) { return new MyAccount2(a.Name, a.ZipCode); }
);
Console.WriteLine("C#3.0 暗黙に型付けされたローカル変数");
foreach (var account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
拡張メソッド
var al = new List<MyAccount>();
al.Add(new MyAccount("hnaka", "553-0001", "大阪府"));
al.Add(new MyAccount("hkodama", "168-0064", "東京都"));
var accounts = al
.Where(delegate(MyAccount a) { return a.ZipCode == "168-0064"; })
.Select(delegate(MyAccount a) { return new MyAccount2(a.Name, a.ZipCode); });
Console.WriteLine("C#3.0 拡張メソッド");
foreach (var account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
static class EnumerableExtension
{
public delegate TD SelectFunc<TS, TD>(TS t);
public static IEnumerable<TD> Select<TS, TD> (this IEnumerable<TS> e,SelectFunc<TS, TD> f)
{
foreach (TS i in e)
{
yield return f(i);
}
}
public static IEnumerable<TS> Where<TS>(this IEnumerable<TS> e, Predicate<TS> p)
{
foreach (TS i in e)
{
if (p(i)) yield return i;
}
}
}
static class EnumerableExtensions<TS, TD> クラスの置き換え。
EnumerableExtensionはクラスライブラリに含まれるのでコーディング不要になる。
ラムダ式
var al = new List<MyAccount>();
al.Add(new MyAccount("hnaka", "553-0001", "大阪府"));
al.Add(new MyAccount("hkodama", "168-0064", "東京都"));
var accounts = al
.Where(a => a.ZipCode == "168-0064")
.Select(a => new MyAccount2(a.Name, a.ZipCode));
Console.WriteLine("C#3.0 ラムダ式");
foreach (var account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
オブジェクト初期化子および コレクション初期化子
var al = new List<MyAccount> {
new MyAccount{Name="hnaka",ZipCode="553-0001",Prefecture="大阪府"},
new MyAccount{Name="hkodama",ZipCode="168-0064",Prefecture="東京都"}
};
var accounts = al
.Where(a => a.ZipCode == "168-0064")
.Select(a => new MyAccount2 { Name = a.Name, ZipCode = a.ZipCode });
Console.WriteLine("C#3.0 オブジェクト初期化子および コレクション初期化子");
foreach (var account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
匿名型
var al = new [] {
new {Name="hnaka",ZipCode="553-0001",Prefecture="大阪府"},
new {Name="hkodama",ZipCode="168-0064",Prefecture="東京都"}
};
var accounts = al
.Where(a => a.ZipCode == "168-0064")
.Select(a => new { Name = a.Name, ZipCode = a.ZipCode });
Console.WriteLine("C#3.0 匿名型");
foreach (var account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
匿名型で public class MyAccount と MyAccount2 が不要になる。
Linq クエリ式
var al = new[] {
new {Name="hnaka",ZipCode="553-0001",Prefecture="大阪府"},
new {Name="hkodama",ZipCode="168-0064",Prefecture="東京都"}
};
var accounts = from a in al
where a.ZipCode == "168-0064"
select new { Name = a.Name, ZipCode = a.ZipCode };
Console.WriteLine("C#3.0 クエリ式");
foreach (var account in accounts)
{
Console.WriteLine(account.Name + "(" + account.ZipCode + ")");
}
パーシャルメソッド
Linq でカスタムプロパティ検証や挿入・更新・削除メソッドの検証に使用する
public partial class DataClasses1DataContext
{
public partial class Account
{
partial void OnZipCodeChanging(string value)
{
Regex zipcheck = new Regex(@“^[0-9]{3}-[0-9]{4}$”);
if (!zipcheck.IsMatch(value)) throw new Excepton(“郵便番号エラー”);
}
}
}