連載:[完全版]究極のC#プログラミングChapter14 拡張メソッド川俣 晶2010/03/01 |
|
同書籍は、もともと本フォーラムにて連載していた『C# 2.0入門』、『C# 3.0入門』の記事を整理統合し、加筆、修正されたものです。 手元でまとめて読みたい方は、ぜひ書店などにてお買い求めください。 【注意】本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。 |
14.1 C# 2.0プログラマーの悲劇
本題に入る前に、よくあるトラブルの事例を見てみよう。C# 3.0を使い始めたC# 2.0プログラマーの話だ。
C# 2.0プログラマーのA君が、Visual Studio 2005を用いて次のリスト14.1のようなコードを書いたとしよう。整数配列がすべて奇数であるかを確認し、その条件が成立していないときはその旨を出力する内容である。
| |
リスト14.1 C# 2.0によるコード−その1 |
しかし、foreach文でループするのはあまりエレガントではない。そこで、ある条件を満たさない項目が存在することを示すだけなら、条件に当てはまらないものを探せばよいことに気づいた。
最初に思い付いたのはArray.Findメソッドを使う方法だ。しかし、Array.Findメソッドは項目が見つからないときに、その型の既定の値を返す。つまり、int型なら0を返す。しかし、これでは、0を発見したのか、発見できずに0になったのかわからない。
結局、A君は、値ではなく、インデックスを返すFindIndexメソッドを使ってリスト14.1を書き直した(リスト14.2参照)。
| |
リスト14.2 C# 2.0によるコード−その2 |
しかし、このコードにもA君は不満を持っていた。本来「すべての値が奇数である」ことを確認するプログラムだが、実際にソースコードに書かれているのは、「偶数の値を探す」処理だからだ。
さて、A君は、C# 3.0で配列(Arrayクラス)に新しいメソッドAllが追加されたことを知った。Allメソッドとは、「シーケンスのすべての要素が条件を満たしているかどうかを判断」するものであり、まさに「すべての値が奇数である」という意図を実現するにふさわしいメソッドに思えた。
そこで、A君は、次のリスト14.3のプログラムをVisual Studio 2008で書いて、Allメソッドの挙動を確認した。
| |
リスト14.3 C# 3.0でAllメソッドを試す |
これを見て、A君は「まさに求めていたメソッドだ」と確信した。そして、さっそくVisual Studio 2005で開発してきたリスト14.1のコードをVisual Studio 2008で読み込み、プロジェクトのプロパティで「対象のフレームワーク」を.NET Framework 3.5に変更した。これでAllメソッドが使用できるはずである。
A君はソースコードの変更に着手した。しかし、A君はすぐにおかしなことに気づく。配列primesに対してIntelliSense(インテリセンス)を機能させても、Allメソッドがリストされないのだ。A君はおかしいと思いつつ、手動でリスト14.4のように書き換えた。ところがこれはコンパイルエラーとなる。
| |
リスト14.4 コンパイル不能となったリスト14.1からの改良コード |
このエラーメッセージを見て、A君は狼狽した。
「『'System.Array' に 'All' の定義が含まれていない』だって? そんなバカな。だって、さっき書いたテスト用のソース(リスト14.3)はOKだったし、対象となるフレームワークのバージョンも正しく切り替えたはずだ。配列に対するメソッド呼び出しは、System.Arrayクラスのメソッドが使われるはずじゃないのか!?」
これに対する答えは、少々ややこしい。
まず、A君の次の認識は正しい。
- Allメソッドは.NET Framework 3.5で拡張されたメソッドである
- Allメソッドを使用するには、対象のフレームワークに.NET Framework 3.5を指定しなければならない(.NET Framework 2.0では使えない)
- Allメソッドは、配列(System.Arrayクラス)に対して拡張されたメソッドである
しかし、次の認識は正しくない。
- AllメソッドはSystem.Arrayクラスのメソッドである
C# 3.0には、既存のクラスを変更せずに、メソッドを追加する機能が付加されている。Allメソッドは、この機能を用いて配列に対して拡張されたメソッドである。.NET Framework 3.5になってSystem.Arrayクラスそのものにメソッドが増えたわけではない。しかし、呼び出し可能なメソッドは増えている。このようなメソッドを「拡張メソッド」(Extension Methods)と呼ぶ。
INDEX | ||
[完全版]究極のC#プログラミング | ||
Chapter14 拡張メソッド | ||
1.14.1 C# 2.0プログラマーの悲劇 | ||
2.14.2 Allメソッドを利用するのに必要な記述 | ||
3.14.3 拡張メソッドの概要 | ||
4.14.4 スイッチなしで機能する例 | ||
5.14.5 sealedクラスを拡張する | ||
6.14.6 拡張メソッドはオブジェクト内部に手出しできない | ||
7.14.7 拡張メソッドはオブジェクトの振る舞いを変更できない | ||
8.14.8 拡張メソッドが安全である理由 | ||
9.14.9 メソッド呼び出しと型の関係 | ||
10.14.10 thisの正体 | ||
11.14.11 拡張メソッドを使用すべきとき | ||
12.14.12 コレクションに拡張されるメソッド | ||
13.14.13 なぜ「using System.Linq;」なのか?/練習問題 | ||
「[完全版]究極のC#プログラミング」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|