using System;
public class Test
{
// コンパイルエラー。whereなしではジェネリック型に演算子を適用できない。
//static void f<T>(T x, T y) {
// Console.WriteLine(x == y ? "OK" : "NG");
//}
// where で参照型だけに制限すれば演算子が使えるが、object.== が呼ばれる
static void f<T>(T x, T y) where T: class {
Console.WriteLine(x == y ? "OK" : "NG");
Console.WriteLine("変数の型:" + typeof(T).Name + " / 値の型:" + x.GetType().Name);
}
// 明示的に ClassA に制約すれば、そのクラスの == が呼ばれる
static void g<T>(T x, T y) where T: ClassA {
Console.WriteLine(x == y ? "OK" : "NG");
Console.WriteLine("変数の型:" + typeof(T).Name + " / 値の型:" + x.GetType().Name);
}
// dynamic を使う場合
static void h(dynamic x, dynamic y) {
Console.WriteLine(x == y ? "OK" : "NG");
Console.WriteLine("値の型:" + x.GetType().Name);
}
// 普通は演算子を使わずに object.Equals() を使うべき
static void f1(object x, object y) {
Console.WriteLine(object.Equals(x, y) ? "OK" : "NG");
Console.WriteLine("値の型:" + x.GetType().Name);
}
static void Main(string[] args)
{
var x = new ClassA(1);
var y = new ClassA(1);
f(x, y); // NG <= objectクラスの == を呼ぶようコンパイルされるため
g(x, y); // OK
h(x, y); // OK
f1(x, y); // OK
}
class ClassA
{
public int Value1 { get; protected set; }
// コンストラクタ
public ClassA(int val) { Value1 = val; }
// Equals()をオーバーライド
public override bool Equals(object other)
{
Console.WriteLine("ClassA の Equals が呼ばれました。");
var other1 = other as ClassA;
if (object.ReferenceEquals(other1, null)) return false;
return object.Equals(this.Value1, other1.Value1);
}
// Equals() が True になる場合は GetHashCode() も同じ値を返す必要がある
public override int GetHashCode()
{
return Value1.GetHashCode();
}
// == 演算子を定義
public static bool operator==(ClassA self, ClassA other)
{
Console.WriteLine("ClassA の == が呼ばれました。");
return object.Equals(self.Value1, other.Value1);
}
// == を定義するためには != もペアで定義が必要
public static bool operator!=(ClassA self, ClassA other)
{
return !(self == other);
}
}
}