extension ブロックでは、メソッドやプロパティだけでなく、演算子のオーバーロードも書くことができます。まずは通常のクラスに対する演算子のオーバーロードの書き方を確認し、その後で extension ブロックに書き換える流れを見ていきます。
演算子のオーバーロードとは
クラスに対して演算子を追加しておくことを、演算子のオーバーロードと呼びます。例えば次のような Money クラスを考えます。
public class Money
{
public int Value { get; set; }
}
この Money クラスのインスタンスを2つ作成し、それぞれの Value に値を入れます。
var m1 = new Money(); m1.Value = 111; var m2 = new Money(); m2.Value = 222;
図1 Money クラス(Value プロパティのみ)
この状態で m1 + m2 のように m1 と m2 を足すことはできません。「何を足すのか」がコンパイラに定義されていないため、コンパイルエラーになります。
図2 m1 + m2 はコンパイルエラーになる
演算子のオーバーロードを定義する
ここに演算子のオーバーロードを定義しておけば、「足すとはこういう処理をすること」をあらかじめ書いておくことができます。書き方は public static で戻り値の型を書き、続けて operator キーワードと演算子を書きます。今回は + 演算子を定義します。
public static int operator +(Money a, Money b)
{
}
図3 operator +(Money a, Money b) のシグネチャ
+ 演算子が使われたときにどのような処理をするかを、このメソッドの中に書いていきます。今回は Money の a と b を受け取り、それぞれの Value 同士を足したものを返すようにします。
public static int operator +(Money a, Money b)
{
return a.Value + b.Value;
}
図4 a.Value と b.Value を足して返す実装
m1 + m2 のとき、m1 が引数 a に、m2 が引数 b になります。つまり「a に b が足されたときは Value 同士を足してね」という定義です。これでコンパイルエラーは解消され、m1 + m2 の結果を mm に代入する次のコードが実行できるようになります。
var mm = m1 + m2;
デバッグ実行して mm の値を確認すると、333 になっています。m1.Value(111)と m2.Value(222)を足した結果が正しく返っていることが分かります。
図5 デバッグ実行で mm の値が 333 になることを確認
なお、戻り値の型は int でなければならないわけではありません。a の Value と b の Value を足した値で新しく Money クラスのインスタンスを作り、それを返却するといった実装にすることもできます。
extension ブロックで書く
ここまでは Money クラスを自分で作っていたので、演算子のオーバーロードを直接クラスに書くことができました。しかしこれがマイクロソフトのクラスライブラリやサードパーティのクラス、あるいは自分たちが作ったものでも DLL を参照しているようなものなど、変更できないコードだった場合は、このようには書けません。
そのような変更できないコードに対して拡張したい場合は、この演算子のオーバーロードも extension ブロックの中に書くことができます。引数を Money にした extension ブロックを用意し、その中に先ほどと同じ内容をそのまま書きます。
extension(Money money)
{
public static int operator +(Money a, Money b)
{
return a.Value + b.Value;
}
}
図6 extension(Money money) ブロックを新設
図7 extension ブロック内に operator + を実装した状態
Money クラス側に書いていた演算子のオーバーロードは削除していますが、これでもコンパイルは通ります。実行すると、こちらも 333 という結果になり、extension ブロックの中に書いた演算子オーバーロードがちゃんと動作していることが分かります。
図8 extension ブロック版でも同じ結果(333)になることを確認
このように、演算子のオーバーロードも 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での動画版はこちらからご覧いただけます