SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C# 1.1からC# 3.0まで~言語仕様の進化

C# 1.1からLINQまで

  • X ポスト
  • このエントリーをはてなブックマークに追加

C# 3.0登場!

 C# 3.0の新機能、ラムダ式を使うと匿名delegateを簡潔に表現できます。先ほどの匿名delegateをラムダ式で書き換えると以下のようになります。

匿名delegateのラムダ式による表現
static IEnumerable<Employee> GoldWatch(
                                  IEnumerable<Employee> employees) {
  return Filter(employees, 
                employee => employee.Years > 3 );
}

static IEnumerable<Employee> SalesForce(
                                  IEnumerable<Employee> employees) {
  return Filter(employees, 
                employee => employee.Department == "Sales" );
}

 GoldWatchSalesForceの利用者コードは、

GoldWatch(employees);
SalesForce(employees);

 のようになりますね。一方オブジェクト指向世界でのメソッド呼び出しは、

employees.GoldWatch();
employees.SalesForce();

 のように名詞.動詞()の形式となります。

 C# 3.0では「拡張メソッド」が新機能として追加されます。これによって既存のクラスに変更を加えることなく新たにメソッドを追加できます。

拡張メソッド
static IEnumerable<Employee> Filter(
               this IEnumerable<Employee> employees, Choose choose) {
  foreach ( Employee employee in employees ) {
    if ( choose(employee) ) {
      yield return employee;
    }
  }
}

static IEnumerable<Employee> GoldWatch(
                              this IEnumerable<Employee> employees) {
  return employees.Filter(employee => employee.Years>3);
}

static IEnumerable<Employee> SalesForce(
                              this IEnumerable<Employee> employees) {
  return employees.Filter(employee => employee.Department=="Sales");
}

 各staticメソッドの第1引数IEnumerable<Employee>に先立ってthisが付いてますね。これが拡張メソッドの印です。この形式でstaticメソッドを定義すれば、IEnumerable<Employee>にあたかもメソッドが追加されたかのように動作します。

利用者側コード
employees.GoldWatch();
employees.SalesForce();
employees.Filter(employee => employee.Department=="Sales");

 さらに、拡張メソッドGoldWatchSalesForceIEnumerable<Employee>を返すので、メソッドを数珠つなぎにできます。

金時計をもらえる営業部員
employees
    .GoldWatch()
    .SalesForce();

 さらなる汎用化を考えましょう。Employeeの集合であるIEnumerable<Employee>に拡張メソッドFilterを適用することで、あらゆる条件での選択操作が可能になりました。同様に顧客Customerや棚卸Inventryにも同様のFilterが欲しくなります。それらを個々に追加するのではなく拡張メソッドFilterを汎用化します。

汎用Filter
delegate bool Choose<T>(T t);

static IEnumerable<T> Filter<T>(this IEnumerable<T> items, 
                                Choose<T> choose) {
  foreach ( T item in items ) {
    if ( choose(item) ) {
      yield return item;
    }
  }
}

 今までEmployeeであったのをGenericパラメータTに書き換えました。こうすることで任意の型の集合に対しFilterを適用できます。

int配列から1または3を抜き出す
int [] a = new int [] {1,2,3,4,5};
a.Filter(i => i==1 || i==3);

まとめ

 Visual Studioには3つの.NET言語「VB.NET」「C#」「C++/CLI」が用意されています。それぞれのコンパイラはいずれも中間コード(IL)を生成するので実行時のパフォーマンスに大差はありません。プログラマは目的や好み/慣れに応じて言語を選ぶことができます。

 筆者は長いことC++世界に暮らしているので.NET言語としてはC++/CLIを選ぶことが多いのですが、C#の表現力はVB.NETやC++/CLIより一歩先を行っているように感じられます。本稿で紹介したyieldイテレータ、匿名delegate、そして近未来のラムダ式と拡張メソッドはC++屋を嫉妬させるエレガンスがありますね。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1540 2007/08/06 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング