C#では、C/C++のように型のキャスト(変換)が可能です。
キャストのための演算子としてimplicitとexplicitという変換演算子があります。
英単語としては、下記の意味があります。
| implicit | 暗黙 |
| explicit | 明白な |
準備
2つの演算子を使った相互変換を行うクラスとして
メートルの2次元データクラス(Meterクラス)と、ミリメーターの2次元データクラス(MilliMeterクラス)を作成して実験をしてみます。
Meterクラス
public class Meter
{
public double X; // X方向データ(単位:メートル)
public double Y; // Y方向データ(単位:メートル)
public Meter()
{
// デフォルトコンストラクタ
}
public Meter(double x, double y)
{
// 引数付きコンストラクタ
this.X = x;
this.Y = y;
}
}
MilliMeterクラス
public class MilliMeter
{
public double X; // X方向データ(単位:ミリメートル)
public double Y; // Y方向データ(単位:ミリメートル)
public MilliMeter()
{
// デフォルトコンストラクタ
}
public MilliMeter(long x, long y)
{
// 引数付きコンストラクタ
this.X = x;
this.Y = y;
}
}
implicit 変換演算子
implicit 変換演算子は、実装しているクラスを「別の型(クラス)」に変換するための実装を行います。
Meterクラスを使って、implicit 演算子を実装してみます。
implicit 変換演算子には、「MeterクラスをMilliMeterクラスに変換するための処理」を記述します。
ですので、戻り値は’MilliMeter’型、引数は’Meter’型となります。
Meterクラスのコードは下記のようになります。
public class Meter
{
public double X; // X方向データ(単位:メートル)
public double Y; // Y方向データ(単位:メートル)
public Meter()
{
// デフォルトコンストラクタ
}
public Meter(double x, double y)
{
// 引数付きコンストラクタ
this.X = x;
this.Y = y;
}
public static implicit operator MilliMeter(Meter d)
{
// MilliMeterクラスへの変換(メートルからミリメートルへの変換)
return new MilliMeter((long)(d.X * 1000.0), (long)(d.Y * 1000.0));
}
}
プログラムの実装は下記のようになります。
static void Main(string[] args)
{
// メートルからミリメートルに変換します
Meter data = new Meter(0.1, 0.2); // Xが10cm、Yが20cm
MilliMeter data2 = (MilliMeter)data; // <-- ここでimplicit変換演算子が呼び出されます
Console.WriteLine(string.Format("X={0}({2}) Y={1}({2})", data2.X, data2.Y, "mm"));
}
このプログラムを実行すると結果は、
X=100(mm) Y=200(mm)
と表示されます。
explicit 変換演算子
explicit 変換演算子は、「別の型(クラス)」を実装しているクラスの型に変換するための実装を行います。
MilliMeterクラスを使ってexplicit 演算子を実装してみます。
explicit 変換演算子には、「MilliMeterクラスをMeterクラスに変換するための処理」を記述します。
ですので、戻り値は’Meter’型、引数は’MilliMeter’型となります。
コードは下記のようになります。
public class MilliMeter
{
public double X; // X方向データ(単位:ミリメートル)
public double Y; // Y方向データ(単位:ミリメートル)
public MilliMeter()
{
// デフォルトコンストラクタ
}
public MilliMeter(long x, long y)
{
// 引数付きコンストラクタ
this.X = x;
this.Y = y;
}
public static explicit operator Meter(MilliMeter d)
{
// Meterクラスへの変換(ミリメートルからメートルへの変換)
return new Meter(((double)d.X / 1000.0), ((double)d.Y / 1000.0));
}
}
プログラムの実装は下記のようになります。
static void Test2(string[] args)
{
// ミリメートルからメートルに変換します
MilliMeter data = new MilliMeter(100, 200); // Xが10cm、Yが20cm
Meter data2 = (Meter)data; // <-- ここでexplicit変換演算子が呼び出されます
Console.WriteLine(string.Format("X={0}({2}) Y={1}({2})", data2.X, data2.Y, "m"));
}
このプログラムを実行すると結果は、
X=0.1(m) Y=0.2(m)
と表示されます。
ちなみに・・・
今回の例に出てきた片方のクラスに、implicit 変換演算子と explicit 変換演算子の両方を実装するとどうなるか、試してみました。
Meterクラスに実装してみました。
public class Meter
{
public double X; // X方向データ(単位:メートル)
public double Y; // Y方向データ(単位:メートル)
public Meter()
{
// デフォルトコンストラクタ
}
public Meter(double x, double y)
{
// 引数付きコンストラクタ
this.X = x;
this.Y = y;
}
public static implicit operator MilliMeter(Meter d)
{
// MilliMeterクラスへの変換(メートルからミリメートルへの変換)
return new MilliMeter((long)(d.X * 1000.0), (long)(d.Y * 1000.0));
}
public static explicit operator Meter(MilliMeter d)
{
// Meterクラスへの変換(ミリメートルからメートルへの変換)
return new Meter(((double)d.X / 1000.0), ((double)d.Y / 1000.0));
}
}
実行するまでもなく、エラーになりました。
エラー CS0457 ‘MilliMeter’ から ‘Meter’ へ変換するときの、あいまいなユーザー定義の変換 ‘MilliMeter.explicit operator Meter(MilliMeter)’ および ‘Meter.explicit operator Meter(MilliMeter)’ です。

