今回は、型パラメータを持つ拡張メソッドを extension ブロックで書き直す方法を見ていきます。題材は、コレクションが空かどうかを判定する IsEmpty という拡張メソッドです。
書き換え前のコード
書き換え前は、従来どおりの static メソッドとして定義された拡張メソッドです。第一引数に this を付けた IEnumerable<T> を受け取り、型パラメータ T は IsEmpty メソッド自身が持っています。
図:書き換え前の IsEmpty<T> 拡張メソッド。this IEnumerable<T> list を第一引数に取る static メソッドとして定義されている。
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list == null) return true;
return !list.Any();
}
extension ブロックを追加する
まず、メソッドの上に extension() と書き、丸カッコを付けます。この丸カッコの中に、これまで拡張メソッドの第一引数(this を除いた部分)に書いていた型を移していきます。
図:メソッドの上に extension() を追加したところ。
続けて、中カッコ { } を書いてブロックにし、IsEmpty メソッドの第一引数だった IEnumerable<T> list を extension の丸カッコの中に移動します。
図:extension(IEnumerable<T> list) { … } という形にブロック化したところ。IsEmpty メソッドはこのブロックの中に含まれる。
static と this 引数を取り除く
拡張メソッド側の第一引数はすでに extension ブロックのほうに吸収されているため、IsEmpty メソッドの static 修飾子と、this を含む第一引数(this IEnumerable<T> list)はどちらも不要になります。まず static を消します。
図:IsEmpty メソッドから static を削除したところ。
続けて、第一引数の this IEnumerable<T> list もまとめて削除します。これで IsEmpty は引数を取らない、普通のインスタンスメソッドになります。
図:this IEnumerable<T> list を削除し、IsEmpty<T>() という引数なしのメソッドになったところ。
型パラメータを extension 側に移動する
最後に型パラメータです。今は IsEmpty<T> という形で、IsEmpty メソッド自身が型パラメータ T を持っていますが、この T を extension の後ろ(extension<T>)に書き直します。そうすると、IsEmpty 側の <T> はもう不要になるので削除します。
図:型パラメータ T を extension<T>(IEnumerable<T> list) の形で extension 側に移したところ。IsEmpty<T>() の <T> はまだ残っている。
図:IsEmpty 側の <T> も削除し、書き換えが完了した状態。extension<T>(IEnumerable<T> list) ブロックの中に、引数なしのインスタンスメソッド IsEmpty() がある。
extension<T>(IEnumerable<T> list)
{
public bool IsEmpty()
{
if (list == null) return true;
return !list.Any();
}
}
呼び出し側は変更不要
extension ブロックで書き直しても、呼び出し側のコードはこれまでとまったく同じです。listA.IsEmpty() のように、今まで通り呼び出すことができます。
図:呼び出し側のコード。listA.IsEmpty() のように変更前と同じ書き方で呼び出せる。
実際にデバッグ実行して確認すると、要素を1件追加した listA では retA が false、空のままの listB・listC では retB・retC がともに true となり、書き換え前と同じ結果が得られていることが分かります。
図:ウォッチウィンドウでの実行結果。retA は false、retB と retC は true。
このように、型パラメータを持つ拡張メソッドを extension ブロックで書く場合は、型パラメータを extension の後ろに、引数を extension の丸カッコの中に書き、メソッド本体は static を外した普通のインスタンスメソッドとして書きます。同じ要領で、ぜひ他の拡張メソッドも extension ブロックに書き換えてみてください。
Udemyでの動画版はこちらからご覧いただけます
00_はじめに
01_VisualStudio2026をインストールしてください
A01_fieldキーワード
B01_extensionブロックとは
B02_拡張メソッドとは
B03_extensionブロック
B04_型パラメータありの拡張メソッド
B05_型パラメータありのextensionブロックの書き方
B06_拡張プロパティ
B07_拡張静的プロパティ&メソッド
B08_拡張演算子
C01_partialコンストラクター
C02_幽霊コードを定義パーツで契約による実装をするという考え方
C03_partialイベント
D01_Null条件付き代入
E01_複合代入演算子のオーバーロード
F01_明示的な型を指定せずにラムダパラメータでパラメータ修飾子を使用する
G01_nameofはバインドされていないジェネリック型をサポートします
H01_SpanTおよびReadOnlySpanTのより暗黙的な変換
Udemyでの動画版はこちらからご覧いただけます