記事

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(“郵便番号エラー”);
  }
 }
}

ダウンロード
 TitleOwnerCategoryModified DateSize (Kb)