C#で演算子のオーバーロードを使ってみる

記事内に広告が含まれています。

今回はC#で演算子のオーバーロードを使ってみたいと思います。

C#のユーザー定義型のクラスや構造体(自分で定義したクラスや構造体)の+等の演算子をオーバーロードするとクラス同士を足したりすることが出来ます。

これが出来ると便利なのが自分で作成したクラスのインスタンス同士を+や-、++の演算子を使って独自の処理をさせることが出来ます。

スポンサーリンク

C#で演算子のオーバーロードを使ってみる

説明を見るだけだと分かり辛いので実際に簡単な例で演算子のオーバーロードを使ってみます。

上の場合はMyClassクラスでintValueフィールドを用意し、コンストラクタでクラスのインスタンス生成時に引数で受け取ったint型の値をフィールドのintValueに保持します。

またToStringメソッドのオーバーライドをしてクラスのインスタンスを表示するとintValueのフィールド値を返すようにしています(ToStringメソッドのオーバーライドは今回の演算子のオーバーロードとは何ら関係はありません)。

+演算子をMyClassクラスでオーバーロードしていて、その結果新しいMyClassクラスのインスタンスを返します。

演算子のオーバーロードの仕方

演算子をオーバーロードするにはpublic staticを付けたoperator 演算子名というメソッドに似た表記をして定義する必要があります。

先ほどの例では+演算子をoperatorキーワードを使って定義し引数で二つのMyClass型の変数を受け取ります・

2項演算子の+は二つの数を足す演算子(例えば1 + 1)なので二つの引数を受け取るようにし、必ず一つは自身の型であるMyClassを受け取るようにしなければいけません。

例えば+演算子の引数は以下のように必ず一方がMyClass型の引数を受け取れるようにします。

サンプルを実行するとMyClassの+演算子をオーバーロードしているので、MyClass型のmc1とmc2を足すと新しいMyClass型のインスタンスを返しmc3に入れます。

それをDebug.Logで出力するとToStringメソッドをオーバーライドしているのでMyClassのintValueの値がコンソールに出力されます。

いくつかの演算子のオーバーロードをしてみる

サンプルでMyClassの+演算子をオーバーロードして確認が出来たので、新しくSwordClassクラスを作成し、様々な演算子のオーバーロードをするサンプルを作成してみます。

SwordClassの演算子のオーバーロードをしていますが、中身としてはあまり意味のないものです。(^_^;)

SwordClassは剣の名前を表すNameプロパティと剣の強さを表すAttackPowerプロパティを持ち、インスタンスを生成する時にコンストラクタで初期値を設定します。

単項演算子のいくつかと2項演算子のいくつかをオーバーロードしています。

確認する為のクラスは以下のようにしました。

ユーザー定義の条件付き論理演算子のオーバーロード

&&や||は直接オーバーロードが出来ないので、&と|、true、falseの演算子をそれぞれオーバーロードし実現させます。

ここら辺はC#ガイドのユーザー定義の条件付き論理演算子を参照してください。

Expressions - C# language specification
This chapter covers operators and expressions. Expressions form several groups, including primary expressions, unary ope...

&&演算子

C#ガイドを見ると&&の評価は以下のようにされます。

x && y は T.false(x) ? x : T.&(x, y)

なのでクラス等のfalse演算子のオーバーロードにx(クラスのインスタンス)を渡して評価し、それが真であればx、そうでなければそのクラス等の&演算子のオーバーロードにxとy(クラスのインスタンス)を渡し評価した結果を返します。

なので&&を使うにはtrue、false、&の演算子のオーバーロードを行う必要があります。

確認の為、簡単なサンプルを作成します。

MyClassではインスタンス生成の時に引数に数値が渡された時はそれをフィールドのintValueに入れます(設定されていなければデフォルト値0を入れる)。

true演算子のオーバーロードで引数で受け取ったMyClassのintValueフィールドが0より大きければtrueを返します。

ここは分かり辛いですが、true演算子が実行された時にmc.intValueが0より大きいか判定し、大きければtrueを返し、大きくなければfalseを返すという事です。

false演算子のオーバーロードでは引数で受け取ったMyClassのインスタンスのintValueフィールドの値が0以下であればtrueを返します。

&演算子のオーバーロードでは引数で受け取った二つのMyClassのインスタンスのintValueフィールド値のビット毎のANDを計算し、それを引数として渡してMyClassインスタンスを生成し返しています。

ビット毎のANDは例えば3は2進数で表すと0011、14は2進数で表すと1110なので

0011
1110

のビット毎のAND(同じ桁が両方1の時1)は

0010

となり、これを10進数に戻すと0×2×3+0×2×2+1×2×1+0×1なので2となります。

サンプルで見ていくと、mc1 && mc2は

MyClass.false(mc1) ? mc1 : MyClass.&(mc1, mc2)

の評価になるので、MyClass.false(mc1)はfalseのオーバーロードにmc1を引数として渡してmc1のintValueが0なので結果trueが返ります。

MyClass.false(mc1)がtrueなのでmc1を実行します。

mc1でmc1.ToString()が実行されるので、0が結果として求められます。

mc2 && mc3は

MyClass.false(mc2) ? mc2 : MyClass.&(mc2, mc3)

となりMyClass.false(mc2)はfalseのオーバーロードにmc2を引数として渡してmc2のintValueが14なので結果falseが返ります。

MyClass.false(mc2)がfalseなのでMyClass.&(mc2, mc3)を実行します。

&演算子のオーバーロードでmc2とmc3のintValueフィールドのビット毎のANDを引数に新しくMyClassインスタンスを生成してそれを返しているので、new MyClass(2)をしたのと同じ結果が得られます。

||演算子

||の評価は以下のようにされます。

x || y は T.true(x) ? x : T.|(x, y)

&&演算子と||演算子のサンプルは特に有用性はありません・・・・(._.)

他にもたくさんオーバーロード出来る演算子はありますが、参考サイトのC#リファレンスを参照してください。

参考サイト

演算子のオーバーロード (C# リファレンス)

タイトルとURLをコピーしました